JDAL Vaadin Spring Integration
Spring UIProvider
To allow spring injection in Vaadin components, we need to declare JDAL UIProvider in web.xml file
<context-param> <description>Vaadin application class to start</description> <param-name>UIProvider</param-name> <param-value>org.jdal.vaadin.SpringUIProvider</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>Vaadin Application Servlet</servlet-name> <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> <init-param> <param-name>UI</param-name> <param-value>org.example.SomeUIClass</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Vaadin Application Servlet</servlet-name> <url-pattern>/*</url-pattern>
Vaadin UI Spring Scope
JDAL provides a Spring scope for Vaadin UI instances. To use it, declare de scope in bean configuration file as follows
<!-- Vaadin scoped beans are linked to UI class instances --> <bean id="vaadinScopeConfigurer" class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="ui" value="org.jdal.vaadin.beans.VaadinScope" /> </map> </property> </bean>
Resource property editor
The resource property editor allow to inject Vaadin resources directly in bean definition files using the following prefixes:
- classpath: for ClassResources.
- theme: for ThemeResources.
- url: for ExternalResources.
For example, to declare an exit button with some icon, we could use somthing like
<bean class="org.jdal.vaadin.ui.action.ExitAction" p:caption="Exit" scope="prototype" p:icon="classpath:/org/freedesktop/tango/22x22/actions/system-shutdown.png" />
Injecting Spring Serializable Proxies into Vaadin Components
All Vaadin Components are linked to J2EE container session and must be serializable to allow session pasitivation and replication across cluster nodes.
This prevents injecting directly Spring beans into Vaadin Components as these are usually non serializable or they shouldn't be serialised at all. For this reason, Spring beans dependences are usually declared as transient and initialized after deserialization. Although this works, it doesn't seem a very natural way to integreate both frameworks.
To solve this problem, the JDAL approach replace the Spring bean dependences with AOP serializable proxies in the Spring context, or directly in Vaadin component fields as well. The proxies resolve the context dependences in the deserialization process, allowing container session pasitivation and replication.
Serializable Proxy Configuration
To enable serializable proxies use the following bean definitions in context configuration file:
<!-- Enable @SerializableProxy support --> <bean id="serializableAnnotationBeanPostProcessor" class="org.jdal.aop.config.SerializableAnnotationBeanPostProcessor" /> <bean id="serializableProxyAdvisor" class="org.jdal.aop.SerializableProxyAdvisor" scope="prototype"/>
To replace a bean in the Spring context globally, we can use the <jdal:serializable-proxy> tag in jdal spring custom namespace.
<bean id="someBean" class="some.package.SomeBean"> <property name="someProperty" value="someValue" /> <jdal:serializable-proxy /> <!-- Replace this bean with a serializable proxy --> </bean>
Or we can use @SerializableProxy annotation on the bean types.
@Component @SerializableProxy public class StoreService { ... }
Finally, we can replace only the reference in the component without touching the Spring context, just using the annotation in the autowired field.
public class MainLayout extends VerticalLayout { @Autowired @SerializableProxy private CustomerDao customerDao; }
Using Spring MessageSource in Vaadin Applications
Just declaring a spring message source as serializable proxy allows us to inject it anywhere
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames" value="i18n/i18n" /> <jdal:serializable-proxy/> </bean> <bean id="staticMessageSource" class="org.jdal.beans.StaticMessageSource"> <constructor-arg ref="messageSource" /> </bean>
We can also use it in spring bean definition files using the 18n: prefix.
<bean id="foo" class="Foo" p:name="i18:name" />
Spring Framework custom namespace for Vaadin
One of the major drawbacks of the previous version (1.3.1) is the high number of bean definitions required in spring configuration files. Version 2.0 includes a custom namespace that greatly simplifies the context configuration.
<vaadin:defaults />
Used to declare the default settings required for JDAL. Define the following beans:
- Vaadin Paginator: Default pager for tabless.
- Default Table Actions: Default actions for tables
- Default Gui Factory: Default Vaadin component factory.
- Custom Editor Configurer: Register defaultPropertyEditors for images and icons
<vaadin:table>
Used to declare a pageable table linked to an entity. Represents a considerable improvement over the previous version which required us to declare two beans per pageable table.
Now, declaring and configuring a server side pageable table is very straightforward:
<!-- Book Table Definition --> <vaadin:table entity="org.jdal.samples.model.Book" filter-form="bookFilterEditor" scope="prototype"> <vaadin:columns> <vaadin:column name="id" display-name="ID" width="60" align="center"/> <vaadin:column name="name" display-name="Name" width="300" align="left" /> <vaadin:column name="author" display-name="Author" width="150" align="left" sort-property-name="author.name" /> <vaadin:column name="category" display-name="Category" width="200" align="left" sort-property-name="category.name" /> <vaadin:column name="isbn" display-name="ISBN" width="150" align="left" /> <vaadin:column name="publishedDate" display-name="Published Date" width="150" property-editor="customDateEditor"/> </vaadin:columns> </vaadin:table>
<vaadin:navigator-action>
Used to declare a button handler that load a bean from context as Vaadin View.
<vaadin:button-bar>
Used to declare a horizontal or vertical layout with a list of actions. For example to create the navigation var of sample application, we declare the following button bar:
<!-- Top button menu --> <vaadin:button-bar id="buttonBar" scope="prototype"> <vaadin:actions> <vaadin:navigator-action caption="Books" view-name="bookMainView" icon="classpath:/org/freedesktop/tango/22x22/mimetypes/x-office-address-book.png"/> <vaadin:navigator-action caption="Authors" view-name="authorMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/preferences-desktop-theme.png"/> <vaadin:navigator-action caption="Categories" view-name="categoryMainView" icon="classpath:/org/freedesktop/tango/22x22/places/folder.png" /> <vaadin:navigator-action caption="Users" view-name="userMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/system-users.png"/> <vaadin:navigator-action caption="About" view-name="aboutMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/help-browser.png"/> <bean class="org.jdal.vaadin.ui.action.ExitAction" p:caption="Exit" p:icon="classpath:/org/freedesktop/tango/22x22/actions/system-shutdown.png" /> </vaadin:actions> </vaadin:button-bar> <!-- Make main views ui scoped to avoid recreating thems in every page change --> <bean id="bookMainView" class="org.jdal.samples.vaadin.BookMainView" scope="ui" /> <bean id="authorMainView" class="org.jdal.samples.vaadin.AuthorMainView" scope="ui" /> <bean id="categoryMainView" class="org.jdal.samples.vaadin.CategoryMainView" scope="ui" /> <bean id="aboutMainView" class="org.jdal.samples.vaadin.AboutMainView" scope="ui" /> <bean id="userMainView" class="org.jdal.samples.vaadin.UserMainView" scope="ui" />