GWT RPC from non-servlet-container (1)
GWT is indeed a beautiful toolkit which does perfect jobs on client side. The most sparking point which I like most is that it is ALL ABOUT JAVA. So it inherits all those beautiful, highly efficient, well-thought-and-examined Java best practices, besides you have so many brilliant tools to use. And BANG!, it compiles cross-platform javascript codes which are run on most of popular browsers nicely. Since it is pure HTTP stuff, it can talks any kind of backend services via web using standard tech such as XML or JSON.
One minor speck is on GWT's proprietary RPC function, in where the backend must be Java and running in a servlet container. There might be some efforts taken on somewhere to let GWT RPC talk with services done other than Java, for example this one. I would like to try something simpler, let GWT RPC being served by non-servlet-container. Although servlet DO rule the market, but still there is alternative, such as Restlet.
The not so much a secret of GWT RPC
Thanks for GWT team's great job, the implementation of service-side GWT RPC is such a breeze which has good structure and not so difficult to get extracted out to be used outside servlet-container.Actually, the key part of a RPC call is consists of following statements:
For
RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass(), this);
RPC.invokeAndEncodeResponse(this, rpcRequest.getMethod(),
rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
RPC.decodeRequest
method:- The first argument, the
payload
, is a UTF-8 string directly read from the input stream client request, no weird encode/decode in it; - The second argument is the class which implements this RPC's
RemoteService
interface. So it is the target class in the RPC method is defined; - The last argument should be an instance of
SerializationPolicyProvider
. It provides an instance ofSerializationPolicy
which instructs how to serialize a Java object from/to a string payload. This is one of the tricky parts which I will explain later.
The
RPC.decodeRequest
method returns an instance of RPCRequest which takes all necessary data for the RPC call.The second statement is easier to understand, in which the first argument is the target instance on which this RPC call is to be invoked. The
RPC.invokeAndEncodeResponse
methods also return a UTF-8 string as result in JSON format (either success or failure). This string can be written back directly to GWT client (the current implementation is to gzip it first).According to aforementioned, seems we can serve a GWT RPC call from an non-servlet container by:
- Prepare an instance of
SerializationPolicyProvider
- Get to know where to load your class and how to create an instance from it;
- Read a UTF-8 string from HTTP request;
- Create an instance of
RPCRequest
and callRPC.invokeAndEncodeResponse
as illustrated above. - Write the UTF-8 string back to HTTP response, which content-type must be
application/json;charset=utf-8
Where SerializationPolicy
come from
SerializationPolicy
is something new after 1.4.RPC now generates a serialization policy file during compilation. The serialization policy file contains a whitelist of allowed types which may be serialized. Its name is a strong hash name followed by.gwt.rpc
. This file must be deployed to your web server as a public resource, accessible from a RemoteServiceServlet viaServletContext.getResource()
. If it is not deployed properly, RPC will run in 1.3.3 compatibility mode and refuse to serialize types implementing Serializable. (#1297)
Basically, for each
RemoteServiceServlet
implementation, there is one policy file generated which has a strong hash name. This name is passed by the RPC request payload. We can then use it together with the utility method SerializationPolicyLoader.getSerializationPolicyFileName
to load a SerializationPolicy
instance. The question is where to find that file under our non-servlet-container environment (says Restlet) and how smart it could be.The next installment I am going to talk about how to create a GWT application backending with Restlet. Hope it will be fun!
0 comments:
Post a Comment