Strange GWT-RPC bug upgrading from 2.7 to 2.8+

252 views
Skip to first unread message

Aaron Davidson

unread,
Sep 28, 2020, 4:43:11 AM9/28/20
to GWT Users
I have a large GWT app and we've been stuck on GWT 2.7 for years. If I try to update to 2.8 or 2.9, a random selection of our GWT-RPC calls are not encoded properly by the client. Certain fields in the request become 'undefined' (example below), and cannot be decoded.

We REALLY want to upgrade to 2.9, and I am at a loss as to how to fix this. At this point. I will happily award a $1000 bounty for a good solution!

An example (no rhyme or reason to the types of RPC arguments, this is just the first one we make but many simpler RPCs fail as well well.

RPC Signature:

     public User authenticate(String sessionKey, Integer offset) throws NotLoggedInException;

GWT 2.7:

7|0|6|http://127.0.0.1:8888/cronometer/|32DF1A25F01F1EA26BACD86E081E664C|com.cronometer.client.CronometerService|authenticate|java.lang.String/2004016611|java.lang.Integer/3438268394|1|2|3|4|2|5|6|0|6|-420|

GWT-2.8, 2.9:

7|0|6|http://127.0.0.1:8888/cronometer/|32DF1A25F01F1EA26BACD86E081E664C|com.cronometer.client.CronometerService|authenticate|java.lang.String/2004016611|java.lang.Integer/3438268394|1|2|3|4|2|5|6|0|undefined|undefined|


The request encoding sent to server is identical here except the last two items have changed to 'undefined'.


This causes decoding to fail with:

WARN  16:40:14.014 [qtp756508433-309] / - Exception while dispatching incoming RPC call

java.lang.NumberFormatException: Expected type 'int' but received a non-numerical value: undefined

at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.getNumberFormatException(ServerSerializationStreamReader.java:1027)

at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.readInt(ServerSerializationStreamReader.java:551)

at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.readString(ServerSerializationStreamReader.java:607)

at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:286)


Another illustrative example:

void setParam(String sessionKey, String val) throws NotLoggedInException;

7|0|7|http://127.0.0.1:8888/cronometer/|32DF1A25F01F1EA26BACD86E081E664C|com.cronometer.client.CronometerService|setParam|java.lang.String/2004016611|a358-6aa3-ca6a-daca-308a-3a30-503a-4a50|http://127.0.0.1:8888/|1|2|3|4|2|5|undefined|6|7|

Again, one of the fields in the request is not set right.

Does anyone have any ideas what's wrong here or how to fix it?

I would log a bug but I cannot reproduce this when I make a small test project and copy an individual RPC example. 



Joker Joker

unread,
Sep 30, 2020, 4:07:33 AM9/30/20
to GWT Users
As an experiment, I would try changing the "offset" parameter type from "Integer" to "int" in both versions of the method.
You can also try deleting all gwt-unitCache files.

понедельник, 28 сентября 2020 г. в 12:43:11 UTC+4, pha...@gmail.com:

lofid...@gmail.com

unread,
Sep 30, 2020, 4:06:10 PM9/30/20
to GWT Users
Did you separate the modules in:
  • client
  • shared
  • server
... with its own classpath? Or did you put them together in one project with one classpath?

The latter is not good, because you may get "classpath hell" so GWT transpiler uses wrong libs to transpile the Java code.

I definitely would try to separate the modules... also because you said, that in a small stand-alone project the mechanism works well.

Hope this helps,
Lofi

Jens

unread,
Oct 1, 2020, 3:40:34 AM10/1/20
to GWT Users
First of all, when updating GWT SDK you should delete your gwtUnitCache directory. Historically there has always been some hiccups with the cache when upgrading GWT. By deleting it you make sure to start a fresh compile without any cached information.

If that does not help you should take the stack trace you see in the browser console and put a break point at the location calling your GWT-RPC service methods. This is just to verify that the GWT-RPC method is really called with non null parameters as you would expect. Maybe that is not the case.


-- J.

Aaron Davidson

unread,
Oct 1, 2020, 3:03:50 PM10/1/20
to GWT Users
Yes, we've tried removing the gwtUnitCache. This issue happens on every dev machine, as well as clean builds on our jenkins build system. 

For further  context, this is a large web app with millions of users (cronometer.com), actively developed and battle hardened for 9 years. 

We've just been unable to upgrade from GWT 2.7 because of this issue.

It's not an issue of null arguments to RPC -- it's a bug in the encoder, giving arguments as 'undefined'. It doesn't seem to matter what the types are (Integer, int, String, etc...), I find encoding issues appear widespread for most of the hundreds of RPCs we have, and I can't spot any pattern to it. Diving into the specific example above:

Encoding the tzOffset integer argument (which is not null) is where it fails. You can see in the local vars the streamWriter buffer looks fine at this point, but after writing tis integer, it will have two 'undefined' values appended.

