Ralf Wehner's Blog

Just another WordPress.com weblog

Combining vaadin and classic spring mvc into one simple spring-boot application

with 2 comments

vaadin, a Java web framework.

As part of my freelance work one day i’ve noticed the very cool project vaadin which is based on google’s GWT and helps to create powerful web applications that will run on differnt browsers and devices. Building a web application with vaadin is analogue to build a SWING or Java FX application. You will create the “pages” (UIs) only in JAVA code and use layout objects e.g. the vertical layout to arrange all widgets like input fields, buttons, borders, labels, views, etc. on your page. There is no need to bother with HTML, javascript or css when you start writing your application, you can simply concentrate in implementing your business logic.

How does it work? When the user navigates to the vaadin application the server provides a JAVA SCRIPT that is loaded and running on the browser to renders the application page. All user actions will be syncronized to the server via RCP (AJAX GET and PUT) calls that will exchange information in JSON form and to the server. In user’s point of view a vaadin application behaves and feels like a native program, for example a rich client written in JAVA SWING. But in differnce to this it will simply run in your browser and there is no need to install software before. It is very impressive what huge functionlity you will get without the effort to search and embed JAVA-SCRIPT elements or code like jquery plugins. To get a better understanding how vaadin works, please have a look a the vaadin book which describes the framework well. The vaadin user interface will show you losts of useful widgets, layouts, databindings, concepts and addons and the corresponding source code and documentation.

What i want to do

Because i am a great fan of spring, especially spring-web-mvc, i want to find out a solution how to integrate a more or less complex vaadin application within a spring mvc application.  So the result have to

  • contain a spring mvc dispatcher servlet which provides the classic html pages,
  • the vaadin servlet used to serve the vaadin application and
  • it should be deployed as a simple war file, running within a tomcat or standalone.

Lets start

Before we start, all source code of this demo is hosted on github and can be cloned from here.

To be able run the application stanalone and within a simple web container like tomcat or jetty, i decided to used the new spring-boot project.

When starting a spring boot application, spring-boot determines the classpath and tries to find out which components are present. It loads the main application class, looks for the spring configuration, determines classes in packages and its annotations and looks for files in conventional pathes like application.properies or logback.xml etc. To pull up the vaadin servlet in combination with spring-boot i integrated the brand new vaadin4spring project into my classpath which makes it very easy to add UIs into the vaadin application.

The vaadin4spring project

First, checkout the project from github and install the artifacts into your local repository.

$ # cd into a directory where you want to checkout the vaading4spring project
$ git clone https://github.com/peholmst/vaadin4spring
$ cd vaading4spring
$ mvn install -DskipTests

The project comes with some example projects that are worth to open and have a look.

I think it is only a matter of time when this project will be published into spring’s or the global maven repositories so you can avoid cloning and building this project locally. But currently, it is necessary.

The demo application

maven’s pom.xml

Our demo application starts with a pom.xml which contains the dependencies to the vaadin4spring project, to spring-mvc, spring-boot and the spring-boot-maven-plugin. The spring-boot-maven-plugin is responsable to start the application from the shell, simply typing mvn spring-boot:run.

<?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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.wehner.demo.vaadin</groupId>
    <artifactId>vaadin-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>vaadin-demo</name>
    <description>Vaadin Demo project</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <!-- spring boot for mvc and thymeleaf -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- spring boot for vaadin, see: https://github.com/peholmst/vaadin4spring -->
        <dependency>
            <groupId>org.vaadin.spring</groupId>
            <artifactId>spring-boot-vaadin</artifactId>
            <version>0.0.3-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-themes</artifactId>
            <version>7.2.4</version>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client-compiled</artifactId>
            <version>7.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <scope>runtime</scope>
        </dependency>

    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>demo.vaadin.Application</start-class>
        <java.version>1.7</java.version>
    </properties>

    <build>
        <plugins>
            <!-- spring-boot-maven-plugin used to start application in debugging mode
                on port 8000 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
<!--                 <configuration>
                    <jvmArguments> -Xdebug
                        -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
                    </jvmArguments>
                </configuration>-->
            </plugin>
        </plugins>
    </build>

</project>

The main configuration file application.properties

The application.properties is placed in folder /src/main/resources and contains the URL mapping for all requests that are intended for the vaadin servlet. This is important for a clear separation which servlet have to process a request, the VaadinServlet or spring’s DispatcherServlet.

