Project

General

Profile

Actions

Sample-vaadin-spring-hibernate » History » Revision 5

« Previous | Revision 5/19 (diff) | Next »
Henning Blohm, 09.10.2012 09:52


A sample using Vaadin with Hibernate JPA and Spring on Z2

This sample is similar to Sample-spring-hibernate but differs (or rather extends) in that it show cases
the use of the Vaadin user interface toolkit in conjunction with Spring implemented annotation based
dependency injection over Z2 modularity.

As Spring is used throughout - in all modules - this is another practical application of How to Spring.

This sample is stored in z2-samples.vaadin-spring-hibernate.

Prerequisites

You need to run Java DB as network server on localhost. This is explained next.

The application will create a database "z2-samples"

Running a Java DB Network Server

Previously to Java 9, the Java SE Development Kit (JDK) by Oracle provided the Java DB - essentially the same as the Apache Derby DB. That is not the case anymore. However, we use that Database implementation in our samples. In order to run those samples that illustrate use of a relational database, please follow the instructions below to install and run Apache Derby. Could hardly be simpler.

Step 1: Download and Install

Unless you have done so already, download Apache Derby DB and follow the installation how-to.

Note: You do not need to unpack Apache Derby into some global folder on your system. Instead you may want to use some local folder under your user's home folder. There is no problem installing and runnning different instances and configurations at any time.

Step 2: Run

Let's assume you installed (well - unpacked) into a folder $DERBY_INSTALL. Also, let's assume some Java Runtime Environment is installed and ready.

Simply run the following on Linux or Mac OS:

cd $DERBY_INSTALL
java -jar lib/derbyrun.jar server start

On Windows run

cd %DERBY_INSTALL
java -jar lib\derbyrun.jar server start

That's it. Apache Derby will be waiting for connections on port 1527.

Run it

Like all samples, also this sample can be run as in How to run a sample. If you have the database, the fastest way to verify whether it runs is:

mkdir install
cd install 
git clone -b master http://git.z2-environment.net/z2-base.core
git clone -b master http://git.z2-environment.net/z2-samples.vaadin-spring-hibernate

# on Linux / Mac OS:
cd z2-base.core/run/bin
./gui.sh

# on Windows:
cd z2-base.core\run\bin
gui.bat

When running, go to http://localhost:8080/vaadin-spring-hibernate. You should see this:

Details

As in the other samples we have a re-use domain module. That is a recurring theme for many good reasons. In this case, the domain module com.zfabrik.samples.vaadin-spring-hibernate.domain is essentially like the similarly named module of Sample-spring-hibernate. The only difference is some more data access methods in the ThingyRepository.

The Vaadin Web application is defined in the module com.zfabrik.samples.vaadin-spring-hibernate.web. It has the usual Spring application context in web/WebContent/WEB-INF/applicationContext.xml that imports the thingy repository:

        <!-- import external components -->
        <bean id="thingyRepository" class="com.zfabrik.springframework.ComponentFactoryBean">
                <property name="componentName" value="com.zfabrik.samples.vaadin-spring-hibernate.domain/repository" />
                <property name="className" value="com.zfabrik.samples.vaadin_spring_hibernate.thingies.ThingyRepository" />
        </bean>

One particularity of using Vaadin in a modular environment is that Vaadin loads it's application class using the class loader that loaded the Vaadin classes (rather than the current thread's context class loader - as would be advised normally). When the Web application module is separated from the Vaadin module this can obviously not work too well (see also Enhancement #9809). To fix that you can tell Vaadin to use a custom class loader implementation (that - again - is loaded with the Vaadin class loader). That's why we declare the Vaadin servlet in web/WebContent/WEB-INF/web.xml list this:

<!-- Vaadin -->
<servlet>
  <servlet-name>VaadinServlet</servlet-name>
  <servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
  <init-param>
    <param-name>application</param-name>
    <param-value>com.zfabrik.samples.impl.vaadin_spring_hibernate.ApplicationImpl</param-value>
  </init-param>
  <!-- this because Vaadin doesn't use the thread's context class loader by default -->
  *<init-param>
    <param-name>ClassLoader</param-name>
    <param-value>com.zfabrik.vaadin.ContextClassLoader</param-value>
  </init-param>*
</servlet>

The Vaadin application class ApplicationImpl constructs a simple view hierarchy that containes a table view based on a lazy query container add-on data model that is fed from the domain module. To do so the corresponding query implementation (in lazy query container speak) has the repository injected:

@Configurable
public class ThingiesQuery implements Query {
    @Autowired
    private ThingyRepository repository;
    private Integer size;
    private boolean asc;

// ...
}

Please browse the actual UI code at com.zfabrik.samples.vaadin-spring-hibernate.web/java/src.impl/com/zfabrik/samples/impl/vaadin_spring_hibernate. It pretty much speaks for itself.

One important note on transaction management: In this example, transaction boundaries are enforced by a servlet filter once more. It is implemented in TransactionFilter and essentially looks like this:

public class TransactionFilter implements Filter {

        @Transactional
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                chain.doFilter(request, response);
        }

}

In other words, the only thing it really does is to make sure Spring spans a transaction (using the underlying JTA implementation) along the request. It is tempting to implement transaction demarcation in the Vaadin Application class. However, we cannot use the @Transactional annotation as there is no single request spanning method and using the JTA UserTransaction object is unfortunately not sufficient to "remote control" Spring's JTA wrappers. So the easiest work around is to use Spring TX demarcation right away (see also how to transaction management).

Updated by Henning Blohm over 11 years ago · 5 revisions