Re: rpc serialization without the rpc

203 views
Skip to first unread message

Jens

unread,
Nov 2, 2012, 1:42:28 PM11/2/12
to google-we...@googlegroups.com
How do you plan to get the payload of any GWT-RPC request to the server when using HTTP GET? Using URL parameters can be pretty unsafe because every GWT-RPC payload should contain your app's security token / session id to prevent CSRF attacks.

-- J.

Jamie

unread,
Nov 2, 2012, 4:47:55 PM11/2/12
to google-we...@googlegroups.com
While not answering your question exactly, I have seen posts around on writing your own caching filter for Java, and they seem pretty easy to do.
And, it would then be really easy to invalidate your cached items.

However, as Jens says, putting all the request parameters into the URL is not a good idea.
If you really want, you could write your caching filter to cache POST requests.

Benjamin Possolo

unread,
Nov 2, 2012, 5:56:09 PM11/2/12
to google-we...@googlegroups.com
Correct me if I am wrong but it sounds like your idea will only have one advantage over a traditional caching layer on the server: avoiding serialization costs. You will still have deserialization costs which are likely a lot more time consuming since they happen in javascript in the browser versus in the JVM on the server.

I think what you are suggesting is dangerously bordering along the lines of "ghetto."
I feel like caching on the client (using a Command like design pattern and local storage) plus a normal caching layer on the server will vastly outweigh the benefits and hassle of creating and maintaining an GWT-RPC-HTTP frankenstein.

Peter Warren

unread,
Nov 3, 2012, 3:33:09 PM11/3/12
to google-we...@googlegroups.com
Thanks for the responses!

@Jens
The payload is already on the server. I send it up as an xml file that gets parsed and converted to a Java object. The upload and conversion happens as a backend process independent of any client interaction. This payload object then gets serialized and sent to clients in response to rpc requests. So the object is uploaded once and then delivered to many clients many times.

@Jamie
I've already done this. I'm caching the actual RPC responses. My RemoteServiceServlet looks at the RPC request and serves the requested item from cache if available.

Sorry, I should've made this clear in my original post. So why am I considering a caching proxy? Because our app is hosted on Google App Engine and is using its distributed cache, and I don't have control over when my cached items get evicted. App Engine doesn't always seem to be super-responsive to the RPC requests (even though I'm using an always-on instance). Since the cached items don't change frequently and aren't client-specific, I thought I would experiment with a proxy cache in front of my system and see how it works. At least I would have better control over cache expiration.

@Benjamin
Hopefully the above makes my situation clearer. I already avoid the serialization overhead on the server because I'm caching the actual RPC response. So the only particular performance advantages I hope to gain are:
- avoiding creation and serialization of the RPC request on the client
- avoiding deserialization of the RPC request on the server
- better performance of Varnish cache serving quasi-static resources from a cache I can control than App Engine servicing RPC requests from a cache that I can't control.

I'm assuming the first 2 are negligible and the 3rd one is what I'm curious about. It's an experiment.

All I want to do is retrieve RPC-serialized objects from the server via GET, with two very simple request parameters as part of the url path. GWT-RPC already happens over HTTP, and what I'm looking to do wouldn't require any "frankensteining" that I can see. It should just take a couple lines in a RemoteServiceServlet and a couple on the client.

Alternatively I'd be happy with any other method of serialization that would allow me to leverage my existing code that uses RPC serialization with custom field serializers, and to serve this serialized object via HTTP GET. I'd also be open to modifying my serialization process, but my hierarchy of serializable classes is pretty deep and I don't really want to create JS overlays or RequestFactory proxies for all of them.

GWT-RPC is already a functional serialization mechanism for getting my object to the client. I just want to request the object slightly differently.

-----

So I'm wondering:
1) is there a way to get the permutation strong name from the client even when running in Hosted Mode?

2) Are there gwt client libraries I can use to parse the RPC response and deserialize the object manually on the client, outside of the standard GWT-RPC request context? Maybe a client-side equivalent of RPC that has a decodeResponse() method?

3) Why are serialization policies permutation-specific? It seems that the serialization policies generated during a single compile should be the same. Why would they need to be browser- or locale-specific?

My existing system is caching RPC responses, and it just occurred to me that I may be caching an RPC response serialized with a given serialization policy but then serving it to a client that will then deserialize it with a different serialization policy. Seems like a bad idea. Both serialization policies would be generated from a single compile but might represent different browsers or locales.  So far in our production system accessed by many different browsers, there haven't been any problems.

Thanks again for any wisdom about the above,
Peter

Jens

unread,
Nov 3, 2012, 5:30:12 PM11/3/12
to google-we...@googlegroups.com
You can switch out the default RpcRequestBuilder of any GWT-RPC service. Your custom RpcRequestBuilder would overwrite doCreate() to create a RequestBuilder that uses GET instead of POST. Everything else should continue to work without any further modifications. To change the default RpcRequestBuilder you have to cast your RemoteService into ServiceDefTarget.

-- J.
Message has been deleted

Peter Warren

unread,
Nov 7, 2012, 1:54:28 PM11/7/12
to google-we...@googlegroups.com
Thanks, Jens! Your tip along with using getSerializationPolicyName() from the ServiceDefTarget worked like a charm.

I ended up using this on the client:
final ServiceDefTarget serviceTarget = (ServiceDefTarget) storage;
serviceTarget.
setRpcRequestBuilder(new RpcRequestBuilder() {
    @Override
    protected RequestBuilder doCreate(String serviceEntryPoint) {
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, "/my/url/"
                + key1 + "/" + key2);
        builder.setHeader(SERIALIZATION_POLICY_HEADER, serviceTarget.getSerializationPolicyName());
        return builder;
    }
});

And this on the server in my RemoteServiceServlet:
String moduleBaseURL = request.getHeader(RpcRequestBuilder.MODULE_BASE_HEADER);
String strongName = request.getHeader(Headers.SERIALIZATION_POLICY_HEADER);
SerializationPolicy serializationPolicy = this.getSerializationPolicy(moduleBaseURL, strongName);
MyResult result = MyService.getInstance().getResult(id);
Method method = MyService.class.getMethod("getResult", new Class[] { Id.class });
return RPC.encodeResponseForSuccess(method, result, serializationPolicy);
Reply all
Reply to author
Forward
0 new messages