gwtproject / gwt

GWT Open Source Project
http://www.gwtproject.org
1.53k stars 378 forks source link

GWT Serialization issue #4263

Closed dankurka closed 9 years ago

dankurka commented 9 years ago

Originally reported on Google Code with ID 4263

Found in GWT Release (e.g. 1.5.3, 1.6 RC):
1.7.1

Encountered on OS / Browser (e.g. WinXP, IE6-7, FF3):
All Tested (GAE, Windows Client FF, IE exc)

Detailed description (please be as specific as possible):
GWT Serialization croaks on the server deserialize

Shortest code snippet which demonstrates issue (please indicate where
actual result differs from expected result):

First of all I have written a test for Gwt Serialization, which seems
to tell me why things wouln't serialize with gwt.  I think it makes sense 
at some point to include this with GWT itself;
The code is here
http://cvs.adligo.org/viewvc/i_util_tests/src/org/adligo/i/util/IsGwtRpcSer
ializable.java?view=markup

Second I am having a issue serializeing 

http://cvs.adligo.org/viewvc/models_core_relations/src/org/adligo/models/co
re/relations/client/rpc/transfer/UserSaveRequest.java?view=markup

It works in the gwt hosted mode, but breaks when I compile and browse.  I 
have copied the error from the google app engine.

[adligo1099/v0-0-7.337913742591040381].<stdout>: log4jxml Runtime Network 
Thread [DEBUG] AdiControllerServlet - Entering processCall
("5|0|21|http://adligo1099.appspot.com/com.adligo.subsystems.ajws.Ajws/|F9C
8A8B28639718D5B10BB9E10802FEC|org.adligo.models.core.relations.client.rpc.U
serEditService|saveUser|org.adligo.models.core.relations.client.rpc.transfe
r.UserSaveRequest|org.adligo.models.core.relations.client.rpc.transfer.User
SaveRequest/2630981496|com.adligo.subsystems.ajws.client.view.vanilla.creat
eUser|org.adligo.models.core.relations.client.UserRelations/2799898142|org.
adligo.models.core.client.User/1219142781|org.adligo.models.core.client.Dom
ainName/1590040293|
[Ljava.lang.String;/2600011424|yourdomain|com|org.adligo.models.core.client
.NamedId/3646344511|yourdomain.com|org.adligo.models.core.client.EMail/2279
217716|9ci|9ci.com|ken@9ci.com|ken|password|1|2|3|4|1|5|6|7|8|0|0|0|0|9|10|
11|2|12|13|14|1908262|0|15|16|10|11|2|17|13|14|9622|0|18|14|207254|0|19|20|
1768522993081|0|20|21|")

I 11-21 10:09AM 49.305 [adligo1099/v0-0-7.337913742591040381].<stdout>: 
log4jxml Runtime Network Thread [ERROR] AdiControllerServlet - 
java.lang.NumberFormatException: For input string: "1768522993081" url 
is /com.adligo.subsystems.ajws.Ajws/do/UserEditService
 com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: 
java.lang.NumberFormatException: For input string: "1768522993081"
    at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:298)
    at org.adligo.i.adi.server.rpc.AdiControllerServlet.processCall
(AdiControllerServlet.java:156)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.doPost
(RemoteServiceServlet.java:86)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:713)
    at com.adligo.subsystems.asm.AsmServlet.service(SourceFile:150)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
    at org.adligo.i.adi.server.rpc.AdiControllerServlet.service
(AdiControllerServlet.java:127)
    at com.adligo.subsystems.asm.AsmServlet.service(SourceFile:126)
    at org.mortbay.jetty.servlet.ServletHolder.handle