vaadin.servlet.urlMapping=/myUI/*

# Allow Thymeleaf templates to be reloaded at dev time
spring.thymeleaf.cache: false
server.tomcat.access_log_enabled: true
server.tomcat.basedir: target/tomcat
#logging.level.org.springframework.security: INFO

The main application and the spring configuration class

The main application class Application also contains the spring configuration, configures spring-boot using the SpringApplicationBuilder class and starts up the spring boot process. It is referred in mavens  pom.xml to specify the application’s main class, see <start-class>demo.vaadin.Application</start-class>.

package demo.vaadin;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages="demo")
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder().sources(Application.class).web(true)
                .logStartupInfo(true).showBanner(true).run(args);
    }
}

The vaadin UI class

Using the vaadin4spring project it is very simple to integrate a vaadin UI-classes into the vaadin servlet. Just implement the abstract UI class and add the annotation @VaadinUI to the class. Here is one of the two UIs i have implemented into the demo application:

package demo.vaadin;

import org.vaadin.spring.VaadinUI;

import com.vaadin.server.ExternalResource;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.AbsoluteLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
import com.vaadin.ui.UI;

@VaadinUI(path = "/simple")
public class SimpleVaadinUI extends UI {

    private static final long serialVersionUID = 1L;

    @Override
    protected void init(VaadinRequest vaadinRequest) {

        Label label = new Label("Hello! I'm another simple UI!");
        Link linkToSpring = new Link("Back to spring's Thymeleaf",
                new ExternalResource("/"));

        AbsoluteLayout absoluteLayout = new AbsoluteLayout();
        absoluteLayout.addStyleName("outlined");
        absoluteLayout.setSizeFull();

        absoluteLayout.addComponent(label, "top:10px; left:10px");
        absoluteLayout.addComponent(linkToSpring, "top: 100px; left: 50px");

        setContent(absoluteLayout);
    }
}

You will access the application in your browser when opening the URL http://localhost:8080/myUI/simple. The url is a combination of the vaadin.servlet.urlMapping property and the path attribute in @VaadinUI.

Adding spring-mvc functionality

To add the spring-mvc functionality according to spring-boot you only have to implement a Controller class with @Controller and @RequestMapping annotation and add the spring-boot-starter-web or spring-boot-starter-thymeleaf artifact to the project.

For this demo i have used a sample code which comes directly from spring-boot project is written by Rob Winch and taken from the example spring-boot-sample-web-ui.

package demo.ui.controller;

import ...
...
/**
 * @author Rob Winch
 */
@Controller
@RequestMapping("/")
public class MessageController {
    private final MessageRepository messageRepository;

    @Autowired
    public MessageController(MessageRepository messageRepository) {
        this.messageRepository = messageRepository;
    }

    @RequestMapping
    public ModelAndView list() {
        Iterable<Message> messages = this.messageRepository.findAll();
        return new ModelAndView("messages/list", "messages", messages);
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView create(@Valid Message message, BindingResult result,
            RedirectAttributes redirect) {
        if (result.hasErrors()) {
            return new ModelAndView("messages/form", "formErrors", result.getAllErrors());
        }
        message = this.messageRepository.save(message);
        redirect.addFlashAttribute("globalMessage", "Successfully created a new message");
        return new ModelAndView("redirect:/{message.id}", "message.id", message.getId());
    }
...
}

The spring-web-mvc part uses Thymeleaf as a template engine to create the HTML output. It is a very good alternative concept to the classic jsp technologie.

Source code and demo application

As mentioned at the beginning of this blog the source code is available in project spring-boot-vaadin-demo on github. For the impatience a running demo application can be downloaded here.

$ cd /tmp
$ wget https://s3.amazonaws.com/rwe-public/vaadin-demo-0.0.1-SNAPSHOT.war
$ java -jar target/vaadin-demo-0.0.1-SNAPSHOT.war

After you have received the war file and started the application you will see the demo in your browser using this url: http://localhost:8080/.

Advertisements

Written by rwehner

August 26, 2014 at 9:34 pm

2 Responses

Subscribe to comments with RSS.

  1. is there in spring-boot-vaadin-demo a jar file missing ?

    … \spring-boot-vaadin-demo>mvn clean spring-boot:run
    [INFO] Scanning for projects…
    [INFO]
    [INFO] ————————————————————————
    [INFO] Building vaadin-demo 0.0.1-SNAPSHOT
    [INFO] ————————————————————————
    [WARNING] The POM for org.vaadin.spring:spring-boot-vaadin:jar:0.0.3-SNAPSHOT is missing, no depende
    ncy information available
    [INFO] ————————————————————————
    [INFO] BUILD FAILURE
    [INFO] ————————————————————————
    [INFO] Total time: 2.428 s
    [INFO] Finished at: 2016-04-27T10:17:22+02:00
    [INFO] Final Memory: 9M/153M
    [INFO] ————————————————————————
    [ERROR] Failed to execute goal on project vaadin-demo: Could not resolve dependencies for project de
    .wehner.demo.vaadin:vaadin-demo:war:0.0.1-SNAPSHOT: Could not find artifact org.vaadin.spring:spring
    -boot-vaadin:jar:0.0.3-SNAPSHOT -> [Help 1]
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please read the following arti
    cles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

    Walter Krejcar

    April 27, 2016 at 9:22 am

    • Hi Walter,

      spring-boot-vaadin comes von maven central. Try to use the non-snapshot version (0.0.3) which is available on maven central.

      rwehner

      April 27, 2016 at 8:45 pm


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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: