GWT 2.1.1 RequestFactory – Part II

Last week, I posted a first article on GWT 2.1.1 RequestFactory, followed a few days later by one on GWT 2.1 Editors (and, as promised in the former, how to use them with RequestFactory). In this article, I'll deal with 3 topics I also promised to tackle: what changed since 2.1.0, how does RequestFactory compares to GWT-RPC, and finally how does it integrates with JSR-303 Bean Validation (feel free to jump directly your section of interest). But first, let's start with something I forgot to talk about in my previous article!

Chained persistence

When you're asked to retrieve a domain object from your datastore, you should use at most one instance of a given persisted object (e.g. if you're asked twice for the Person with identifier 1, you should return the same instance each time, or at least instances that live in the same context so that changes to one instance will be persisted when saving another instance representing the same entity). This is causing many incomprehensions. Fortunately, when using JPA or JDO, it's as easy as using a request-scoped transaction.

What's new in 2.1.1

RequestFactory saw its first stable release in GWT 2.1.0. In GWT 2.1.1, the server part was totally rewritten, and the client side was slightly reworked as well. But this is all transparent to the developer, and code that compiled and ran with GWT 2.1.0 should still work with GWT 2.1.1. The following will probably only be useful for people who started using RequestFactory in 2.1.0 and want to know which new things can benefit them.

Features GWT 2.1.1 provides are summed up in the release announcement:

How does RequestFactory compare to GWT-RPC

Contrary to GWT-RPC which shares the same objects on the client and server side, RequestFactory uses proxy interfaces on the client-side (whose implementation is automatically generated). Thus, your real objects stay on the server, and are therefore not subject to the constraint of being translatable to JavaScript (remember having to fight with Hibernate's enhanced collections and lazy-loading until hibernate4gwt and gilead?). That dychotomy also allows a single server-side domain object to be represented by different proxy interfaces on the client-side, each proxy exposing a different set of properties.

The drawback is of course that there's a bit of redundancy (having to re-declare methods on the client-side interface), but on the other hand it brings flexibility and, if you ask me, removing the "must be translatable" constraint is enough to justify it.

It's worth mentionning that the dichotomy actually already existed in GWT-RPC in the service interfaces (synchronous, implemented by your RemoteServiceServlet, and asynchronous, used on the client-side).

Despite removing the "must be translatable" constraint, RequestFactory comes with a number of limitations regarding the types that can be transported: only primitive types and their boxed classes, enums, strings, dates (java.util.Date), BigInteger and BigDecimal, other proxies, and finally java.util.List and java.util.Set of any of the above, can be used. RequestFactory doesn't (yet!) support polymorphism (which means you have to use the exact classes I listed above; you cannot for instance declare a property of type java.util.SortedSet or java.sql.Timestamp).

However, because of those limitations, RequestFactory does not use serialization policies computed at compile-time, which means that your client and server code are much more loosely coupled than with GWT-RPC. With RequestFactory, provided the changes were made in a compatible way, you can independently deploy your client and server code, including using DevMode in -noserver mode against an already deployed application.

Actually, RequestFactory has all the advantages of De-RPC:

…and it works on Google AppEngine.

Finally, although the API and concepts are highly different, RequestFactory and its new (in 2.1.1) support for ValueProxy makes it possible to use it as a general-purpose RPC mechanism, at least to aid in migrating from GWT-RPC, and it's expected that De-RPC will die in favor of RequestFactory (don't worry, GWT-RPC will still be supported, we're only talking here about De-RPC, which never leaved the experimental state).

JSR-303 Bean Validation

When receiving a request to process, the RequestFactoryServlet applies the operations on the domain objects and validates them before processing any invocation. The default behavior for that validation is to use javax.validation, and that's why you might see an "Unable to initialize a JSR 303 Bean Validator" error in your server logs if you do not have a JSR 303 implementation (such as Hibernate Validator) in your classpath, and why you must have the validation API in your classpath for RequestFactory to work, to begin with.

ConstraintViolations are reported on the client side as a set of Violations to the onViolation() method of Receivers. Because validation is done before invocations are processed, all Receivers for a given RequestContext will receive the violations, and the default implementation of onViolation() is to call onFailure() with a fatal ServerFailure, which will by result in a RuntimeException.

What's next?

In the next article, I expect to write about the ServiceLayerDecorators, that is, the internals of the RequestFactoryServlet, where you can plug your own code to tweak a few things.