Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GWT manually serialize domain object on server

The first thing my GWT app does when it loads is request the current logged in user from the server via RequestFactory. This blocks because I need properties of the User to know how to proceed. This only takes < 500ms, but it really annoys me that the app is blocked during this time. I already have the User on the server when the jsp is generated, so why not just add the serialized User to the jsp and eliminate this request altogether?

I have two problems keeping me from doing this:

  • I need to transform User to UserProxy
  • I need to serialize UserProxy in a way that is easy for GWT to deserialize.

I have not figured out a good way to do #1. This logic appears to be buried in ServiceLayerDecorator without an easy way to isolate? I may be wrong here.

The second one seems easier via ProxySerializer But how do I get my hands on the requestfactory when I am on the server? You cannot call GWT.create on the server.

I have been looking into AutoBeans but this does not handle #1 above. My UserProxy has references to collections of other EntityProxy's that I would like to maintain.

like image 346
Brad Avatar asked Mar 17 '12 18:03

Brad


3 Answers

You could use AutoBeans for this as well if you are able to make User implements UserProxy. It works since Proxies are interfaces with getters/setters:

interface UserFactory implements AutoBeanFactory
{
  AutoBean<UserProxy> user(UserProxy toWrap); // wrap existing instance in an AutoBean
}

Then on server you can create the autobean and serialize to json:

UserFactory factory = AutoBeanFactorySource.create(UserFactory.class)
AutoBean<UserProxy> userProxyBean = factory.user( existingUserPojo );

// to convert AutoBean to JSON
String json = AutoBeanCodex.encode(userProxyBean).getPayload();

On the client you can just use AutoBeanCodex.decode to deserialize JSON back to a bean

like image 124
Andrejs Avatar answered Nov 02 '22 11:11

Andrejs


You cannot call GWT.create on the server (or from any real JVM), but in many cases you can call a JVM-compatible method designed for server use instead. In this case, take a look at RequestFactorySource.create.

It can be a little messy to get the server to read from itself and print out data using RequestFactory - here is a demo example of how this can work (using gwt 2.4, the main branch has the same thing for 2.3 or so) https://github.com/niloc132/tvguide-sample-parent/blob/gwt-2.4.0/tvguide-client/src/main/java/com/acme/gwt/server/TvViewerJsonBootstrap.java - not quite the same thing that you are after, but it may be possible to use this same idea to populate a string in a proxy store that can be read in the client (seen here https://github.com/niloc132/tvguide-sample-parent/blob/gwt-2.4.0/tvguide-client/src/main/java/com/acme/gwt/client/TvGuide.java).

The basic idea is to create a request (including ids, invocations, and with() arguments so the proxy builder makes all the right pieces in a consistent way), and pass it into a SimpleRequestProcessor instance, which will then run it through the server pieces it normally would. (Any entity management system probably should still have the entities cached to avoid an additional lookup, otherwise you need to model some of the work SRP doesn internally.) The ProxySerializer, which wraps a ProxyStore, expects to have full RF messages as sent from the server, so a fair bit of message bookkeeping needs to be done correctly.

like image 1
Colin Alworth Avatar answered Nov 02 '22 10:11

Colin Alworth


I found the answer on the GWT Google Group. All credits go to Nisha Sowdri NM.

Server side encoding:

DefaultProxyStore store = new DefaultProxyStore();
ProxySerializer ser = requests.getSerializer(store);
final String key = ser.serialize(userProxy);
String message = key + ":" + store.encode();

Client side decoding:

String[] parts = message.split(":", 2);
ProxyStore store = new DefaultProxyStore(parts[1]);
ProxySerializer ser = requests.getSerializer(store);
UserProxy user = ser.deserialize(UserProxy.class, parts[0]);
like image 1
Dominik Avatar answered Nov 02 '22 10:11

Dominik