GWT/Tomcat serialization issues during deployment

57 views
Skip to first unread message

duey

unread,
Aug 11, 2010, 9:52:44 PM8/11/10
to Google Web Toolkit
I have a simple application setup. It is comprised of a single module
that has one responsibility. Its job is to test RPC in my
application. Here's what I have. First, on the client side, I have a
TestData object. This object implements java.io.Serializable. It has
one member variable, which has a public access modifier. On the
server side, it's very simple. I have an implementation of a
RemoteServiceServlet that has 2 methods. One that creates an instance
of TestData, the other that accepts an instance of TestData and simply
returns true.

I have 2 goals:
1. I am testing if the TestData can successfully travel from server-
side to client side.
2. I want to create a TestData object and send it to the server side.

I am deploying my application as a WAR file with Tomcat. Tomcat is
running with security enabled.

I can successfully accomplish my first goal. I get the object back
from the server and display its contents in a Label. When I attempt
the second goal I get the following exception:

2010-08-11 21:24:37 StandardContext[/trunorth]Exception while
dispatching incoming RPC call
java.security.AccessControlException: access denied
(java.lang.reflect.ReflectPermission suppressAccessChecks)
at
java.security.AccessControlContext.checkPermission(AccessControlContext.java:
323)
at
java.security.AccessController.checkPermission(AccessController.java:
546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:
532)
at
java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:
107)
at
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.instantiate(ServerSerializationStreamReader.java:
887)
at
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:
544)
at
com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readObject(AbstractSerializationStreamReader.java:
61)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader
$ValueReader$8.readValue(ServerSerializationStreamReader.java:137)
at
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserializeValue(ServerSerializationStreamReader.java:
384)
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:296)
at
com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:
186)
at
com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:
224)
snip...


In terms of code, this is what I'm trying to do from the client side:
testService.sendTestData(new TestData(), sendTestDataCallback);

The communication with the server is fine. The ONLY problem I have is
when I try and create a custom object on the client side and send it
to the server. How can I get around this WITHOUT modifying Tomcat
permissions?

When I officially deploy this application I won't have access to
Tomcat's permissions so I need to make this work with the default
Tomcat security settings.

Please explain to me why a custom object can travel from server to
client with no issues, while the converse is not true.

Thanks in advance

duey

unread,
Aug 13, 2010, 12:49:47 PM8/13/10
to Google Web Toolkit
Had to get my hands dirty to figure this one out. Here's how I got
around these exceptions.

1. First, on the client side. Instead of calling
testService.sendTestData(new TestData(), sendTestDataCallback); I
did the following:
String content = ServiceUtils.marshallTestServiceObject(new
TestData());
testService.sendTestData(content, sendTestDataCallback);

where marshallTestService looks like this:
public static String marshallTestServiceObject(Object obj) {
String content = null;
SerializationStreamFactory factory = GWT.create(TestService.class);
SerializationStreamWriter writer = factory.createStreamWriter();
try {
writer.writeObject(obj);
content = writer.toString();
} catch (SerializationException se) {
content = null;
}
return content;
}

That successfully sent the object to the server side.

2. On the server side I had to create my own
AbstractSerializationStreamReader and call it as follows:
CustomSerializationStreamReader reader = new
CustomSerializationStreamReader(
Thread.currentThread().getContextClassLoader(), null);
try {
reader.prepareToRead(content);
TestData testData = (TestData)reader.readObject();
// viola, I have the testData instance
} catch (SerializationException se) {
se.printStackTrace();
}

Before I created a custom string reader I tried to use the
ServerSerializableStreamReader. This did not work because of the
following line of code:
Constructor<?> constructor =
instanceClass.getDeclaredConstructor();

That line of code essentially makes the following call:

System.getSecurityManager() .checkMemberAccess(TestData.class.getDeclaredConstructor().getClass(),
Member.DECLARED);

Unfortunately, when Tomcat is running with a security manager,
this call causes an AccessControlException because we can only see
Member.PUBLIC. So...Long story short. My
CustomSerializableStreamReader simply calls Constructor.newInstance(),
which does the trick. I know that my default ctor exists and is
public so this worked for me.

I hope somebody is able to find this useful. Especially if you run
your app on GoDaddy and need reflection.

-Eric
Reply all
Reply to author
Forward
0 new messages