| 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 |
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
|
|
,
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. |
|
,
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 |
|
,
Nov 10, 2009
Fix in r6609. The ArrayList constructors no longer call any other methods that might be overridden by a subclass.
Status: FixedNotReleased
|
|
,
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
|
|
,
Nov 23, 2009
(No comment was entered for this change.)
Status: Fixed
|
|
|
|