Hibernate, Spring and Maven

Filed under: J2EE, Java, — Tags: HSQL, Hibernate, Maven, Spring, TDD — Thomas Sundberg — 2009-04-09

We will create a small Java application that connects to a database using Hibernate. We will use Spring to wire stuff together and Maven to build it.

Step 0 - Setting the stage
Step 1 - Creating unit tests to verify our Java code
Step 2 - Annotate the entities using EJB3 annotations
Step 3 - Create the database schema for the annotated entities with Maven
Step 4 - Connect the Data Access Objects, dao, to Hibernate using Spring for the wiring
Step 5 - Start Hypersonic SQL, HSQL
Step 6 - Run the integration tests to verify the entire setup using a database

Step 0 - Setting the stage

The problem we will solve is to create a small project that uses Spring to wire stuff together, Hibernate to communicate with a database and build everything using Maven.

Why?

I tried to get a similar setup to work and didn't find any solutions on the net. Or the solutions that I found was either incomplete or didn't solve the problem the way I wanted it to be solved.

I found a lot of un answered questions on mailing list and for some reason nobody wanted to describe something that I felt like a valid solution. Hopefully I will be able to solve some issues and clarify some things I have discovered.

Creating the project structure

I will use Maven so the file structure will be the standard maven setup like this:

    src -------+- main ----+- java ------
               |           |
               |           +- resources -
               |
               +- test ---+- java -------
                          |
                          +- resources --
    pom.xml

Create the first version of the pom.xml with this content:

    <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>com.agical.experimental</groupId>
        <artifactId>spring-hibernate-maven</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringHibernateMaven</name>
        <url>http://www.agical.com</url>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-idea-plugin</artifactId>
                    <configuration>
                        <downloadJavadocs>true</downloadJavadocs>
                        <downloadSources>true</downloadSources>
                        <jdkLevel>1.5</jdkLevel>
                        <jdkName>1.5</jdkName>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

The heading is a normal Maven heading

I define two things in the build section. First I want the project to be created for Java 1.5 so we can use annotations later.
Then I define how the maven-idea-plugin pluging should create project files for Intellij Idea. Note that I set both downloadJavadocs and downloadSources to true. this will enable me to browse the source code from Idea if I want to and get Javadocs automatic.
Somebody using Eclipse may want to do something similar. I don't use Eclispe unless I have to so I don't really care how this should be done.

We should now be able to create the first version of the projects files so we can do the rest of the editing in Idea. Create the project files for Idea with the command

mvn idea:idea

Any stuff needed to be downloaded will be downloaded and if everything goes well we should have a successful build.

    >mvn idea:idea
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'idea'.
    [INFO] ------------------------------------------------------------------------
    [INFO] Building SpringHibernateMaven
    [INFO] task-segment: [idea:idea]
    [INFO] ------------------------------------------------------------------------
    [INFO] Preparing idea:idea
    [INFO] No goals needed for project - skipping
    [INFO] [idea:idea]
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 1 second
    [INFO] Finished at: Mon Dec 15 22:25:33 CET 2008
    [INFO] Final Memory: 3M/6M
    [INFO] ------------------------------------------------------------------------

So, now we can launch Idea with our new project files and continue with something more interesting then setting up the project.

Step 1 - Creating unit tests to verify our Java code

Lets start with adding a dependency to JUnit. Add the dependency below to the pom.

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.4</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

The new pom should look something like this.

    <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>com.agical.experimental</groupId>
        <artifactId>spring-hibernate-maven</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringHibernateMaven</name>
        <url>http://www.agical.com</url>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-idea-plugin</artifactId>
                    <configuration>
                        <downloadJavadocs>true</downloadJavadocs>
                        <downloadSources>true</downloadSources>
                        <jdkLevel>1.5</jdkLevel>
                        <jdkName>1.5</jdkName>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.5</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>

Recreate the project files for Idea with mvn idea:idea as above.

We should now be able to create our test unit tests. To start with, lets create one to test a Data Access Object, dao. This will be the only class we test in this project. The other classes will be entities with simple setter and getters that can be generated. I don't see any point in testing generated source code if you don't build the tool generating them. The tests we create will be running using a database. I claim that this is by definition not a unit test but rather an integration test. At this stage it doesn't really matter, we will be using a in memory database so he performance impact will not be significant.

Create the class com.agical.experimental.SubscriptionDaoTest My test class looks like the one below:

