GWT 2.0 RPC not picking up custom generated Serializable classes

26 views
Skip to first unread message

Martin Söderström

unread,
Jan 11, 2010, 5:19:36 AM1/11/10
to Google Web Toolkit
Hi,

I have a custom Generator (subclassing
com.google.gwt.core.ext.Generator) class that generates a class to be
used as argument in an RPC method. The generated class implements
Serializable and the interface that the RPC method expects. This used
to work in GWT 1.7, but with GWT 2.0 I get a
com.google.gwt.user.client.rpc.SerializationException. Using
IsSerializable instead of Serializable does not make any difference.

It feels like, in GWT 2.0, the scanning for RPC serializable classes
does not take into consideration the custom generated classes. Does
anyone know anything about this? A possible workaround?

/Martin

Chris Ramsdale

unread,
Jan 11, 2010, 5:03:35 PM1/11/10
to google-we...@googlegroups.com
Martin,

The RPC serialization generator is most likely being run before your custom generator. As a result serialization code, whitelisting, etc... are not being created. Unfortunately there is no way of guaranteeing that your generator is run before the RPC serialization generator. 

That said, I did have a couple of thought:

1. Within your RPCs, what class is your server expecting?
2. Rather than generate classes that you send across the wire, would it be possible to send an interface, and generate client-side classes that understand how to instantiate themselves based on said interface?
 

2010/1/11 Martin Söderström <martin.k....@gmail.com>
--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.




Martin Söderström

unread,
Jan 12, 2010, 12:26:26 PM1/12/10
to Google Web Toolkit
Chris,

Thanks for trying to help me with this. As for your questions, I'm not
sure I understand the second one, but I'll exemplify better what my
code is doing:

First there is a listener interface:

public interface TestMessageListener {
void messageReceived(String message);
}

Then there is the RPC service (client side version here):

public interface TestServiceAsync {
void addMessageListener(TestMessageListener listener,
AsyncCallback<Void> callback);

void removeMessageListener(TestMessageListener listener,
AsyncCallback<Void> callback);
}

Then there is the concrete listener class in the client:

public class TestMessageListenerImpl extends AbstractRpcObserver
implements TestMessageListener {
@Override
public void messageReceived(String message) {
System.out.println(message + " received");
}
}

The extended class AbstractRpcObserver looks like this:

public abstract class AbstractRpcObserver implements RpcObserver,
Serializable {
protected int rpcReversedSessionId;

protected int observerId;

protected transient Object source;

protected AbstractRpcObserver() {
}

public void setSource(Object source) {
this.source = source;
}

public void setRpcReversedSessionId(int rpcReversedSessionId) {
this.rpcReversedSessionId = rpcReversedSessionId;
}
}

The generated class extends this AbstractRpcObserver (and is thereby
Serializable) and implements the TestMessageListener interface. An
instance of the generated class is used as argument in the
addMessageListener method invoction in the RPC service.

This is part of a framework for asynchronous invocations of observers
in the client from the server. The idea is to have the framework
generate the plumbing code so that any interface can be used as a
"listener" to be added to the server.

Everything works like a charm in GWT 1.7.1, but as you say, that could
be just a happy coincidence.

/Martin

On 11 Jan, 23:03, Chris Ramsdale <cramsd...@google.com> wrote:
> Martin,
>
> The RPC serialization generator is most likely being run before your custom
> generator. As a result serialization code, whitelisting, etc... are not
> being created. Unfortunately there is no way of guaranteeing that your
> generator is run before the RPC serialization generator.
>
> That said, I did have a couple of thought:
>
> 1. Within your RPCs, what class is your server expecting?
> 2. Rather than generate classes that you send across the wire, would it be
> possible to send an interface, and generate client-side classes that
> understand how to instantiate themselves based on said interface?
>

> 2010/1/11 Martin Söderström <martin.k.soderst...@gmail.com>


>
>
>
> > Hi,
>
> > I have a custom Generator (subclassing
> > com.google.gwt.core.ext.Generator) class that generates a class to be
> > used as argument in an RPC method. The generated class implements
> > Serializable and the interface that the RPC method expects. This used
> > to work in GWT 1.7, but with GWT 2.0 I get a
> > com.google.gwt.user.client.rpc.SerializationException. Using
> > IsSerializable instead of Serializable does not make any difference.
>
> > It feels like, in GWT 2.0, the scanning for RPC serializable classes
> > does not take into consideration the custom generated classes. Does
> > anyone know anything about this? A possible workaround?
>
> > /Martin
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Google Web Toolkit" group.
> > To post to this group, send email to google-we...@googlegroups.com.
> > To unsubscribe from this group, send email to

> > google-web-tool...@googlegroups.com<google-web-toolkit%2Bunsubs cr...@googlegroups.com>

Chris Ramsdale

unread,
Jan 12, 2010, 3:27:23 PM1/12/10
to google-we...@googlegroups.com
My comments/questions inline:
 
The generated class extends this AbstractRpcObserver (and is thereby
Serializable) and implements the TestMessageListener interface. An
instance of the generated class is used as argument in the
addMessageListener method invoction in the RPC service.

