Vaadin and Spring simple autowire

I have been using vaadin and spring in some of my projects but I don’t any find a simple way to manage autowiring for the spring bean to vaadin. I tried the add-on from the vaadin to integrate spring and vaadin into one context but it fail and to many changes in the configuration and I have tried the autowiringbeanfactory.java to become the servlet of vaadin but it only serve autowiring for the main application. If you have so many autowired annotation spread in your bean then all the above solution will not work.

I found a simple way to manage the autowiring by adding a very minimum configuration changes and it becomes my favorite solution to my next project. Please check below the configuration

1. Setup the Vaadin maven project in eclipse + JbossAS installation

2. Configure the pom as below


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>study</groupId>
<artifactId>testIntegrate</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Vaadin Web Application</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<vaadin.version>6.8.2</vaadin.version>
<gwt.version>2.3.0</gwt.version>
<gwt.plugin.version>2.2.0</gwt.plugin.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>vaadin-snapshots</id>
<url>http://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>vaadin-addons</id>
<url>http://maven.vaadin.com/vaadin-addons</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin</artifactId>
<version>${vaadin.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.2.RELEASE</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.1.2.RELEASE</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.1.2.RELEASE</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.1.2.RELEASE</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jsp-api</artifactId>
<version>6.0.35</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.0</version>
</dependency>
</dependencies>
</project>

3. Create the application-context.xml and put it into the WEB-INF with text below, please noted that to ensure the “annotation-config” is there because it will activate the autowiring via spring annotation such as @Autowire, @Component and etc


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
 http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
 <context:spring-configured />
 <context:annotation-config />

<context:component-scan base-package="study.testIntegrate" />

</beans>

4. Edit your web.xml in order to spring aware of context creation from the beginning, please follow as below


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 id="WebApp_ID" version="2.5">
 <display-name>Vaadin Web Application</display-name>
 <context-param>
 <description>Vaadin production mode</description>
 <param-name>productionMode</param-name>
 <param-value>false</param-value>
 </context-param>

<context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>/WEB-INF/applicationContext-spring.xml</param-value>
 </context-param>

<listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <listener>
 <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
 </listener>

<servlet>
 <servlet-name>Vaadin Application Servlet</servlet-name>
 <servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
 <init-param>
 <description>Vaadin application class to start</description>
 <param-name>application</param-name>
 <param-value>study.testIntegrate.MyVaadinApplication</param-value>
 </init-param>
 </servlet>
 <servlet-mapping>
 <servlet-name>Vaadin Application Servlet</servlet-name>
 <url-pattern>/*</url-pattern>
 </servlet-mapping>
</web-app>

5.  In order to make the injection to the autowiring to your bean working as expected then you should create a helper class to allow the spring knows your vaadin bean. You can include this class below into your source


import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.WebApplicationContext;

public class Inject {

static Application application;
 static ApplicationContext applicationContext;

public static void Inject(Object object) {
 if (applicationContext == null) {
 ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
 .currentRequestAttributes();
 HttpServletRequest request = requestAttributes.getRequest();
 HttpSession session = request.getSession(false);
 applicationContext = WebApplicationContextUtils
 .getRequiredWebApplicationContext(session
 .getServletContext());
 }

AutowireCapableBeanFactory beanFactory = applicationContext
 .getAutowireCapableBeanFactory();
 beanFactory.autowireBeanProperties(object,
 AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);

}

}

6. In order to use the helper class you my just call this static function “Inject” and pass the class you want to autowire, Please follow the sample class below


public class MyWindow extends Window {

@Autowired
 MyTest myTest;

Button button;

public MyWindow() {

 Inject.Inject(this);

 button = new Button();
 addComponent(button);
 button.addListener(Button.ClickEvent.class, this, "Check");
 }

public void Check(Button.ClickEvent event) {
 if (myTest != null) {
 showNotification("Ahhhaaa");
 }
 }
}

7. Then by calling the inject and pass the class itself then spring will autowire all the properties with the @autowire annotation for you. Here is the magic then. Very simple right to make the Vaadin aware to Spring autowiring with a very less configuration changes.

8. Here is my vaadin application init method


import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.Window;

@SuppressWarnings("serial")
public class MyVaadinApplication extends Application {
 private MyWindow window;

@Override
 public void init() {
 window = new MyWindow();
 setMainWindow(window);
 }

}

9. The last but not least is you dont forget to annotate your class with the @Component or @Service in order to let the spring bean scanner able to detect that it is a spring bean that need to be managed or autowired.

Hopefully my tutorial will make the integration of the vaadin and spring become easier so that the power of spring framework will available in combination with Vaadin superb technology.

One comment

  1. This actually works in my project with Hibernate 4.1.4 running on Tomcat 7 using the VaadinServlet as servlet in web.xml and without using any SpringContextHelper and various manual getBean-calls. The persistence unit is defined in a @Configuration annotated class defining @Bean EntityManagerFactory. Consider AUTOWIRE_BY_NAME in Inject as AUTOWIRE_AUTODETECT is now deprecated.

    Unless it’s possible to get @Autowire to “just work” this seems the most convenient way to go.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s