Skip to main content
Blog

AutoBean restrictions in GWT

By 15 mei 2013januari 30th, 2017No Comments

When transferring data from server to the client (javascript) application in GWT, one option is to use the built-in AutoBean framework.

According to the documentation, it’s pretty straightforward and problem free: http://code.google.com/p/google-web-toolkit/wiki/AutoBean
The reality though is, that the documentation may be a little to ‘concise’ and does not explictly cover all constraints.

The whole system in short work like this:
The dto’s that travel to the client need interfaces with getters, implement those on the server and feed the instances to a server side factory class (which also follows a defined interface).

[box type=”shadow”] Maps lose order after serializing to json. To preserve the order of a map, the easiest workaround is to split the keys and values into separate lists.
The map can than be rebuilt using the lists values, based on matching indexes.
[/box]

The next step is sending the data to the client and rebuild the instances there. On the server the factory renders the tree of instances to json, basically a map of nested maps. The json data is read back on the client, in our case from the page source. On the client, GWT will provide an implementation of a factory that can rebuild the object map. The json is fed to the factory and the instances become available to the client javascript application.

Take a look at a typical dto implementation for AutoBean usage.

public interface ServerDto extends Serializable {
    String getValue();
}
public class ServerDtoImpl implements ServerDto {
    private String value;

    @Override
    public String getValue() {
        return value;
    }
    
    public void setValue(String value) {
        this.value = value;
    }
}

To serialize to json, a factory should be implemented and some plumbing calls made:

public interface ServerDtoFactory extends AutoBeanFactory {
    AutoBean serverInfo(ServerDtoImpl serverInfo);
}

The plumbing:

 ServerDto dto = new ServerDtoImpl();
 dto.setValue("test");

 ServerDtoFactory factory = AutoBeanFactorySource.create(ServerDtoFactory.class);
 AutoBean autoBean = infoFactory.serverInfo(dto);        
 Splittable splittable = AutoBeanCodex.encode(autoBean);

 String json = splittable.getPayload();

The json output will be:

   { value : "test" } 

The json can then be, for instance, printed to a field named “json” of a javascript variable map named “server”.

To actually start using the json data as class instances, the following is needed in GWT, on the client:

ServerDtoFactory factory = GWT.create(ServerDtoFactory.class);
Dictionary dictionary = Dictionary.getDictionary("server");
String json = dictionary.get("json");
AutoBean autoBean = AutoBeanCodex.decode(factory, ServerDto.class, json);

ServerDto dto = autoBean.as();
[box type=”shadow”] Note that the dto instance on the client is not of the same implementation as we started out with on the server.
Instead, it is a generated / compiled implementation in javascript by GWT. This means that only the interface can be used to
work with. A common workaround it to use the original implementation to rebuild it’s own state from the given interface using a static factory method.
[/box]

Finally let’s look at the constraints here:

  • Only use built-in types or AutoBean compatible beans, meaning custom class fields can typically not be used
  • All data must be serializable, the interface should extend Serializable (or IsSerializable)
  • Lists (ArrayList) and Maps (HashMap) are supported, but can – only – contain built-in types (so even no AutoBean compatible beans)
  • AutoBean intefaces can have getter return values typed to other AutoBean compatible beans
  • Any map that travels to the client loses any ordering, lists do maintain the order in which they were defined

Still, even with all these constraints, the benefits of working with POJO beans is far greater than manually producing and parsing json text and converting that into code somehow.

[twitter name=”bwijsmuller”]