Reputation: 19150
I'm using GWT 2.4. I'm having a serialization issue. My service has a method ...
@RemoteServiceRelativePath("retrieveChild")
public interface ChildRetrievalService extends RemoteService {
...
Collection<Node> getRootNodes();
In which my "Node" class is defined as follows ...
public class Node implements Serializable {
private Long id;
private Node parent;
private String info;
private List<Node> children;
public Node() {
this.children = new ArrayList<Node>();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
} // setId
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
} // setInfo
public List<Node> getChildren() {
return children;
}
public boolean equals(Object node) {
return node != null &&
node instanceof Node &&
((Node) node).getId() == id;
}
public int hashCode() {
return getId().hashCode();
}
}
But I'm getting an error when trying to invoke the service method, complaining about serialization. Both HashMap and Node are Serializable, so where is everything breaking down?
[WARN] Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'java.util.HashMap$Values' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = [com.cme.draganddroptree.shared.Node@0, com.cme.draganddroptree.shared.Node@1, com.cme.draganddroptree.shared.Node@2, com.cme.draganddroptree.shared.Node@3, com.cme.draganddroptree.shared.Node@4] at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619) at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:539) at com.google.gwt.user.server.rpc.RPC.encodeResponse(RPC.java:616) at com.google.gwt.user.server.rpc.RPC.encodeResponseForSuccess(RPC.java:474) at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:571) at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208) at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248) at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362) 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:729) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:324) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505) at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:205) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Thanks, - Dave
Upvotes: 1
Views: 2323
Reputation: 13519
Always use a concrete type for data used in RPC. Because the GWT compiler needs to generate implementations for all subclasses, as it doesn't know what sub type will be send from the server. This can mean for some types or interfaces it can lead to a lot over overhead, lots of types added, which are never used. For example you know you only use ArrayList, when you have a List specified.
This probably also can cause this error, because it wants to add a substype it can't serialize.
Upvotes: 1
Reputation: 2674
You can't use an abstract type (or interface) for a method parameter for a GWT RPC:
The current GWT RPC system is based around the serialization of concrete types. In the general case, an identical concrete type must be available on both the client and the server. While a custom Serializer can be used to change the actual type used in either the client or server, the serialized type must have knowledge of the Serializer to use. This is problematic when RPC interfaces are declared using (abstract) types of which there are arbitrarily many implementations on the server.
See here for details.
It boils down to the fact that the RPC mechanism can't serialize what your parameter because it doesn't know what it's really going to be. Alternatively, any approach to serialize any possible concrete implementation is just not practical. So you have to pick a concrete class the best suits your needs.
Upvotes: 2