Screen Shot 2020-10-01 at 11.54.41 AM.png

Diving in here, it fails trying to write the type signature ("java.lang.Integer/3438268394") for the Integer:

  public void writeString(String value) {
    writeInt(addString(value));
  }

in addString() it returns '6':
Screen Shot 2020-10-01 at 11.59.37 AM.png

But then when writeInt() passes that "6" it is appearing to be magically transformed to undefined!!!! :
Screen Shot 2020-10-01 at 12.01.15 PM.png

And there you have it... absolutely no idea why it's malfunctioning in this way. Any help is greatly appreciated!

Aaron Davidson

unread,
Oct 1, 2020, 3:25:04 PM10/1/20
to GWT Users
Hmm, we've got client and server code in separate packages, but I don't know exactly what the configuration would look like for separate project classpaths. If you feel like having a peek with me over a zoom call to look further, let me know! 

Jens

unread,
Oct 2, 2020, 7:31:37 AM10/2/20
to GWT Users
And there you have it... absolutely no idea why it's malfunctioning in this way. Any help is greatly appreciated!

Ok in sourcemaps it looks indeed a bit weird. However there will be additional JS code executed to convert java.lang.Integer into a primitive int which is represented by JS number. That conversion seems to produce undefined.

Please use newest GWT SDK and either launch SuperDevMode or GWT compiler with these additional command line parameters: "-strict -style PRETTY -XmethodNameDisplayMode ABBREVIATED".

When doing so you make sure that no compile issue will be skipped (-strict), your JS code will be more readable (-style PRETTY) and you can more easily search for Java method names in the generated JS code (-XmethodName...). Next you should disable JS Source Maps support in Chrome Dev Tools to see the JS code.
To find the above method you would search the JS for "AbstractSerializationStreamWriter.addString" and should find a JS line that sets a displayName property. Above that line you will find the method implementation.

In the typical case to convert java.lang.Integer to primitive int, GWT should have generated JS that calls the intValue() method of Integer.


If something looks weird you might also want to double check that you do not have multiple versions of GWT in class path. That sometimes happened people when upgrading GWT and also using a bunch of third party libraries. Sometimes 3rd party libraries also emulate JRE classes which then do not match the JRE emulation in GWT SDK. This can be an additional possibility for unexpected JS behavior.


-- J.

Aaron Davidson

unread,
Oct 3, 2020, 11:16:11 PM10/3/20
to GWT Users
Thanks Jens, I did what you asked and have the following in the debugger:

Screen Shot 2020-10-03 at 8.11.01 PM.png

Screen Shot 2020-10-03 at 8.11.17 PM.png

What do you make of this?

I don't see any duplicate GWT on the classpath (project is a pretty simple maven setup).

Thanks,
Aaron

lofid...@gmail.com

unread,
Oct 6, 2020, 2:15:19 PM10/6/20
to GWT Users
If you need a fast solution I would recommend to use professional help like Vertispan: https://www.vertispan.com

Colin knows the transpiler inside out 😉

@Jens: thanks for your debugging tips, I would add your tips to my GWT deck.

Michael Conrad

unread,
Oct 6, 2020, 2:20:08 PM10/6/20
to google-we...@googlegroups.com
I don't know if this applies to your situation, but we had an issue similar to this (a long time ago) that was caused by shadowing properties from parent classes in child classes.

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit/e6492c9f-e3e1-4933-b1eb-5bbaca5e1866n%40googlegroups.com.

Aaron Davidson

unread,
Oct 7, 2020, 12:21:50 PM10/7/20
to GWT Users
Thanks for the tip Lofi -- I don't know about vertispan, but looks like a great option for us to check out!

Jens

unread,
Oct 7, 2020, 12:30:57 PM10/7/20
to GWT Users
Well ok that devirtual function is clearly broken. Normally these kind of functions do instanceof dispatches to delegate an abstract method call, e.g. Number.intValue(), to a concrete implementation, e.g. Integer.intValue.

Below an example how it should look (GWT master branch with an example app):

function intValue__I__devirtual$_0_g$(this$static_0_g$){
  $clinit_Number_0_g$();
  return instanceOfDouble_0_g$(this$static_0_g$)?$intValue_0_g$(this$static_0_g$):this$static_0_g$.intValue_20_g$();
}
intValue__I__devirtual$_0_g$.displayName = 'Number.intValue__I__devirtual$';


_.intValue_20_g$ = function intValue_4_g$(){
  return this.value_73_g$;
}
_.intValue_20_g$.displayName = 'Integer.intValue';


This looks like a compiler bug to me triggered by your source code or you have am 3rd party GWT library that emulates either Number or Integer. A small reproduction project would be nice, but probably very hard to isolate the underlying issue.

Do you still have the issue when you comment everything in your entry point and just add a line that executes the GWT-RPC call that currently fails?

-- J.
Reply all
Reply to author
Forward
0 new messages