JDK-4212311 : java.util.Observable.notifyObservers() doesn't conform to api
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util
  • Affected Version: 1.1.7
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 1999-02-17
  • Updated: 2016-05-31
  • Resolved: 2016-04-20
Related Reports
Relates :  
Description

Name: dbT83986			Date: 02/17/99


The java api states the notifyObservers() checks to see 
if hasChanged(), notifies the observers, and then calls 
clearChanged().  However, in reality, it constructs an 
array of Observers to notify, then calls clearChanged, 
then notifies the controllers. 

This is a codelet from java.util.notifyObservers():

   synchronized (this) {
	    /* We don't want the Observer doing callbacks into
	     * into arbitrary code while holding its own Monitor.
	     * The code where we extract each Observable from 
	     * the Vector and store the state of the Observer
	     * needs synchronization, but notifying observers
	     * does not (should not).  The worst result of any 
	     * potential race-condition here is that:
	     * 1) a newly-added Observer will miss a
	     *   notification in progress
	     * 2) a recently unregistered Observer will be
	     *   wrongly notified when it doesn't care
	     */
	    if (!hasChanged())
		return;
	    size = obs.size();
	    if (size > arr.length) {
		arr = new Observer[size];
	    }
	    obs.copyInto(arr);
	    clearChanged();
	}

	for (int i = size -1; i>=0; i--) {
	    if (arr[i] != null) {
		arr[i].update(this, arg);
	    }
	}

In my program, I needed to know exactly what changed so I have
private variables to indicate what changed.  Each observer
checks these statuses if they are notified.  I overrode 
clearChanged() to set these statuses back assuming that they
would be cleared AFTER the controllers were actually notified
and not before.

public void clearChanged()
{
	super.clearChanged();
	mSectorDisplayChanged = false;
	mAccountDisplayChanged = false;
	mGroupDisplayChanged = false;
}
(Review ID: 48263)
======================================================================

Comments
There is probably old code out there that depends on this exact sequence of operations, so this can't be "fixed" without breaking other code. Observer and Observable will be deprecated. See JDK-8154801. Closing this bug as Won't Fix.
20-04-2016

WORK AROUND Name: dbT83986 Date: 02/17/99 There are two work arounds for my application: 1) If only one observer cares about each status, then it's easy enough to do separate sets for each and have the observer set them back. Messy, but easy. I only have three statuses now but I will have about 50 when I'm done. 2) Make each status an Observable. Equally messy once I have 50 of them. Especially since these changes are all interrelated. ======================================================================
08-09-2004