Integer and int are not equal... Especially if received via JSNI

439 views
Skip to first unread message

pash7ka

unread,
Sep 14, 2012, 11:10:12 PM9/14/12
to google-we...@googlegroups.com
I've spent a huge amount of time trying to find the source of one strange bug in my app, so I want to share what I've found.
First I should say I'm using GWT 2.3 currently, so i don't know if the described behavior changed in latest version.

My app is receiving some data from my server, displays it and after some user actions send something from this data back to the server.
I’ve used standart GWT RPC for this data exchange and everything was fine.
Then we decided to receive that data via JSON requests and here my trubles started: trying to send data back to the server (with the old GWT RPC method) throwed the com.google.gwt.user.client.rpc.SerializationException: undefined at Unknown.anonymous(Unknown Source).

Well, I’m not going to tell all the steps how I’ve found the problem, just the result.
My data class looks like this: 
public final class MyDataObj  extends JavaScriptObject {
//… NoArgs constructor and other stuff
public final native Ineger getMyDataVal() /*-{ return this.myDataVal; }-*/;
}

I’ve used Integer and not int here because null value is perfectly valid here and has its own meaning.
But in JSON this was a normal JavaScript integer or the absence of the property.
It was fine. Just until GWT had to serialize this Integer for RPC. Or until I’ve tried to use toString() or intValue() on it. That fails, since this was not an Integer.

Thomas Broyer

unread,
Sep 15, 2012, 3:55:40 AM9/15/12
to google-we...@googlegroups.com
JSNI doesn't do auto-boxing/unboxing at Java/JS boundaries, i.e. an Integer is an opaque object in JS (typeof == 'object'), not a JS Number.

You have to change your JSNI method to:
native Integer getMyDataVal() /*-{ this.myDataVal == null ? null : @java.lang.Integer::validOf(I)(this.myDataVal); }-*/;
or change your API to have an hasMyDataVal():boolean and getMyDataVal()int:
native boolean hasMyDataVal() /*-{ return this.myDataVal != null; }-*/;
native int getMyDataVal() /*-{ return this.myDataVal; }-*/;

BTW, your code as it is today should throw in DevMode, so I suppose you only tested it in prod mode?

pash7ka

unread,
Sep 17, 2012, 5:17:17 AM9/17/12
to google-we...@googlegroups.com
Yes, this manual boxing is what i did to solve this.

I don't use DevMode because it's a bit difficult to configure my environment for it: i use JBoss as my app server and the app is deployed via .ear archive with some other modules it needs to work... I'm sure it's possible to configure somehow, just i didn't need it. :)

Thomas Broyer

unread,
Sep 17, 2012, 6:53:51 AM9/17/12
to google-we...@googlegroups.com


On Monday, September 17, 2012 11:17:17 AM UTC+2, pash7ka wrote:
Yes, this manual boxing is what i did to solve this.

I don't use DevMode because it's a bit difficult to configure my environment for it: i use JBoss as my app server and the app is deployed via .ear archive with some other modules it needs to work... I'm sure it's possible to configure somehow, just i didn't need it. :)

Reply all
Reply to author
Forward
0 new messages