package com.agical.experimental.dao;

import com.agical.experimental.entity.DefaultSubscription;
import com.agical.experimental.entity.FixedLineSubscription;
import com.agical.experimental.entity.Subscription;
import static junit.framework.Assert.assertNull;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.Ignore;

public class SubscriptionDaoTest {

    @Test
    @Ignore
    public void saveReadUpdateAndDeleteADefaultSubscription() {
        SubscriptionDao subscriptionDao = new SubscriptionDaoImpl();
        Subscription subscription = new DefaultSubscription();

        String subscriberName = "Marie";
        subscription.setSubscriberName(subscriberName);

        subscriptionDao.saveSubscription(subscription);

        Subscription fetchedSubscription = subscriptionDao.getSubscription(subscription);
        assertThat(fetchedSubscription.getSubscriberName(), is(subscriberName));

        String newSubscriberName = "Klara";
        fetchedSubscription.setSubscriberName(newSubscriberName);

        subscriptionDao.updateSubscription(fetchedSubscription);

        fetchedSubscription = subscriptionDao.getSubscription(subscription);
        assertThat(fetchedSubscription.getSubscriberName(), is(newSubscriberName));

        subscriptionDao.deleteSubscription(subscription);
        fetchedSubscription = subscriptionDao.getSubscription(subscription);
        assertNull(fetchedSubscription);
    }

    @Test
    @Ignore
    public void saveReadUpdateAndDeleteAFixedLineSubscription() {
        SubscriptionDao subscriptionDao = new SubscriptionDaoImpl();
        Subscription subscription = new FixedLineSubscription();

        String subscriberName = "Lena";
        subscription.setSubscriberName(subscriberName);

        subscriptionDao.saveSubscription(subscription);

        Subscription fetchedSubscription = subscriptionDao.getSubscription(subscription);
        assertThat(fetchedSubscription.getSubscriberName(), is(subscriberName));

        assertThat(fetchedSubscription.getSubscriberName(), is(subscriberName));

        subscriptionDao.deleteSubscription(subscription);
        fetchedSubscription = subscriptionDao.getSubscription(subscription);
        assertNull(fetchedSubscription);
    }
 }

If you enjoy TDD, test driven development, then you already know that defining a test like the one above is a great way to define the classes that we should implement. Only the stuff defined in the test will be implemented and if the tests define what we need, we will not create any waste since we will use everything we create and nothing more.

I will use Ideas great support to create the interfaces and the classes defined in the test. You should be able to compile everything when you have created all interfaces and classes. The code will not run properly since we implemented the production code. This is the next steps.

Step 2 - Annotate the entities using EJB3 annotations

You created all the interfaces and classes needed in the previous step. We need to annotate the entity classes so we can use Hibernate to handle the database communication.

To start, we need to add more stuff to our pom so we can get access to some Hibernate stuff, lets add the dependency javax.persistence below.

    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>persistence-api</artifactId>
        <version>1.0</version>
    </dependency>

Your pom should look something like this by now:

    <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>com.agical.experimental</groupId>
        <artifactId>spring-hibernate-maven</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringHibernateMaven</name>
        <url>http://www.agical.com</url>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-idea-plugin</artifactId>
                    <configuration>
                        <downloadJavadocs>true</downloadJavadocs>
                        <downloadSources>true</downloadSources>
                        <jdkLevel>1.5</jdkLevel>
                        <jdkName>1.5</jdkName>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.5</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.persistence</groupId>
                <artifactId>persistence-api</artifactId>
                <version>1.0</version>
            </dependency>
        </dependencies>
    </project>

Recreate the Idea project files.

We are now in the position that we can annotate the classes we want to persist. I plan to use a single table to persist the data for both the DefaultDescription and the FixedLineSubscription. The reason isn't more complicated then it is enough for this example. The difference between these entities will only be how they use there internal data, which we will not see anything of. The values persisted will be the same for both type of subscriptions.

Lets start to annotate the DefaultSubscription class.

package com.agical.experimental.entity;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
        name = "subscriptionType",
        discriminatorType = DiscriminatorType.STRING
)
@DiscriminatorValue("subdscription")
@Table(name = "subscriptions")
public class DefaultSubscription implements Subscription {
    private String subscriberName;
    private Long id;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setSubscriberName(String subscriberName) {
        this.subscriberName = subscriberName;
    }