(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter
(ServletHandler.java:1093)
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter
(SaveSessionFilter.java:35)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter
(ServletHandler.java:1084)
    at 
com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter
(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter
(ServletHandler.java:1084)
    at org.mortbay.jetty.servlet.ServletHandler.handle
(ServletHandler.java:360)
    at org.mortbay.jetty.security.SecurityHandler.handle
(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle
(SessionHandler.java:181)
    at org.mortbay.jetty.handler.ContextHandler.handle
(ContextHandler.java:712)
    at org.mortbay.jetty.webapp.WebAppContext.handle
(WebAppContext.java:405)
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle
(AppVersionHandlerMap.java:238)
    at org.mortbay.jetty.handler.HandlerWrapper.handle
(HandlerWrapper.java:139)
    at org.mortbay.jetty.Server.handle(Server.java:313)
    at org.mortbay.jetty.HttpConnection.handleRequest
(HttpConnection.java:506)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete
(HttpConnection.java:830)
    at 
com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable
(RpcRequestParser.java:76)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
    at 
com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceReques
t(JettyServletEngineAdapter.java:139)
    at com.google.apphosting.runtime.JavaRuntime.handleRequest
(JavaRuntime.java:239)
    at 
com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequ
est(RuntimePb.java:5135)
    at 
com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequ
est(RuntimePb.java:5133)
    at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest
(BlockingApplicationHandler.java:24)
    at com.google.net.rpc.impl.RpcUtil.runRpcInApplication
(RpcUtil.java:363)
    at com.google.net.rpc.impl.Server$2.run(Server.java:814)
    at com.google.tracing.LocalTraceSpanRunnable.run
(LocalTraceSpanRunnable.java:56)
    at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan
(LocalTraceSpanBuilder.java:516)
    at com.google.net.rpc.impl.Server.startRpc(Server.java:769)
    at com.google.net.rpc.impl.Server.processRequest(Server.java:351)
    at com.google.net.rpc.impl.ServerConnection.messageReceived
(ServerConnection.java:437)
    at com.google.net.rpc.impl.RpcConnection.parseMessages
(RpcConnection.java:319)
    at com.google.net.rpc.impl.RpcConnection.dataReceived
(RpcConnection.java:290)
    at com.google.net.async.Connection.handleReadEvent
(Connection.java:436)
    at com.google.net.async.EventDispatcher.processNetworkEvents
(EventDispatcher.java:762)
    at com.google.net.async.EventDispatcher.internalLoop
(EventDispatcher.java:207)
    at com.google.net.async.EventDispatcher.loop
(EventDispatcher.java:101)
    at com.google.net.rpc.RpcService.runUntilServerShutdown
(RpcService.java:251)
    at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run
(JavaRuntime.java:396)
    at java.lang.Thread.run(Unknown Source)
Caused by: com.google.gwt.user.client.rpc.SerializationException: 
java.lang.NumberFormatException: For input string: "1768522993081"
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lize(ServerSerializationStreamReader.java:524)
    at 
com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readO
bject(AbstractSerializationStreamReader.java:61)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader$ValueRe
ader$8.readValue(ServerSerializationStreamReader.java:131)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeValue(ServerSerializationStreamReader.java:372)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeClass(ServerSerializationStreamReader.java:575)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeImpl(ServerSerializationStreamReader.java:608)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lize(ServerSerializationStreamReader.java:502)
    at 
com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readO
bject(AbstractSerializationStreamReader.java:61)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader$ValueRe
ader$8.readValue(ServerSerializationStreamReader.java:131)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeValue(ServerSerializationStreamReader.java:372)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeClass(ServerSerializationStreamReader.java:575)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeImpl(ServerSerializationStreamReader.java:608)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lize(ServerSerializationStreamReader.java:502)
    at 
com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readO
bject(AbstractSerializationStreamReader.java:61)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader$ValueRe
ader$8.readValue(ServerSerializationStreamReader.java:131)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeValue(ServerSerializationStreamReader.java:372)
    at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:287)
    ... 46 more
Caused by: java.lang.NumberFormatException: For input 
string: "1768522993081"
    at java.lang.NumberFormatException.forInputString(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.readInt
(ServerSerializationStreamReader.java:461)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader$ValueRe
ader$6.readValue(ServerSerializationStreamReader.java:117)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeValue(ServerSerializationStreamReader.java:369)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeClass(ServerSerializationStreamReader.java:575)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lizeImpl(ServerSerializationStreamReader.java:608)
    at 
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deseria
lize(ServerSerializationStreamReader.java:502)
    ... 62 more

Workaround if you have one:

Links to relevant GWT Developer Forum posts:

Reported by adligo778 on 2009-11-21 18:24:39

dankurka commented 9 years ago
I believe I've tracked down the problem, based on the encoded RPC string you enclosed.
 The value 
'1768522993081' is intended to be the hashCode field of the org.adligo.models.core.client.User
class.  
However, its value is too large to fit into an int, so when ServerSerializationStreamReader.readInt
calls 
Integer.parseInt on it, a java.lang.NumberFormatException is thrown.

In GWT, client-side code represents Java 'int's using native JavaScript numbers, which
act more like Java 
'double's.  In the interest of performance, GWT does not attempt to emulate the way
int arithmetic 
handles overflow via wraparound.  Thus your User.genHashCode method ends up generating
different values 
in dev (hosted) mode versus prod (web) mode, and sometimes that values can't be passed
through RPC since 
the server-side code expects a true Java int.  The larger value is written out in decimal
representation as 1768522993081 and the server-side code chokes on it.

  There are two main workarounds I can think of: 

1) Add code to handle overflow such as 'result = result & 0xffffffff' after each computation
that could overflow 
32 bits.  If you do this correctly your hash code computation should be identical in
dev an dprod modes.  
Basically you would be forcing int emulation at specific places where it matters for
RPC.

2) Make dangerous fields like 'hashCode' transient, i.e., don't attempt to send them
via RPC.  Make the rest of 
the code generate the 'hashCode' field on demand, e.g, using code like 'if (hashCode
== 0) genHashCode();'. 
(one object in 32 billion or so will fail to benefit from caching). The hash codes
will be different on the client 
and server but as long as you don't 'pickle' any hash codes into collection objects
that get sent over RPC that 
shouldn't matter.  Each side will be self-consistent.

While the lack of integer wraparound is not a bug in GWT (since GWT explicitly chooses
not to emulate it), 
the way this behavior interacts with RPC seems like a trouble spot within GWT and we
will give some thought 
as to how the experience for code similar to yours could be improved.

Reported by rice@google.com on 2009-12-01 19:26:13

dankurka commented 9 years ago

Reported by rice@google.com on 2009-12-01 21:13:17

dankurka commented 9 years ago
I'm closing this as "AsDesigned."  It's up to the client code to avoid overflow for
integer fields that are 
transmitted by RPC.  Revision r7238 adds a more descriptive error message for this
case.

Reported by rice@google.com on 2009-12-22 18:01:02