What is the effect of reverse proxy on a GWT application?
Asked Answered
T

1

8

I am deploying a GWT 2.4 app on Glassfish 3.0.1. I can easily access my application via http://host:PORT/appContext/
However, when I reverse proxy the application with Apache I get an exception with the following excerpt (from Glassfish logs):

Exception while dispatching incoming RPC call com.google.gwt.user.client.rpc.SerializationException: Type 'com.ozdokmeci.basicgwtproject.shared.GroupData' was not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' and did not have a custom field serializer. For security purposes, this type will not be serialized.

Implementing IsSerializable solves the problem as advised by Chi in a related question. There are also other workarounds in the related question.

My question is what is the underlying cause of this and how come two seemingly unrelated solutions (implementing a marker interface and extending a servlet class) solve this problem? Also are there any disadvantages to both of the methods mentioned in the related question?

Note: The exception does not occur if the app is reached directly.

Note2: Class related to the exception already implements the interface Serializable, which should be equivalent to the IsSerializable as far as GWT is concerned.

Tybie answered 30/9, 2011 at 13:20 Comment(5)
Are you sure the exception occcurs only when it is accessed via Apache - you need to check that assumption. I think the error is happening even when you accessing it directly. The exception has nothing to do with reverse proxy.Frug
The exception occurs only when it is proxied behind Apache (I'm not suggesting that Apache is causing it). When I access the app directly no such exception occurs. This wasn't an assumption and I checked the logs more than once before posting the question. I know that the exception is not directly related with the reverse proxy and thats why I asked the question :)Tybie
I think there is something else going wrong - when you say non-apache is that the hosted / devmode or accessing the compiled js version. Can you check if both are running the same version of code (caching, improper build etc are ruled out). Make some visible change on the main page and check if the change appears through apache proxy.Frug
The app is deployed to a remote server, so it is running the compiled version. I am putting the deployed app behind the reverse proxy on the same server. So the one running behind the proxy and the one that is accessed directly are the same. By the way the proxy is not a caching proxy, it is there only to make the URLs look prettier to the end user.Tybie
Having the same exact issues on my front over here.Khasi
B
4

I had the exact same issue and when I traced through the source code I found that the directory of GWT serialization files was not being found when reverse-proxying (I think because the directory was a relative path). This is why you are getting serialization exceptions even though you have implemented IsSerializable.

My solution in the end was to move to restful JSON for my RPC. Using JSON will allow you to reverse proxy because it doesnt need to find these Serialization files.

Edit

If you want to still use GWT RPC though, I have an idea of how it's possible (though I havent implemented it myself).

First, take a look at the GWT Help about these rpc files: https://developers.google.com/web-toolkit/doc/2.4/DevGuideCompilingAndDebugging#key_application_files

You will notice it says:

The serialization policy file must be accessible by your RPC RemoteServiceServlet via the ServletContext.getResource() call

So you will need to override RemoteServiceServlet and re-point the location of the rpc (serialization policy) files.

Here is one suggestion, taken from this site: http://code.google.com/p/google-web-toolkit/issues/detail?id=4817

    public class MyRemoteServiceServlet extends RemoteServiceServlet
    {

    ...

    @Override
    protected SerializationPolicy doGetSerializationPolicy(
            HttpServletRequest request, String moduleBaseURL, String strongName) {
            //get the base url from the header instead of the body this way 
            //apache reverse proxy with rewrite on the header can work
            String moduleBaseURLHdr = request.getHeader("X-GWT-Module-Base");

            if(moduleBaseURLHdr != null){
                    moduleBaseURL = moduleBaseURLHdr;
            }

            return super.doGetSerializationPolicy(request, moduleBaseURL, strongName);
    }

    ...

In apache config add:

    ProxyPass /app/ ajp://localhost:8009/App-0.0.1-SNAPSHOT/

    <Location /app/>

    RequestHeader edit X-GWT-Module-Base ^(.*)/app/(.*)$ $1/App-0.0.1-SNAPSHOT/$2

    </Location>

Hopefully my suggestion above at least points someone in the right direction. Please let us know if someone implements this and it works.

Basidiomycete answered 3/8, 2012 at 13:10 Comment(3)
Your solution is nice. It would be beneficial for others if you could elaborate on the underlying cause (relative directories ?) or outline the structure of GWT serialization if you know it :) ThanksTybie
@Tybie - Okay, I have updated my solution with some more detail... I still havent implemented this myself, so please try it out and let everyone know if it works!Basidiomycete
@jsop - Thanks for the update, nice suggestion & pointer. I won't be able to try this out soon. Accepting as an answer until then.Tybie

© 2022 - 2024 — McMap. All rights reserved.