    public String getSubscriberName() {
        return subscriberName;
    }
}

The class is annotated with these annotations:
The @Entity annotation tells us that this is an entity class.
We will use a single table strategy to handle inheritance, @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
We will differ the rows in the table using a column called subscriptionType that will be a called name = "subscriptionType" and be of the type String
For the DefaultSubscription we use the value @DiscriminatorValue("subdscription")
And finally, we will store the rows in a table called @Table(name = "subscriptions")

Then we want to define a primary key for the table. In this example I will create a surrogate key that will be an integer and doesn't have any connection to the data stored. It can be argued that this is a pretty bad solution, but in order to keep the example as small as possible I will accept this.

The annotation @Id tells us that this will be the Id column for this table.
It will be created automatically @GeneratedValue(strategy = GenerationType.AUTO)

Next we want to annotate the FixedLineSubscription class. It will be significant less annotations.

package com.agical.experimental.entity;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("fixedline")
public class FixedLineSubscription extends DefaultSubscription {
}

We have the @Entity annotation to define that this is an entity.
We have to add the discriminator value @DiscriminatorValue("fixedline")
The rest is handled through the inheritance system in Java.

Step 3 - Create the database schema for the annotated entities with Maven

We should now be done with some of the preparations and ready to add some more stuff the the pom so we can create the database schema.

We need some hibernate tools. Add the hibernate3-maven-plugin and configure it as below:

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>hibernate3-maven-plugin</artifactId>
        <version>2.1</version>
        <configuration>
            <components>
                <component>
                    <name>hbm2ddl</name>
                    <implementation>annotationconfiguration</implementation>
                </component>
            </components>
            <componentProperties>
                <drop>true</drop>
                <jdk5>true</jdk5>
                <outputfilename>schema.sql</outputfilename>
                <skip>${maven.test.skip}</skip>
                <hibernate.dialect>org.hibernate.dialect.HSQLDialect</hibernate.dialect>

                <!-- Connection properties
                    May be used or not by the plugin, when it will recreate the annotated tables
                    every time it is executed
                -->
                <hibernate.connection.driver_class>org.hsqldb.jdbcDriver</hibernate.connection.driver_class>
                <hibernate.connection.url>jdbc:hsqldb:mem:spring-hibernate-maven</hibernate.connection.url>
                <hibernate.connection.username>sa</hibernate.connection.username>
                <hibernate.connection.password></hibernate.connection.password>
                <!-- /Connection properties -->

            </componentProperties>
        </configuration>
        <executions>
            <execution>
                <phase>process-test-resources</phase>
                <goals>
                    <goal>hbm2ddl</goal>
                </goals>
            </execution>
        </executions>
        <dependencies>
            <dependency>
                <groupId>hsqldb</groupId>
                <artifactId>hsqldb</artifactId>
                <version>1.8.0.7</version>
            </dependency>
        </dependencies>
    </plugin>

We have a dependency to org.hibernate.dialect.HSQLDialect so we need to one more dependency. Add the dependency:

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-annotations</artifactId>
        <version>3.4.0.GA</version>
    </dependency>

A working pom should look something like this:

    <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>com.agical.experimental</groupId>
        <artifactId>spring-hibernate-maven</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringHibernateMaven</name>
        <url>http://www.agical.com</url>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>hibernate3-maven-plugin</artifactId>
                    <version>2.1</version>
                    <configuration>
                        <components>
                            <component>
                                <name>hbm2ddl</name>
                                <implementation>annotationconfiguration</implementation>
                            </component>
                        </components>
                        <componentProperties>
                            <drop>true</drop>
                            <jdk5>true</jdk5>
                            <outputfilename>schema.sql</outputfilename>
                            <skip>${maven.test.skip}</skip>
                            <hibernate.dialect>org.hibernate.dialect.HSQLDialect</hibernate.dialect>

                            <!-- Connection properties
                                May be used or not by the plugin, when it will recreate the annotated tables
                                every time it is executed
                            -->
                            <hibernate.connection.driver_class>org.hsqldb.jdbcDriver</hibernate.connection.driver_class>
                            <hibernate.connection.url>jdbc:hsqldb:mem:spring-hibernate-maven</hibernate.connection.url>
                            <hibernate.connection.username>sa</hibernate.connection.username>
                            <hibernate.connection.password></hibernate.connection.password>
                            <!-- /Connection properties -->

                        </componentProperties>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>process-test-resources</phase>
                            <goals>
                                <goal>hbm2ddl</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>hsqldb</groupId>
                            <artifactId>hsqldb</artifactId>
                            <version>1.8.0.7</version>
                        </dependency>
                    </dependencies>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-idea-plugin</artifactId>
                    <configuration>
                        <downloadJavadocs>true</downloadJavadocs>
                        <downloadSources>true</downloadSources>
                        <jdkLevel>1.5</jdkLevel>
                        <jdkName>1.5</jdkName>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.4</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.persistence</groupId>
                <artifactId>persistence-api</artifactId>
                <version>1.0</version>
            </dependency>
            <dependency>
                <groupId>hsqldb</groupId>
                <artifactId>hsqldb</artifactId>
                <version>1.8.0.7</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-annotations</artifactId>
                <version>3.4.0.GA</version>
            </dependency>
        </dependencies>
    </project>

