One problem that you’ll face in practically any application, including a Vaadin-powered one, is getting hold of data or external services. Usually this functionality is put in some kind of service facade, or for instance a repository. Vaadin presents a problem in this regard, because it uses classes on both client (compiled to JavaScript) and server. You can’t (and don’t want to) execute service methods on the browser. Luckily, thanks to modern frameworks and good old Java, this turns out to be incredibly easy.
If you want to decouple service from client classes, there used to be a time when you would either go for some static factory pattern (please, don’t) or use some kind of JNDI lookup to get a hold of the service objects or repositories. In modern times, you’re probably going for a dependency injection container (I like Spring, but the latest JEE6 beans have similar possibilities).
Using Spring, it’s as simple as defining a service in the Spring configuration and injecting it with the @Autowired annotation. With a little setup, this works perfectly in Vaadin.
I don’t think I’m telling anything new here, neither is the next part, but the combination makes for very non-intrusive, clean code.
If you start adding @Autowired annotations everywhere, you’ll soon end up with errors: Vaadin requires that any Java class is serializable. This is necessary to transmit information between the JavaScript web browser client application and the Java server code. Serialized object are sent between the two, to keep the internal states in sync.
However, many service classes won’t be serializable. A typical JPA repository will depend on an entity manager, which is not serializable.
The solution, is to mark those fields as “transient“, an often forgotten Java keyword that excludes fields from being serialized (among other things). The great thing about the @Autowired annotation is that it will inject dependencies every time a Java object is constructed. Also when it is de-serialized.
So each time the client sends an object, when it is constructed on the server, it will get autowired with your services.
It’s just that easy:
- Mark your dependencies toward services with @Autowired.
- Make them transient so that they don’t get serialized.