6

I have a perfectly working GWT application. Now I am trying to use gwt-syncproxy to create an Android client which can simply reuse the server side code.

So far everything was working perfectly. The only problem that I can find is when I start RPC to a method expecting an enum as a parameter.

The enum looks something like this:

import java.io.Serializable;
import com.google.gwt.user.client.rpc.IsSerializable;

public enum ReferenceTable implements IsSerializable, Serializable
{
    basetable, othertable;

    ReferenceTable(){}
}

The error message I'm getting is:

com.google.gwt.user.client.rcp.IncompatibleRemoteServiceException: Invalid type signature for package.ReferenceTable

which suggests that it's a problem related to serialization.

I tried using different combinations of IsSerializable and Serializable and always cleaned the project before deploying. Both the GWT app and the Android app use the same code for the data types used for communication.

Does anyone have an idea how to solve this? If nothing else works, I could refrain from using enums, but I would prefer using them. Especially, since everything is working for the GWT server-client communication itself.


BTW: The error on the server side is:

Caused by: com.google.gwt.user.client.rpc.SerializationException: Invalid type signature for some.package.ReferenceTable
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.validateTypeVersions(ServerSerializationStreamReader.java:1116)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:610)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.readObject(ServerSerializationStreamReader.java:567)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader$ValueReader$8.readValue(ServerSerializationStreamReader.java:140)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserializeValue(ServerSerializationStreamReader.java:425)
    at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:312)
    ... 24 more

EDIT:

I created both a sample GWT app and a sample Android app, so people can actually try the code:

To deploy the app, just modify the build.properties file and then run build.xml as an ant script. In the MainActivity of the Android app, modify the URL to point to the GWT app.

Baz
  • 36,440
  • 11
  • 68
  • 94
  • Have you tried to add a non argument constructor to the ReferenceTable class? – El Hoss Sep 27 '13 at 13:13
  • @ElHoss Please have a look at the code again. There is a non argument constructor. – Baz Sep 27 '13 at 13:39
  • ups ... You are right. is your class inside your source packages? – El Hoss Sep 27 '13 at 13:43
  • @ElHoss Yes, it is in the `shared` package which is marked as source. – Baz Sep 27 '13 at 13:46
  • Just founds something: https://groups.google.com/forum/#!topic/google-web-toolkit/3MdEHteLw-4 – El Hoss Sep 27 '13 at 13:50
  • @ElHoss Everything is synced, i.e. all classes used have the same state. As I said, the GWT app itself is working properly. – Baz Sep 27 '13 at 13:51
  • One question: have you tried to the RCP service only with the Android client? Does this work? – El Hoss Sep 27 '13 at 14:00
  • @ElHoss What do you mean? Try to navigate to the URL in a browser? BTW: It works for requests that don't have an enum as a parameter. – Baz Sep 27 '13 at 14:35
  • The RCP serialization treats enums in a different way. Only the names are serialized. Both clients will have a GWT.create that invokes a generator to generate the code for the serialization. Because of the different handling, may be GWT generates a new version for the enum handling. To check this, I would try to generate a GWT application which only contains the Android client. If it works, you can use enums in your usecase. – El Hoss Sep 27 '13 at 14:49
  • @ElHoss I'm still not sure if I understand your last sentence. What do you mean with _"a GWT application which only contains the Android client"_? The Android code just includes the `shared` folder and the service interfaces. – Baz Sep 27 '13 at 14:51
  • You don't need to implement both `IsSerializable` and `Serializable`. Also, the `java.lang.Enum` class is already serializable, so try extending the object `Enum`? – Churro Sep 27 '13 at 16:27
  • @Churro Yeah, I read that it's not necessary and tried it without, but it didn't work. And you can't extend `Enum` directly. – Baz Sep 27 '13 at 16:32
  • sorry, you're right about the enums. The only time I had experienced `IncompatibleRemoteServiceException`s were when the client had a older version of the code running from the version on the server. I was able to resolve that with a refresh of the client browser, but sometimes it required the client to clear the cache. – Churro Sep 27 '13 at 16:49
  • SyncProxy relies on the content of the *.gwt.rpc files to determine types that are whitelisted for Serialization. Can you check if ReferenceTable appears in your *.gwt.rpc files? If not you can try adding it manually to see if that corrects the problem. – Josh Sep 28 '13 at 23:59
  • @Josh It has to be contained, since the basic GWT client server interaction works. It's just the interaction to Android that fails although it's using the same server code and the same code for the client. – Baz Sep 29 '13 at 07:13
  • @Josh I had a look and the enums are not specifically mentioned in the .gwt.rpc files. However, I don't know how to add them, since I'm not sure what all the entries of each line stand for. – Baz Oct 01 '13 at 13:16
  • Remove the Serialization since this is an enum? – Sherif elKhatib Oct 01 '13 at 13:38
  • @SherifelKhatib What exactly do you mean? If it's about the interfaces I implement, then I can tell you that it doesn't work, even if I remove them. – Baz Oct 01 '13 at 13:39
  • If you remove the Serialization interfaces, clean, rebuild completely; you get the same error? – Sherif elKhatib Oct 01 '13 at 13:42
  • @SherifelKhatib Yes, I do. Keep in mind, that this is only true for the communication via gwt-syncproxy. The actual GWT app itself (client <-> server) works perfectly. – Baz Oct 01 '13 at 13:43
  • Baz, can you try manually adding to one of your *.gwt.rpc files the following line: com.baz.ReferenceTable, true, true, true, true, com.baz.ReferenceTable/2966767886, 2966767886 The booleans represent whether the type may be serialized / de-serialized by the client / server and is checked by sync-proxy before serialization is attempted. If this resolves the issue you can create a dummy RemoteService interface that lists the types you want to have the GWT compiler add to the *.gwt.rpc files. – Josh Oct 01 '13 at 22:10
  • @Josh Ok, I think I finally understood the structure of the .gwt.rpc files. And I found the `ReferenceTable` in the file for the service I'm trying to call. So it's already contained in the file and still I'm getting the same result... – Baz Oct 02 '13 at 08:25
  • Try to generate 'serialVersionUID' fot the Enum type and see if it solves the problem. – M.Sameer Oct 04 '13 at 11:56
  • @M.Sameer Unfortunately, that doesn't change anything. – Baz Oct 04 '13 at 12:05

