gwt - Using List in a RPC call?

2019-01-08 00:19发布

问题:

I have a RPC service with the following method:

public List<Serializable> myMethod(TransactionCall call) {...}

But I get a warning when this method is analyzed, and then the rpc call fails

Analyzing 'my.project.package.myService' for serializable types
Analyzing methods:
public abstract java.util.List<java.io.Serializable> myMethod(my.project.package.TransactionCall call)
Return type: java.util.List<java.io.Serializable>
[...]
java.io.Serializable
Verifying instantiability
(!) Checking all subtypes of Object wich qualify for serialization

It seems I can't use Serializable for my List... I could use my own interface instead (something like AsyncDataInterface, wich implements the Serializable interface) but the fact is that my method will return a list custom objects AND basic objects (such as Strings, int....).

So my questions are:

  • Is it a standart behaviour? (I can't figure out why I can't use this interface in that case)
  • Does anyone have a workaround for that kind of situation?

回答1:

When passing objects across RPC call's its a good practice to declare concrete parameter types in the RPC interface. If for some reason you cannot use concrete class in the RPC interface try to be as specific as possible.

This is because the GWT compiler while emitting javascript has to take into account all possible variants of List in the compilation unit. This includes all the classes extending List and Serializable interface in the class path. The permutations can be huge, which will effect your compile time as well as the application download size.

So the best approach is to define your interface as

public ArrayList<YourType> myMethod(TransactionCall call) {...}

rather than

public List<Serializable> myMethod(TransactionCall call) {...}

That way compiler has to generate compilation units for ArrayList and YourType extensions only. The benifit is in faster compile times and smaller compiled javascript files, hence faster downloads of your application.

In case you have to return a wide range of unrelated objects in your RPC call, try creating a wrapper class and return object of the wrapper class with the return value wrapped. Use the wrapper class in the RPC method definition. Resist the urge to declare the wrapped field as Object or Serializable, you will negate all serialization benefits you gained by using a wrapper. Instead you can define a Wrapper interface and a small set of Wrapper implementation for each concrete type you wish to return through your RPC call.



回答2:

You might want to check that serialization policy file isn't the source of the problem.

Quote from GWT documentation:

However, there is one condition to enable support for java.io.Serializable in the new GWT RPC system.

RPC now generates a serialization policy file during GWT compilation. The serialization policy file contains a whitelist of allowed types which may be serialized. Its name is a strong hash name followed by .gwt.rpc. In order to enable support for java.io.Serializable, the types that your application will send over the wire must be included in the serialization policy whitelist. Also, the serialization policy file must be deployed to your web server as a public resource, accessible from a RemoteServiceServlet via ServletContext.getResource(). If it is not deployed properly, RPC will run in 1.3.3 compatibility mode and refuse to serialize types implementing java.io.Serializable.



回答3:

I don't see the point of defining List<Serializable> as the return value. The type Serializable provides no additional information in the service API declaration. GWT will make the serialization check at runtime anyway.

In your case, where the list elements have no common ancestor other than Object, I would use List<?>.