I'm liking GWT development with the Eclipse plugin. I ran through the StockWatcher tutorial, added RPCs and it was working great in hosted mode, but when I deployed it on Tomcat 6 on Ubuntu 9.04, RPCs failed with the following:
The call failed on the server; see server log for details
There were no errors in the catalina log, so following troubleshooting in the GWT dev guide on RPC deployment, I turned on access logging in /etc/tomcat6/server.xml
by uncommenting the following block near the end:
<!-- Access log processes all example. Documentation at: /docs/config/valve.html --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>Restarted Tomcat, tried the app again, and saw a whole lot of these in the access log:
192.168.1.22 - - [20/Jan/2010:23:59:57 -0600] "POST /StockWatcher/stockwatcher/stockPrices HTTP/1.1" 500 57
I verified that the URL used in setServiceEntryPoint(URL)
and the <url-pattern>
in my web.xml matched, then did more searching and found a post to the GWT google group. There are a couple of good replies in there, and it seems to come down to this: reflection is used by GWT RPC to serialize objects for transmission to the client browser, but it requires access to private members, which Tomcat doesn't allow by default.As I understand it, there are two ways you can go:
- Make all members public in classes that require serialization.
- Grant reflection permission to the app in the Tomcat Security Manager config.
/etc/tomcat6/policy.d/50local.policy
, then restarted.
grant codeBase "file:${catalina.base}/webapps/StockWatcher/-" { permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; };I've modified it from the post by changing
${catalina.home}
to ${catalina.base}
, but this cleared up the errors.
Thanks. Your crystal clear explanation saved me from a world of pain.
ReplyDeleteYou mentioned to options for fixing this problem:
ReplyDelete1. Make all members public in classes that require serialization.
2. Grant reflection permission to the app in the Tomcat Security Manager config.
Did you ever test option 1? I can get option 2 to work, but when I deploy to a server where I have limited control, I'm wondering if option 1 will work?
I believe I did test the public members solution and that it worked, but give it a shot with the security manager enabled.
ReplyDeleteI gave it a try and have some interesting results. Here's what I tried:
ReplyDelete1. Created a simple object that was serializable. It had a single String field which was public. It had a single accessor to retrieve the String data. This object was successfully marshalled from the server to the client.
2. Using the same object above, I then tried to pass the object from client to server. This does not work. Have yet to find a solution.