Vaadin Spring + MVP + Hibernate ... How?

Hello community!
I’m setting up my first Vaadin application with
Vaadin 7.5.6
and the
official Vaadin Spring 1.0.0
.
My vision is to have the following technologies included:

  • MVP Structure
  • Vaadin Spring 1.0.0
    [list]
  • Dependency injection
  • Scopes
  • SpringUI provider, SpringView provider + Navigator support

    [/list]
  • Spring ORM
    [list]
  • SessionFactory SpringBean creation (
    org.springframework.orm.hibernate4.LocalSessionFactoryBean
    )
  • TransactionManager SpringBean creation (for @Transactional annotation:
    org.springframework.orm.hibernate4.HibernateTransactionManager
    )

    [/list]
  • Hibernate ORM
    [list]
  • DTO Mapping
  • Database operations

    [/list]
  • Responsive Menu Layout (from
    official demo
    )

Because I’m new to Vaadin & MVP I was a bit confused when I saw the
unofficial MVP Addon from vaadin4spring
. It uses an Eventbus, which is new to me, and I’m asking myself if that’s the recommended way. Anyway, I started trying to build a MVP structure in the use of Vaadin Spring 1.0.0.
My current code looks like this:

UI class:

[code]
@Theme(“mytheme”)
@SpringUI
@EnableVaadin
public class MyUI extends UI
{
private static final long serialVersionUID = -5508691235080555823L;

@Autowired
SpringViewProvider viewProvider;

@Autowired
MainViewPresenter mainViewPresenter;

@Autowired
ApplicationContext applicationContext;

@Override
protected void init(VaadinRequest vaadinRequest)
{
    setLocale(Locale.GERMANY);
    Page.getCurrent().setTitle("MyApp");
    Responsive.makeResponsive(this);

    updateContent();
}

private void initNavigator(ComponentContainer content)
{
    setNavigator(null);

    Navigator navigator = new Navigator(this, content);
    navigator.addProvider(viewProvider);
    navigator.setErrorView(applicationContext.getBean(ErrorViewPresenter.class).getView());

    setNavigator(navigator);
}

private void updateContent()
{
    boolean userIsLoggedIn = VaadinSession.getCurrent().getAttribute("user") != null;

    if (userIsLoggedIn)
    {
        redirectToMainView();
    } else
    {
        // Cookie handling...

        Cookie myCookie = [...]


        if (myCookie != null)
        {
            [... getting user from cookie ...]


            VaadinSession.getCurrent().setAttribute("user", user);

            redirectToMainView();
        } else
        {
            setContent(applicationContext.getBean(LoginViewPresenter.class).getView());
          
            addStyleName("loginview");
        }
    }
}

private void redirectToMainView()
{
    initNavigator(mainViewPresenter.getView().getContent());
    addStyleName(ValoTheme.UI_WITH_MENU);
    mainViewPresenter.getView().setMenu(applicationContext.getBean(MenuViewPresenter.class).getView());

    setContent(mainViewPresenter.getView());
    removeStyleName("loginview");

[/code]MainView:

[code]
@SuppressWarnings(“serial”)
@UIScope
@SpringView(name = MainView.NAME)
public class MainView extends HorizontalLayout implements View
{
public static final String NAME = “MainView”;

private CssLayout menu = new CssLayout();
private CssLayout content = new CssLayout();

@PostConstruct
private void init()
{
    setSizeFull();
    addStyleName("mainview");

    // Menü
    menu.setPrimaryStyleName(ValoTheme.MENU_ROOT);
    menu.addStyleName("v-scrollable");
    addComponent(menu);

    // Content
    content.addStyleName("view-content");
    content.setSizeFull();
    addComponent(content);

    setExpandRatio(content, 1.0f);
}

@Override
public void enter(ViewChangeEvent event)
{

}

public CssLayout getContent()
{
    return content;
}

public void setMenu(Component menu)
{
    this.menu.removeAllComponents();
    this.menu.addComponent(menu);
}

[/code]MainViewPresenter:

[code]
@UIScope
@SpringComponent
public class MainViewPresenter implements Serializable
{
private static final long serialVersionUID = -898180058329832335L;

@Autowired
private MainView view;

@PostConstruct
public void init()
{

}

public MainView getView()
{
    return view;
}

}
[/code]HomeView:

[code]
@SuppressWarnings(“serial”)
@UIScope
@SpringView(name = HomeView.NAME)
public class HomeView extends Panel implements View
{
public static final String NAME = “”;

private VerticalLayout root;

@PostConstruct
private void init()
{
    addStyleName(ValoTheme.PANEL_BORDERLESS);
    setSizeFull();
    root = new VerticalLayout();
    root.setSizeFull();
    root.setMargin(true);
    root.addStyleName("dashboard-view");
    setContent(root);
    Responsive.makeResponsive(root);

    root.addComponent(buildHeader());

    Component content = buildContent();
    root.addComponent(content);
    root.setExpandRatio(content, 1);
}

private Component buildHeader()
{
    HorizontalLayout header = new HorizontalLayout();
    header.addStyleName("viewheader");
    header.setSpacing(true);

    Label titleLabel = new Label("Startseite");
    titleLabel.setSizeUndefined();
    titleLabel.addStyleName(ValoTheme.LABEL_H1);
    titleLabel.addStyleName(ValoTheme.LABEL_NO_MARGIN);

    header.addComponent(titleLabel);

    return header;
}

private Component buildContent()
{
    HorizontalLayout layout = new HorizontalLayout();
    layout.addStyleName("dashboard-panels");

    Label label = new Label("Welcome!!!");
    layout.addComponent(label);

    return layout;
}

@Override
public void enter(ViewChangeEvent event)
{

}

}
[/code]HomeViewPresenter:

[code]
@SpringComponent
@UIScope
public class HomeViewPresenter implements Serializable
{
private static final long serialVersionUID = 1504172856408784656L;

@Autowired
private HomeView view;

@PostConstruct
public void init()
{

}

public HomeView getView()
{
    return view;
}

public void setView(HomeView view)
{
    this.view = view;
}

}
[/code]My pom.xml looks like this:

[code]

<?xml version="1.0" encoding="UTF-8"?> 4.0.0
[...]


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

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-bom</artifactId>
            <version>${vaadin.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
   
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-server</artifactId>
    </dependency>
    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-push</artifactId>
    </dependency>
    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-themes</artifactId>
    </dependency>
    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-client-compiled</artifactId>
    </dependency>
   

    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-spring</artifactId>
        <version>1.0.0</version>
    </dependency>
   
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>4.2.1.RELEASE</version>
    </dependency>
   
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.3.11.Final</version>
    </dependency>
   
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.0</version>
            <configuration>
                <encoding>${project.encoding}</encoding>
                <source>${project.source.version}</source>
                <target>${project.target.version}</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <encoding>${project.encoding}</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
                <!-- Exclude some unnecessary files generated by the GWT compiler. -->
                <packagingExcludes>WEB-INF/classes/VAADIN/gwt-unitCache/**,    WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**</packagingExcludes>
            </configuration>
        </plugin>
        <plugin>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-maven-plugin</artifactId>
            <version>${vaadin.plugin.version}</version>
            <configuration>
                <extraJvmArgs>-Xmx512M -Xss1024k</extraJvmArgs>
                <webappDirectory>${basedir}/target/classes/VAADIN/widgetsets</webappDirectory>
                <draftCompile>false</draftCompile>
                <compileReport>false</compileReport>
                <style>OBF</style>
                <strict>true</strict>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>clean</goal> <!-- deleteMeIfItsNotWorking -->
                        <goal>resources</goal> <!-- deleteMeIfItsNotWorking -->
                        <goal>update-theme</goal>
                        <goal>update-widgetset</goal>
                        <goal>compile-theme</goal> <!-- deleteMeIfItsNotWorking -->
                        <goal>compile</goal>
                        <!-- disabled by default to use on-the-fly theme compilation -->
                        <!-- <goal>compile-theme</goal> -->
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.4</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-clean-plugin</artifactId>
            <version>2.6.1</version>
            <!-- Clean up also any pre-compiled themes -->
            <configuration>
                <filesets>
                    <fileset>
                        <directory>src/main/webapp/VAADIN/themes</directory>
                        <includes>
                            <include>**/styles.css</include>
                            <include>**/styles.scss.cache</include>
                        </includes>
                    </fileset>
                </filesets>
            </configuration>
        </plugin>

        <!-- The Jetty plugin allows us to easily test the development build by
            running jetty:run on the command line. -->
        <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>${jetty.plugin.version}</version>
            <configuration>
                <scanIntervalSeconds>2</scanIntervalSeconds>
            </configuration>
        </plugin>
    </plugins>

    <pluginManagement>
        <plugins>
            <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
            <!-- TODO Remove when http://dev.vaadin.com/ticket/14924 is resolved -->
            <plugin>
                <groupId>org.eclipse.m2e</groupId>
                <artifactId>lifecycle-mapping</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <lifecycleMappingMetadata>
                        <pluginExecutions>
                            <pluginExecution>
                                <pluginExecutionFilter>
                                    <groupId>com.vaadin</groupId>
                                    <artifactId>
                                        vaadin-maven-plugin
                                    </artifactId>
                                    <versionRange>[7.1.11,)</versionRange>
                                    <goals>
                                        <goal>resources</goal>
                                        <goal>update-widgetset</goal>
                                        <goal>compile</goal>
                                        <goal>compile-theme</goal>
                                    </goals>
                                </pluginExecutionFilter>
                                <action>
                                    <ignore></ignore>
                                </action>
                            </pluginExecution>
                        </pluginExecutions>
                    </lifecycleMappingMetadata>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>

</build>
[/code]My applicationContext.xml:

[code]

<?xml version="1.0" encoding="UTF-8"?>


<context:component-scan base-package=“de.myApp” />

</bean
[/code]My questions:

  1. As you can see I’m injecting the view in the particular presenter. Is this the right way? Or do you advise to use the unofficial MVP Addon?

    1.1. Does the View know the presenter? I heard a lot of variants about MVP…

  2. How can I save the state of a presenter? If I’m fetching a lot of data from a database in a presenter I want to save it although the user refreshes the page. Is it the @PreserveOnRefresh annotation over the UI class?

  3. Did i forgot any dependencies for my plan?

Best regards
shinchillahh2000

Hello shinchillahh2000,

I was trying to execute your example at my local environment but I am getting “null” instance of SpringViewProvider (I am wondering how you have initiazed spring application Context) . Would you please share your complete example or any good references if possible so that I can try to implement the same.

Any help will be highly appreciated.

  • Abhijeet Tayade

Hello Abhijeet,

I’m very sorry if you had issues to setup this example. Because I was playing with a few configurations there might be some mistakes…
My current spring references in pom.xml looks like this:

<dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-spring</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.0.2.RELEASE</version> </dependency>
“but I am getting “null” instance of SpringViewProvider”

  • I don’t know this issue, I just implemented the official Vaadin Spring AddOn and it worked out of the box! Maybe you should take a look at this
    vaadin article
    .


“I am wondering how you have initiazed spring application Context”

In my opinion the posted files are enough for testing this configuration… Please correct me if I’m wrong!

Regards
shinchillahh2000