How to implement an EntityProxy interface without frustration

One of new GWT 2.1 features is RequestFactory; “an alternative to GWT-RPC for creating data-oriented services.”. The main drive behind many of the new features is Spring Roo with GWT support. RequestFactory offers some great advantages over GWT-RPC, but the bad news is, it’s very lightly documented. Also as RequestFactory adds an extra layer of abstraction with advanced functionality, like keeping objects synchronized, it makes it difficult to use and understand in practice without good documentation.

Part of the difficulty of using RequestFactory and more specific EntityProxy is the implied usage conventions. With EntityProxy client/server code part of the implementation depends on implicit naming conventions. This is similar to GWT-RPC where the service and serviceAsync interfaces are bound by naming conventions, not code. As a consequence it’s easy to forget or create invalid code, which you unfortunately will find out at runtime. Leading to longer development cycles and frustration.

Implementing an EntityProxy

In this article the focus is on implementing an EntityProxy interface without getting run time error because you missed some implicit convention. I tried to create a comprehensive list as possible, but don’t sue me if I missed something… I’m assuming from here you have a basic understanding of how to use an EntityProxy.

EntityProxy is the core of an alternative method to transfer data between client and server. With GWT-RPC you need to create Data Transfer Objects(DTO). A DTO contains simple getters and setters that mirror your server side data object. A DTO is necessary because your server side objects can not be used on the client side, due to dependencies on libraries that can’t be compiled with GWT. A big disadvantage of a DTO is that you need to copy data from the DTO into and from the server object. Code you need to write manually. With EntityProxy instead of creating a DTO you create an interface, and specify on that interface the getter and setter methods. GWT will generate a class for you from that interface. A small disadvantage of this approach is that is more difficult to debug. You have to include the generated path in your source path to access the code if you need and your data in the generated class is somewhat buried. But together with RequestFactory it gives you a simpler approach to keep data synchronized on the client. A very simple Employee EntityProxy example with a getter and setter method that relates to a field name in you server side class Employee would look as follows:

    @ProxyFor(Employee.class)
    public interface EmployeeProxy extends EntityProxy {

       String getName();

       void setName(String name);

       @Override
       EntityProxyId<EmployeeProxy> stableId();
    }

With this interface, anytime you need an Employee object on the client you use the EmployeeProxy and on the server side you program with the Employee class. Meaning you may never use one of them on the other side! This approach with the DTO interface looks like the same overhead as a DTO class. But it frees you from having to write the copy code from the data class into the DTO class and back. With the RequestBuilder you create instances of the EntityProxy objects, but I won’t go the details on how to do that in this article.

Rules to obey

When implementing an EntityProxy interface there are a number of conventions you need to know and follow. The main cause of problems simple problems when using EntityProxy are because there is no relation between the EntityProxy interface and the server side data object. As a consequence you have no compile time support to check if you missed something, like if the methods you put on the interface actual exist on the data class on the server. Incorrectly implementations result in run time errors and are sometimes buried in the stack trace or hard to find in production if the stack trace was not logged. Al you get in the client is an empty error message. GWT documentation already names a number of the items shown below, but here is an more comprehensive list:

For you EntityProxy interfaces:

  • Each method in your interface must have an matching method in the server side class.
  • Only get or set methods are allowed in your interface.
  • You don’t have to add getters/setters for all member fields of server side data class in the EntityProxy interface, only those you want to use on the client side
  • If you add a setter method to your EntityProxy you must add a getter or else the setter will have no effect.
  • The naming of the getter and setter method must match a field member in your server side class. If you have a getLocation() getter you must have a field named location in the server data class. This restriction has been removed in GWT 2.1.1. But when using an Editor with an EntityProxy you must name the Editor field (in Class) or method (in Interface) exactly as the getter/setter.
  • While you need matching getter/setter/fields the getters and setter don’t have to operate on the same type as the field, but it must match the type of the getter/setter method. So it correct to have an field of type Integer, while you getter/setter methods in the server side object and EntityProxy operate on String.
  • GWT 2.1 doesn’t support native types (like int) as return type for methods in the proxy interface and only List and Set data grouping types are valid. For the latter it means you can for example return an ArrayList, but the return type of the method must be List
  • In the example above the stableId() is override from the interface EntityProxy. You must always override the stableId() method can override the stableId() method so it will be easier to use with the RequestFactory find method, but it’s not a requirement.