We want to configure a dependency to hsqldb se we can generate a schema and update the database when we run the process-test-resources, which we do every time we run the test from Maven.

The hibernate plugin is dependant of a hibernate configuration file called hibernate.cfg.xml. Create it in /src/main/resources/hibernate.cfg.xml.

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>
        <session-factory>
            <property name="hibernate.show_sql">false</property>
            <property name="hibernate.format_sql">true</property>
            <property name="use_sql_comments">true</property>

            <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
            <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
            <property name="hibernate.connection.url">jdbc:hsqldb:hsql://localhost</property>
            <property name="hibernate.connection.username">sa</property>
            <property name="hibernate.connection.password"></property>

            <!-- add classes to map from here -->
            <mapping class="com.agical.experimental.entity.DefaultSubscription"/>
            <mapping class="com.agical.experimental.entity.FixedLineSubscription"/>
        </session-factory>
    </hibernate-configuration>

Recreate the idea project files, mvn idea:idea to get the resources missing and make sure that Idea knows about the last dependency we added.

Step 4 - Connect the Data Access Objects, dao, to Hibernate usng Spring for the wiring

We want to connect the different parts we have. The goal here is to use Springs IoC, Inversion of Control, container for the wiring. We will create two configuration files. The first one should be src/main/resources/applicationContext.xml. It should contain some bean definitions like below:

    <?xml version="1.0"  encoding="ISO-8859-1"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

        <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>

        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"/>
            <property name="dataSource" ref="dataSource"/>
        </bean>

        <bean id="recordDao" class="com.agical.experimental.dao.RecordDaoImpl">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    </beans>

We refer to a bean called sessionFactory. It need to be defined as well, define it in src/main/resources/sessionFactory.xml below:

    <?xml version="1.0"  encoding="ISO-8859-1"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>

        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
            <property name="url" value="jdbc:hsqldb:hsql://localhost"/>
            <property name="username" value="sa"/>
            <property name="password" value=""/>
        </bean>

        <!-- Hibernate session factory -->
        <bean id="sessionFactory"
              class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                    <prop key="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</prop>
                    <prop key="hibernate.connection.url">jdbc:hsqldb:hsql://localhost</prop>
                    <prop key="hibernate.connection.username">sa</prop>
                </props>
            </property>
            <property name="annotatedClasses">
                <list>
                    <value>com.agical.experimental.entity.DefaultSubscription</value>
                    <value>com.agical.experimental.entity.FixedLineSubscription</value>
                </list>
            </property>
        </bean>
    </beans>

Finally we need to add some more dependencies to the pom. We have introduced some spring stuff above as well as a DataSource implementation. So lets add the dependencies below:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.2.2</version>
    </dependency>