2 Answers2

2

I am unable to verify your issue as described (using your provided src, it works in my dev environment using a JB emulator), though I have seen your specified error during development of the Android library. I have found that many of the "Serialization" issues in GWT are usually something small such as unserializable member types, missing interfaces, default constructors, etc. Since it seems you have already addressed those possibilities, please verify the following:

Version of GWT being used in web-app on your machine. Android OS Version being tested on (emulator or Device) and which device if appropriate.

Though I dont expect it to be an issue, the Android library is compiled with GWT 2.5.0 src, so it's possible (an as yet untested theory) that if the server is running GWT other than 2.5.0, the RPC serialization is failing due to that.

This would also explain why the desktop client works and the android library does not. The desktop client syncproxy library is compiled against GWT, not with GWT, so you link your version of GWT at compile time. The Android library was compiled directly with GWT src code for 2.5.0 with a few custom overrides in order to reduce the size of the library to be usable and manageable in the Dalvik environment.

That said, if its possible for your project, try using GWT 2.5.0, clean/recompile and give that a shot. If not, it's on my todo list to get the library up to 2.5.1, but I haven't had time as yet.

Disclaimer: I created the Android library in question as a contributor to the gwt-syncproxy project. I can't claim to understand all the ins and outs of GWT or the syncproxy internals, but at least enough to get the working model of the library functional. I'm open to suggestions on improvement of the library or any ideas of where in the internals we should look to resolve this if any gwt-guru's are out there...

JCricket
  • 1,318
  • 2
  • 17
  • 34
  • Brilliant, switching the Example app to GWT 2.5.0 did the trick. Can you give me an estimate as to when you would be able to update the library to 2.5.1? If you don't have the time to do it, I *could* switch the main app to 2.5.0. However, I'd prefer staying with the latest release if possible. Please let me know if you're planning to update to 2.5.1! :) – Baz Oct 07 '13 at 09:00
  • I'll take a look at the 2.5.1 source this week and see if I can pull it off. If so, I'll try to get a 2.5.1 compatible library out within a week or 2. If major changes occurred to the files, it will likely take me longer to filter things out to get it to be compatible with 2.5.1 (based on my schedule, upwards of a month). If it looks like it will take that long, I may end up just holding off until the 2.6 release (expected early Dec). Keep an eye on the wiki's and issue tracker for the project (I can't modify the project home page because I'm not the project owner and the owner is...MIA). – JCricket Oct 07 '13 at 20:58
  • That's great. I'm really looking forward to this! – Baz Oct 07 '13 at 21:11
0

Delete the IsSerializable interface declaration, from:

public enum ReferenceTable implements IsSerializable, Serializable

To:

public enum ReferenceTable implements Serializable

Just if your application is purely GWT you must use the IsSerializable interface, but, in this case, you want to use the same code with an Android app, you have to use only the Serializable interface.

n3k0
  • 577
  • 14
  • 40
  • Enum is already serializable on itself and it doesn't work. How would adding the `Serializable` interface help? – Baz Oct 04 '13 at 20:17
  • 1
    Did you already deleted the IsSerializable interface and made a test? The problem here, is that IsSerializable interface is exclusive from GWT, when you try to have interaction to other platforms (Android in this case) you have to declare the IsSerializable interface, or delete the references in the GWT code. – n3k0 Oct 04 '13 at 20:33
  • Yes, I already tried all combinations. FYI, the app (GWT and Android) works with `IsSerializable`, just not with enums. – Baz Oct 04 '13 at 20:37
  • 1
    Check this, may be useful: http://stackoverflow.com/questions/17219111/gwt-2-5-1-and-intellij-debug-mode-serializable-exception and http://stackoverflow.com/questions/4207988/problems-with-gwt-and-enum and http://stackoverflow.com/questions/8908352/gwt-incompatibleremoteserviceexception – n3k0 Oct 04 '13 at 21:18
  • Unfortunately, I've read them all before and none of them contain a solution for my problem. I can't emphasize this enough that the actual GWT app is working, so no problems there. It is a specific problem to the combination of GWT and gwt-syncproxy. – Baz Oct 04 '13 at 21:21
  • That definitely sounds related, however, the thread states that the issue was resolved in version 0.4 which is the one I'm using. – Baz Oct 05 '13 at 07:33