I would like to spend some time to write a post about the best practices I have learnt using GWT and which common pitfalls to avoid.
When I have started to use GWT, the first problem I encountered was the development of the RPC services:
- They need two interfaces.
- They should be implemented by java Servlet.
- The serialization of objects is a difficult to manage.
- Their interface should not follow the java common best practices.
The 1st point is solvable using the
maven-gwt-plugin: this will generate the
Async interface as well the Servlet mapping on the
(it doesn’t work well with generics actually).
The drawbacks of the 2nd point instead is that if you are using Spring, the Servlet
are instantiated outside the Spring context; you cannot apply any aspect on them.
(e.g. they can’t be transactional). If you want the GWT service to be managed
by the Spring context, you need to create two instances of the same interface:
- A Spring bean
- A Servlet that delegates all method implementations to the Spring bean.
This is a possible implementation of that:
So if we need to implement a GWT service interface, we have to extend and implement our interface. Then we have to write our Servlet that extends and implements the same interface, delegating all method implementations to the Spring bean.
This is the example for a interface:
Writing this code for each service is very boring job of course, but your IDE can do it for you.
How you can notice the expose the concrete type
instead of the interface. It is about the
4, exposing makes
GWT creating one snipped of code for each possible implementation of . This
will generate a oversize codebase and a longer compilation time. Indeed it is against
any Java common best practice, but you have to keep in mind that GWT is not Java.
About the serialization of object:
- They should implement Serializable or IsSerializable
- They should have an empty default constructor
- All transient or final(so crazy) fields will be ignored.
- All dependent object should follow the same rules.
Of course GWT should know the codebase of the type for each dependent not final/transient field. The trick is put the source as dependency of the maven module contains the GWT plugin. However it is not enough because not all standard java classes are supported (no Calendar for example), so also if you include a lib source code, unlikely will be supported. Some libs offers a separate module for the GWT support, as Google Guava does. But they are not so common. Alternatively you can write the serialization for a particular class yourself. However is not so trivial.
How we have seen there is no simple solutions for the
4, having a serializable object, is
complex and unlikely good integrated in our domain. If for example we are using Hibernate as
ORM, serializing an Hibernate entity is the worst thing you can do. It will serialize your whole
DB in the worst case. However in many case you have to deep copy the object because GWT is not
able to serialize the Hibernate custom collections. And usually you don’t need them in client side.
At the end using GWT RPC require to write a GWT service layer with its own domain objects. They will likely contain already preprocessed data, like the formatted date (no joda time on GWT, neither Calendar). At the end of the day, the promise to use your domain object in the client side is a lie.
In the next post I will describe a way to use a JSON REST api with GWT.
The complete code is available at GWT RPC Spring Scaffolding gist.