My favorites | Sign in
Google
                
New issue | Search
for
| Advanced search | Search tips
Issue 4177: Code works in hosted mode but fails once compiled to javascript
3 people starred this issue and may be notified of changes. Back to list
Status:  Fixed
Owner:  rice+legacy@google.com
Milestone-2_0_RC1


Sign in to add a comment
 
Reported by mbwoody, Oct 28, 2009
Found in GWT Release 1.7
Encountered on Win Vista / IE7, FireFox 3, Chrome

Description:
I encountered a situation where code works fine in hosted mode but fails
when compiled and ran from a real browser.  I subclassed an array list to
add change notification.  In the constructor that accepts a Collection<>, I
initalize an ArrayList of _listeners.  

When running in Java, this code compiles and runs fine.  When compiled to
javascript, I get a null error.  The problem is that the ArrayList
implementation in GWT appears to call on an inner method to perform the
add.  This method attempts to check the _listeners collection.  Since the
_listener collection was null, it failed.  My code was easy to fix, but it
was a frustrating bug to deal with since it worked fine in hosted mode.


Sample Code:
public class ObservableList<E> extends ArrayList<E>{

   ArrayList<Listener<BaseEvent>> _listeners;
   
   public ObservableList(Collection<? extends E> collection){
       super(collection);
       _listeners = new ArrayList<Listener<BaseEvent>>();
   }

   ...
   
   public boolean addAll(Collection<? extends E> arg0){
        boolean r = super.addAll(arg0);
        onCollectionChange(arg0);
        return r;
   }

   ...
   
   private void onCollectionChange(Collection arg0){
       for(int i=0; i<_listeners.size(); i++)
          ...  
       //GWT hits this code after constructor.  Java does not.
   }


Workaround:
check for _listeners == null in the onCollectionChange method





Comment 1 by rice+legacy@google.com, Nov 03, 2009
The GWT translatable implementation happens to implement the constructor
ArrayList(Collection) by calling ArrayList.addAll(), whereas the Sun JDK does not. 
But Sun's implementation could change at any time, so I don't think it's correct to
depend on this behavior.  The issue is that your subclass doesn't have its listeners
in place at the time you call super(collection).  You could fix this by initializing
_listeners at the point it is declared, or by calling 'super(); _listeners = ...;
addAll(collection)'.  Checking for _listeners == null in onCollectionChange would
prevent the null reference but would have different semantics since the listeners
would not be called for the initial collection.

In general, the process of initializing subclasses in Java can reveal certain details
of the superclass implementation that are rarely specified as fully as one would
like.  In such a case, it's impossible to guarantee that the GWT implementation will
never be distinguishable from another implementation such as the Sun JDK.

Comment 2 by rice+legacy@google.com, Nov 03, 2009
On further thought, it seems worth avoiding calling overridable methods from
constructors of commonly subclassed classes like ArrayList.  I'm working on a fix for
this specific case.

Status: Accepted
Owner: r...@google.com
Comment 3 by rice+legacy@google.com, Nov 10, 2009
Fix in r6609.  The ArrayList constructors no longer call any other methods that might
be overridden by a subclass.

Status: FixedNotReleased
Comment 4 by br...@google.com, Nov 15, 2009
This change was made as part of a bulk edit, so not 100% sure all these 
weren't shipped prior to 2.0 RC.
Labels: Milestone-2_0_RC1
Comment 5 by cramsdale@google.com, Nov 23, 2009
(No comment was entered for this change.)
Status: Fixed
Sign in to add a comment