Vaadin & Spring: Using @Configurable in Vaadin Components
This post has been featured on This Week in Spring – March 12, 2013.
This is going to be one post in a series regarding integration and usage of the Spring Framework with Vaadin.
First of all, thanks to @toberl for giving me a little kickstart to try Vaadin and for his hints for basic integration.
Pretty much every item in Vaadin is or should be serializable. The state of the UI is stored on the server and many container persists sessions between restarts or distribute session among many servers. So if a UI component or a container isn’t serializable, persistent or distributable sessions won’t work. Notice the hint by the author of spring-vaadin: “You should use “transient” attribute for ApplicationContext and other’s context’s beans.”.
For example, if a Vaadin container contains an EntityManager as an attribute, the container isn’t serializable anymore and any view using this container won’t be serializable.
Spring Framework provides a great benefit regarding this problem through it’s pretty integration of @AspectJ. In case you don’t know, read this chapter in the reference documentation. You can use @Configurable to make pretty much any class eligible for Spring-driven configuration.
What does that mean? You can inject any dependency from the application context via @Autowired into any bean not directly managed by spring, for example:
import java.util.Collection; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.Property; @Configurable public class TestContainer implements Container { private static final long serialVersionUID = -6686019829605781376L; @PersistenceContext private transient EntityManager entityManager; @Autowired private transient SomeService someService; } |
This container is serializable, contains an EntityManager and some arbitrary service. Both of them are not serializable and therefor marked as transient. Springs @AspectJ and @Configurable provides both of them after using standard constructor “new TestContainer()” as well after instances are deserialized. The only drawback here is that one is not able to mark them as final and use constructor injection.
I’m using the following @AspectJ and load-time-weaving configuration
@Configuration @EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED) @EnableSpringConfigured @EnableAspectJAutoProxy public class LTWConfig { } |
together with the TomcatInstrumentableClassLoader:
<?xml version="1.0" encoding="UTF-8"?> <Context antiJARLocking="true" disableURLRewriting="true"> <Loader delegate="false" loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader" /> </Context> |
and can use the dummy TestContainer above like i would use any other class by just calling new and have Spring inject my dependencies.