A working pom should look like this by now:

    <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>com.agical.experimental</groupId>
        <artifactId>spring-hibernate-maven</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringHibernateMaven</name>
        <url>http://www.agical.com</url>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>hibernate3-maven-plugin</artifactId>
                    <version>2.1</version>
                    <configuration>
                        <components>
                            <component>
                                <name>hbm2ddl</name>
                                <implementation>annotationconfiguration</implementation>
                            </component>
                        </components>
                        <componentProperties>
                            <drop>true</drop>
                            <jdk5>true</jdk5>
                            <outputfilename>schema.sql</outputfilename>
                            <skip>${maven.test.skip}</skip>
                            <hibernate.dialect>org.hibernate.dialect.HSQLDialect</hibernate.dialect>

                            <!-- Connection properties
                                May be used or not by the plugin, when it will recreate the annotated tables
                                every time it is executed
                            -->
                            <hibernate.connection.driver_class>org.hsqldb.jdbcDriver</hibernate.connection.driver_class>
                            <hibernate.connection.url>jdbc:hsqldb:mem:spring-hibernate-maven</hibernate.connection.url>
                            <hibernate.connection.username>sa</hibernate.connection.username>
                            <hibernate.connection.password></hibernate.connection.password>
                            <!-- /Connection properties -->

                        </componentProperties>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>process-test-resources</phase>
                            <goals>
                                <goal>hbm2ddl</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>hsqldb</groupId>
                            <artifactId>hsqldb</artifactId>
                            <version>1.8.0.7</version>
                        </dependency>
                    </dependencies>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-idea-plugin</artifactId>
                    <configuration>
                        <downloadJavadocs>true</downloadJavadocs>
                        <downloadSources>true</downloadSources>
                        <jdkLevel>1.5</jdkLevel>
                        <jdkName>1.5</jdkName>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.4</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.persistence</groupId>
                <artifactId>persistence-api</artifactId>
                <version>1.0</version>
            </dependency>
            <dependency>
                <groupId>hsqldb</groupId>
                <artifactId>hsqldb</artifactId>
                <version>1.8.0.7</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-annotations</artifactId>
                <version>3.4.0.GA</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring</artifactId>
                <version>2.5.6</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>2.5.6</version>
            </dependency>
            <dependency>
                <groupId>commons-dbcp</groupId>
                <artifactId>commons-dbcp</artifactId>
                <version>1.2.2</version>
            </dependency>
        </dependencies>
    </project>

Step 5 - Start Hypersonic SQL, HSQL

You have downloaded HSQL when you updated the pom earlier. A simple way to start it is to locate the downloaded hsqldb-1.8.0.7.jar and issue the command below.

java -cp hsqldb-1.8.0.7.jar org.hsqldb.Server

You may want to shut it down without loosing your data. Do so from the DatabaseManager. To launch the DatabaseManager issue the command:

java -cp hsqldb-1.8.0.7.jar org.hsqldb.util.DatabaseManager

But remember that you don't want to shut down the database for the rest of this tutorial. If you do, the parts that want to connect to the database will fail.

Step 6 - Run the integration tests to verify the entire setup using a database

The final step should be to run Maven and have it to perform the unit/integration tests so we can verify that the table has been created and that we can add stuff to it. Run the Maven command below:

mvn clean install