If I understand this correctly, your custom generator is generating the TestMessageListenerImpl class you reference above. Correct?
 
This is part of a framework for asynchronous invocations of observers
in the client from the server. The idea is to have the framework
generate the plumbing code so that any interface can be used as a
"listener" to be added to the server.

Everything works like a charm in GWT 1.7.1, but as you say, that could
be just a happy coincidence.

Yes. Either happy coincidence, or the order in which we ran the generators was different in 1.7.1. Not necessarily my area of expertise, but I'm asking around back here.

Would you mind emailing me your gwt.rpc file? I would like to see what classes have been whitelisted.

 
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.

Martin Söderström

unread,
Jan 12, 2010, 5:03:48 PM1/12/10
to Google Web Toolkit
Chris,

Sorry, I was unclear and also a bit wrong in my description above.
First, the class that gets generated is NOT TestMessageListenerImpl,
TestMessageListenerImpl is the class that the user of the framework
defines to be the "real" listener class in the client and is of less
importance.

I missed to mention the class AbstractRpcObserverWrapper. This is the
class that the generated class extends (I wrote AbstractRpcObserver,
which is wrong, but this doesn't really change the reasoning since
both implement Serializable). Apart from extending this class, the
generated class also implements TestMessageListener.

AbstractRpcObserverWrapper looks like (although the internals
shouldn't matter for the resoning):

public abstract class AbstractRpcObserverWrapper implements
RpcObserverWrapper, Serializable {
protected int observerId;

protected int rpcReversedSessionId;

@Override
public int getObserverId() {
return observerId;
}

@Override
public void setObserverId(int listenerId) {
this.observerId = listenerId;
}

@Override
public int getRpcReversedSessionId() {
return rpcReversedSessionId;
}

@Override


public void setRpcReversedSessionId(int rpcReversedSessionId) {
this.rpcReversedSessionId = rpcReversedSessionId;
}

protected boolean matches(String methodName, List<Class<?>>
parameterTypes, RpcObserverInvocation invokation) {
if (!methodName.equals(invokation.getMethodName())) {
return false;
}
List<JavaType> invokationParametersTypes =
invokation.getParametersTypes();
Iterator<JavaType> invokationParametersTypesIterator =
invokationParametersTypes.iterator();
for (Class<?> parameter : parameterTypes) {
if (!invokationParametersTypesIterator.hasNext()) {
return false;
}
JavaType invokationParameter =
invokationParametersTypesIterator.next();
if (!parameter.equals(invokationParameter.getAsClass())) {
return false;
}
}
if (invokationParametersTypesIterator.hasNext()) {
// Different number of parameters.
return false;
}
return true;
}
}

When the user of the framework needs an instance of
TestMessageListenerImpl, he will do:

TestMessageListener testMessageListener = GWT.create
(TestMessageListenerImpl.class);

and be handed out an instance of the generated class.

Once I get back in the office I will supply the code for the generated
class and also for the gwt.rpc so you can see it.

/Martin

> > > > google-web-tool...@googlegroups.com<google-web-toolkit%2Bunsubs cr...@googlegroups.com><google-web-toolkit%2Bunsubs

Farid

unread,
Sep 20, 2011, 9:19:36 AM9/20/11
to google-we...@googlegroups.com
Hello Martin and Chris,

I was wondering if there is any final answer to this issue. I happen to have the same problem whereby I cannot send classes generated by my generator through GWT RPC. The GWT RPC generator does not seem to be able to find the source for my generated class.

Let me know if there is any progress on this. It is holding me up at the moment.
Many thanks and best regards,
farid

Martin Söderström

unread,
Sep 21, 2011, 8:20:34 PM9/21/11
to google-we...@googlegroups.com
Farid,

FYI: my team stopped progress on this project before I had the chance to supply Chris the code for the generated class and gwt.rpc, so we never actually sorted this out. Maybe Chris would still be interested in seeing your code now instead to have a look at what's going on.

/Martin

Farid

unread,
Sep 22, 2011, 2:31:34 PM9/22/11
to Google Web Toolkit
Thank you Martin.

I think I have found a fix. GWT seems to generate the java source only
for the purpose of cross-compiling it into javascript and then
discards the generated java files. There is a compiler option to keep
the generated java code in a specific folder but the resulting .java
file is not compiled with the build.

It is possible, although very convoluted and clumsy, to change the
build process to pick up source files generated by my generator and
include them in the build path so they can be compiled and available
at runtime.

I have instead created a separate class to generate my java source
code. This class is used by the generator to generate the java source
to be cross-compiled by GWT. The same class is then used by my
application to dynamically generate and load these java classes into
the VM. They are then available at runtime and all seems to be working
fine.

Thank you again for your help and if anyone needs more information
about this workaround I will be happy to send it to them.

On Sep 22, 2:20 am, Martin Söderström <martin.k.soderst...@gmail.com>
wrote:
Reply all
Reply to author
Forward
0 new messages