10813

PropertyChangeSupport and equals method

Question:

I'll try to explain my problem as clear as possible :). I am using PropertyChangeSupport to notify registered views for changes in the properties. One of the property is an object which properties are changed every view seconds. I don't want to create for this particular object new instance every time it is being updated (for the propertychangelistener to notice the change), so I wrote my own equals method where I ommit the comparation to itself.

@Override public boolean equals(Object item) { // do not compare // if (this == item) { return true; } if (!(item instanceof TransferQueueItem) || item == null) { return false; } TransferQueueItem newItem = (TransferQueueItem) item; boolean value = // ommited... properties comparation return value; }

Unfortunatelly that doesn't have the effect I was looking for. If I create a copy of the object and fire the property change method on it, then it works fine.

What am I missing here?

-- Edit

I realized, that since I am using the same instance and not a copy of it, the properties are pointig the same place, thus the comparation would always come out true. Is there a workaround to that (besides creating a copy). Or how bad is to create a copy of an object every second, eg.

Answer1:

You must always return true to tell PropertyChangeSupport that your object did <em>not</em> change. But that means equals() is broken for all objects of this class (so you can't use them in sets or maps anymore, for example).

A better way would be to have a special method firePropertyChange() for this kind of object which does the special handling. This way, you can even avoid to create an instance of PropertyChangeEvent, too. Here is an example for handling BigDecimal (where equals() doesn't work at all):

protected transient PropertyChangeSupport changeSupport = null; public void addPropertyChangeListener (String propertyName, PropertyChangeListener listener) { if (changeSupport == null) changeSupport = new PropertyChangeSupport (this); changeSupport.addPropertyChangeListener (propertyName, listener); } public void firePropertyChange (String propertyName, BigDecimal oldValue, BigDecimal newValue) { if (changeSupport == null) return; if (oldValue != null && newValue != null && oldValue.compareTo (newValue) == 0) { return; } changeSupport.firePropertyChange(new PropertyChangeEvent(this, propertyName, oldValue, newValue)); }

[EDIT] What you do is something else entirely: You have a parent and a child and you want listeners of the <em>parent</em> to receive events when the <em>child</em> changes.

The correct approach here is to add PropertyChangeSupport to the <em>child</em>. When the child is added to the parent, the parent must install the necessary listeners in the child. When an event is fired, it must fire a second event which informs the listeners of the <em>parent</em> of the change in the <em>child</em> (the parent must forward the events).

Answer2:

this is a case of chained propertychangelisteners:

TransferQueueItem should launch their own PropertychangeEvents which must be listened by the TransferQueue in which is inserted

And in response TransferQueue must notify their listeners that an owned item has changed.

Every time i have a problem like this in which an object must relaunch events i use this convention (of my work team):

1 An object can only launch events which source is itself.

2 If it want delegate event it launchs an event like this: new PropertyChangeEvent(this,"DELEGATED_EVENT", null, receivedEvent). So that the listeners can follow the chain of events.

Addicionally i have a static method in an Util class which follow the events chain and returns the very first event, the one whick property is not "DELEGATED_EVENT"

Recommend

  • Write and execute excel VB macro with win32com.client
  • How to handle javascript on page with thousands of checkboxes in IE6
  • CRM 2011 - N:N (Many-To-Many) Linq Issue
  • JSON convert Map with Integer keys
  • webstorm autocomplete for require(.json)
  • PHP: Overriding parent methods with __call
  • Best Way to create configuration file(config.php) php
  • how to use view.setX() method in android version less then 3.0
  • How to write numpy arrays to .txt file, starting at a certain line? numpy version 1.6
  • R colors - many distinctive colors that are still pretty
  • How to prevent TreeItem selection?
  • TFS edit build log using custom activity
  • Chrome breakpoint on radio doesn't fire
  • CKeditor stripping font tags instead of converting to span
  • Ionic Slide Up Slide Down Animation for only one view in sidebar
  • Symfony2 - Doctrine - no changeset in post update
  • Android onKey w/ virtual keyboard
  • How do I Dispose a HttpResponseMessage in my Web Api Method?
  • LESS CSS how to modify parent property in mixin
  • Most efficient way to move table rows from one table to another
  • Prevent Tomcat from caching request during starup
  • std::remove_copy_if_ valgrind bytes in block are possibly lost in loss record
  • Functions in global context
  • Meteor helpers not available in Angular template
  • Sony Xperia Z Tablet not found by adb
  • How to recover from a Spring Social ExpiredAuthorizationException
  • ILMerge & Keep Assembly Name
  • Large data - storage and query
  • How can I estimate amount of memory left with calling System.gc()?
  • WOWZA + RTMP + HTML5 Playback?
  • XCode can't find symbols for a specific iOS library/framework project
  • Hits per day in Google Big Query
  • Why joiner is not used after Sequence generator or Update statergy
  • Exception on Android 4.0 `android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode)`
  • File not found error Google Drive API
  • Is it possible to post an object from jquery to bottle.py?
  • sending mail using smtp is too slow
  • Busy indicator not showing up in wpf window [duplicate]
  • Why is Django giving me: 'first_name' is an invalid keyword argument for this function?
  • How can I use `wmic` in a Windows PE script?