While your server side data object have no knowledge of the client side, and are not dependent on GWT they must meet some requirements to make things work. Here is the list for your server side data objects:

  • A no-arg constructor. This may be the implicit default constructor. This is required unless you use a Locator, which takes the control of object instantiation.
  • The data class must have a method getId() that returns a String or Long any type (Since GWT 2.1.1) that represents the persisted ID.
  • A getVersion() method, which returns a non null value. This value should be incremented or changed each time that specific instance of the object is persisted. GWT uses this version number to check whether the object was changed. Some ORM frameworks have support for Versioning and thus can be implemented with ease. Since GWT 2.1.1 the return type is no longer limited to Integer and with a Locator you can use a different name for the method instead of getVersion().
  • A getVersion() method my not return null. GWT will not set version if you create a new object on the client. When a new object is persisted GWT will call getVersion() and you must make sure it doesn’t return null, even while it was never set to any value.
  • A method: public static entity_type find<entity_type>(id_type id). This method is used by RequestFactory find method to lookup individual instances. It seems possible since GWT 2.1.1 to do have a non static method by using a Locator. But I haven’t tried it.

To summarize. As you’ve seen you need to keep an eye on a number of rules to correctly implement and use EntityProxy interfaces. It might be possible in the future better tool will be released or some limitations will be lifted. For now keep the list at hand when implementing EntityProxy interfaces or you will become frustrated each time you hit a run time error…

This article only covered EntityProxy but to correctly and efficient use the RequestFactory there is enough material to write about. Thomas Broyer wrote two articles on GWT 2.1.1 RequestFactory Part I and Part II that are a good starting point. Finally if you find other rules I’ve missed let me know.

UPDATE January, 26 2011: Thanks to Thomas Broyer for commenting and pointing out some incorrect claims. Based on his feedback I’ve updated the text.

This entry was posted in gwt and tagged , , . Bookmark the permalink.

2 Responses to How to implement an EntityProxy interface without frustration

  1. Some of the constraints you list here are specific to GWT 2.1.0, and if you use RF you should really upgrade to 2.1.1!

    Namely:
    – you no longer need to have a field in your domain classes that match the properties defined on the EntityProxy
    – primitive types can be used: http://code.google.com/p/google-web-toolkit/source/detail?r=9437
    – with a Locator, you take the control on object instantiation, so you might have domain objects without a no-arg constructor
    – the getId() (or you can name it otherwise if you use a Locator) return type is no longer limited to String or Long (I’m using composite IDs, i.e. another object with several fields, it has to map to a ValueProxy though)
    – the getVersion() (or you can name it otherwise if you use a Locator) return type is no longer limited to Integer, you really use the type of object you want (we’re using longs): http://code.google.com/p/google-web-toolkit/issues/detail?id=5368
    – the static findXxx: you don’t need it if you use a Locator (not ServiceLocator, see http://twitter.com/BobVawter/status/29932761636675584 )

    Another one is just plain wrong: you don’t have to override stableId(), doing so only makes RequestFactory’s find() easier to use (because Java generics are plain broken to begin with)

  2. Hilbrand says:

    @thomas. Thanks for the comments. I’ve updated the post and include your points. Most of the items you mention are related to the Locator. I did see some references to the Locator. But, if I’m correct, there is no information in the documentation (not here: http://code.google.com/webtoolkit/doc/latest/DevGuide.html) on how to use the Locator. Which makes it difficult to start using it.