PUBLIC OBJECT

Implementing Observers with Stateless Properties

I've got a simplified Property interface and a mixin that makes the property observable:

public interface Property<B,V> {
  V get(B bean);
  void set(B bean, V value);
}

public interface ObservableProperty<B,V> extends Property <B,V> {
  void addPropertyChangeListener(B bean, PropertyChangeListener p);
  void removePropertyChangeListener(B bean, PropertyChangeListener p);
}`</pre>For most use cases, the interface is implemented by a library. For example, this instance uses the getters and setters:
<pre>`  ObservableProperty p = new BeanProperty(Customer.class, "address");`</pre>Today I'm interested in the implementation of this interface. Here's a very straightforward implementation that doesn't even need reflection - getting the `Document` property from a `JTextField`:
<pre class="prettyprint">`public class JTextFieldDocumentProperty 
    implements ObservableProperty&lt;JTextField, Document&gt; {

  public Document get(JTextField bean) {
    return bean.getDocument();
  }

  public void set(JTextField bean, Document value) {
    bean.setDocument(value);
  }

  public void addPropertyChangeListener(JTextField bean, PropertyChangeListener p) {
    bean.addPropertyChangeListener("document", p);
  }

  public void removePropertyChangeListener(JTextField bean, PropertyChangeListener p) {
    bean.removePropertyChangeListener("document", p);
  }
}`</pre>This code is deceivingly simple because the listener types in the Property interface (`PropertyChangeListener`) exactly match the listener types in the bean. Things get a much more interesting if the listener types are different.

**Using an adapter**
The natural solution is to code the `addPropertyChangeListener` to use a simple adapter to convert events of one type to events of another type. This adapter converts between `[DocumentListener](http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/event/DocumentListener.html)` and `[PropertyChangeListener](http://java.sun.com/j2se/1.4.2/docs/api/java/beans/PropertyChangeListener.html)`:
<pre class="prettyprint">`private class DocumentToPropertyChangeListener
    implements DocumentListener {
  private String currentText;
  private final Document document;
  private final PropertyChangeListener delegate;

  public DocumentToPropertyChangeListener(Document bean, PropertyChangeListener p) {
    this.document = bean;
    this.delegate = p;
    this.currentText = getDocumentText();
  }

  private String getDocumentText() {
    try {
      return document.getText(0, document.getLength());
    } catch (BadLocationException e) {
      throw new RuntimeException(e);
    }
  }

  public void insertUpdate(DocumentEvent e) {
    fireChanged();
  }
  public void removeUpdate(DocumentEvent e) {
    fireChanged();
  }
  public void changedUpdate(DocumentEvent e) {
    fireChanged();
  }
  public void fireChanged() {
    String oldText = currentText;
    currentText = getDocumentText();
    delegate.propertyChange(
        new PropertyChangeEvent(document, "text", oldText, currentText));
  }
}`</pre>As you can see, the `Document` class is a bit cumbersome to use. But this interface correctly adapts the listener types. Unfortunately, we still have the trickiest problem ahead of us...

**The problem with removePropertyChangeListener()**
In my second example, I'll implement Property for the text of a `[Document](http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/text/Document.html)`. The implementation of `addPropertyChangeListener` is easy; we just create the adapter inline:
<pre class="prettyprint">`public class DocumentTextProperty 
    implements StatelessProperty&lt;Document, String&gt; {
  ...
  public void addPropertyChangeListener(Document bean, PropertyChangeListener p) {
    bean.addDocumentListener(_new DocumentToPropertyChangeListener(bean, p)_);
  }
  public void removePropertyChangeListener(Document bean, PropertyChangeListener p) {
    ...
  }
}`</pre>But how does remove work? There's a big problem - we didn't save a reference to our adapter! We need to recover that reference somehow so we can remove the same adapter that was added.

The `Document` interface doesn't expose its listeners; ie. there's no `getDocumentListeners()` method. So we can't just iterate over the document's listeners to find the matching adapter.

If we store a reference to the adapter in the `DocumentTextProperty` object, then we'll almost certainly have a memory leak. Even if we stored just a `WeakReference&lt;DocumentTextProperty&gt;`, it would make our Property stateful. In the ideal implementation, any two instances of the same property should be interchangeable. For example, we shouldn't force the user to store a reference to the Property instance. This code should work fine but it won't work if the property is stateful:
<pre class="prettyprint">`  public void installListeners() {
    new DocumentTextProperty().addPropertyChangeListener(
        myDocument, myPropertyChangeListener);
  }
  ...
  public void shutdown() {
    new DocumentTextProperty().removePropertyChangeListener(
        myDocument, myPropertyChangeListener);
  }
`</pre>
The next option is to store this state in a static global registry. This is the approach taken by the [bean-properties](https://bean-properties.dev.java.net/) Java.net project. I don't like this approach because it feels very heavyweight:
<li>It needs `WeakReferences`.
</li><li>The shared registry requires synchronization.
</li><li>There's memory overhead to store each registered bean/listener pair.
</li><li>The registry is complex because it requires each listener pair to be uniquely identified.
</li><li>It prevents bean/listener pairs from being serialized.

Fortunately, there is a clever solution to this problem - don't store a reference to the adapter. Instead, when we call `removePropertyChangeListener`, we pass in a different instance that [equals](http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)) the first:
<pre class="prettyprint">`public class DocumentTextProperty 
    implements StatelessProperty&lt;Document, String&gt; {
  ...
  public void addPropertyChangeListener(Document bean, PropertyChangeListener p) {
    bean.addDocumentListener(new DocumentToPropertyChangeListener(bean, p));
  }
  public void removePropertyChangeListener(Document bean, PropertyChangeListener p) {
    bean.removeDocumentListener(_new DocumentToPropertyChangeListener(bean, p)_);
  }
}`</pre>This requires us to implement `equals` and `hashCode` in our adapter:
<pre class="prettyprint">`private class DocumentToPropertyChangeListener 
    implements DocumentListener {
  public boolean equals(Object obj) {
    return obj != null
      && obj.getClass() == this.getClass()
      && ((DocumentToPropertyChangeListener) obj).delegate.equals(delegate)
      && ((DocumentToPropertyChangeListener) obj).document.equals(document);
  }
  public int hashCode() {
    return delegate.hashCode() * 37 + document.hashCode();
  }
}

I love equals()
We've taken advantage of one of Java's greatest features: a strong concept of equality. It makes our solution stateless, immutable, serializable, efficient and easy to use.