A successful build could produce this output:

    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Building SpringHibernateMaven
    [INFO] task-segment: [clean, install]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean]
    [INFO] Deleting directory C:projectsAgicalMavenHibernateAnnotationssandboxstep4target
    [INFO] [resources:resources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:compile]
    [INFO] Compiling 5 source files to C:projectsAgicalMavenHibernateAnnotationssandboxstep4targetclasses
    [INFO] [resources:testResources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] Preparing hibernate3:hbm2ddl
    [WARNING] Removing: hbm2ddl from forked lifecycle, to prevent recursive invocation.
    [INFO] [resources:resources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [hibernate3:hbm2ddl {execution: default}]
    [INFO] Configuration XML file loaded:
    file:/C:/projects/Agical/MavenHibernateAnnotations/sandbox/step4/src/main/resources/hibernate.cfg.xml
    20:44:38,718 INFO org.hibernate.cfg.annotations.Version - Hibernate Annotations 3.3.0.GA
    20:44:38,734 INFO org.hibernate.cfg.Environment - Hibernate 3.2.5
    20:44:38,734 INFO org.hibernate.cfg.Environment - hibernate.properties not found
    20:44:38,734 INFO org.hibernate.cfg.Environment - Bytecode provider name : cglib
    20:44:38,734 INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling
    [INFO] Configuration XML file loaded:
    file:/C:/projects/Agical/MavenHibernateAnnotations/sandbox/step4/src/main/resources/hibernate.cfg.xml
    20:44:38,796 INFO org.hibernate.cfg.Configuration - configuring from url:
    file:/C:/projects/Agical/MavenHibernateAnnotations/sandbox/step4/src/main/r
    esources/hibernate.cfg.xml
    20:44:38,890 INFO org.hibernate.cfg.Configuration - Configured SessionFactory: null
    [INFO] src/main/resources/database.properties not found within the project. Trying absolute path.
    [INFO] No hibernate properties file loaded.
    20:44:38,968 INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class:
    com.agical.experimental.entity.DefaultSubscription
    20:44:39,000 INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity
    com.agical.experimental.entity.DefaultSubscription on table subscriptions
    20:44:39,031 INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class:
    com.agical.experimental.entity.FixedLineSubscription
    20:44:39,062 INFO org.hibernate.validator.Version - Hibernate Validator 3.0.0.GA
    20:44:39,078 INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.HSQLDialect
    20:44:39,171 INFO org.hibernate.tool.hbm2ddl.SchemaExport - Running hbm2ddl schema export
    20:44:39,171 INFO org.hibernate.tool.hbm2ddl.SchemaExport - writing generated schema to file:
    C:projectsAgicalMavenHibernateAnnotationssandboxst
    ep4targethibernate3sqlschema.sql
    20:44:39,171 INFO org.hibernate.tool.hbm2ddl.SchemaExport - exporting generated schema to database
    20:44:39,171 INFO org.hibernate.connection.DriverManagerConnectionProvider - Using Hibernate built-in connection
    pool (not for production use!)
    20:44:39,171 INFO org.hibernate.connection.DriverManagerConnectionProvider - Hibernate connection pool size: 20
    20:44:39,171 INFO org.hibernate.connection.DriverManagerConnectionProvider - autocommit mode: false
    20:44:39,171 INFO org.hibernate.connection.DriverManagerConnectionProvider - using driver: org.hsqldb.jdbcDriver at
    URL: jdbc:hsqldb:hsql://localhost

    20:44:39,171 INFO org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=sa,
    password=****}
    drop table subscriptions if exists;
    create table subscriptions (subscriptionType varchar(31) not null, id bigint generated by default as identity (start
    with 1), subscriberName varchar(2
    55), primary key (id));
    20:44:39,234 INFO org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete
    20:44:39,234 INFO org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool:
    jdbc:hsqldb:hsql://localhost
    [INFO] [compiler:testCompile]
    [INFO] Compiling 1 source file to C:projectsAgicalMavenHibernateAnnotationssandboxstep4targettest-classes
    20:44:39,968 INFO org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool:
    jdbc:hsqldb:hsql://localhost
    [INFO] [surefire:test]
    [INFO] Surefire report directory: C:projectsAgicalMavenHibernateAnnotationssandboxstep4targetsurefire-reports

    -------------------------------------------------------
    T E S T S
    -------------------------------------------------------
    Running com.agical.experimental.dao.SubscriptionDaoTest
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 2, Time elapsed: 0.141 sec

    Results :

    Tests run: 2, Failures: 0, Errors: 0, Skipped: 2

    [INFO] [jar:jar]
    [INFO] Building jar:
    C:projectsAgicalMavenHibernateAnnotationssandboxstep4targetspring-hibernate-maven-1.0-SNAPSHOT.jar
    [INFO] [install:install]
    [INFO] Installing
    C:projectsAgicalMavenHibernateAnnotationssandboxstep4targetspring-hibernate-maven-1.0-SNAPSHOT.jar to
    C:Documents and Settin
    gsThomas.m2repositorycomagicalexperimentalspring-hibernate-maven1.0-SNAPSHOTspring-hibernate-maven-1.0-SNAPSHOT.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 9 seconds
    [INFO] Finished at: Mon Dec 22 20:44:42 CET 2008
    [INFO] Final Memory: 14M/26M
    [INFO] ------------------------------------------------------------------------

BUILD SUCCESSFUL indicates that we are happy and that the configuration we have created works.

Resources



(less...)

Pages

About
Events
Why

Categories

Agile
Automation
BDD
Clean code
Continuous delivery
Continuous deployment
Continuous integration
Cucumber
Culture
Design
DevOps
Executable specification
Gradle
Guice
J2EE
JUnit
Java
Kubernetes
Linux
Load testing
Maven
Mockito
Pair programming
PicoContainer
Presentation
Programming
Public speaking
Quality
Recruiting
Requirements
Scala
Selenium
Software craftsmanship
Software development
Spring
TDD
Teaching
Technical debt
Test automation
Tools
Web
Windows
eXtreme Programming

Authors

Thomas Sundberg
Adrian Bolboaca

Archives

Meta

rss RSS