Some time ago I started working with intellij, recently I bought a mac, and now I want to start programming. But where to start? There are some mandatory things, or not? Well let’s just start and try to make it as flexible as possible so we can use other frameworks for some layers. For now I will focus on the following technologies:
- Springframework
- JPA, the hibernate implementation
- Java 5 and annotations
When creating the sample I started of programming in Intellij. Even with the excellent integration of JPA and Hibernate I still had a lot op problems creating the sample. Damn this is not easy. So what do you do when you are stuck? You start reading, I already had some books that could help me out. Still I like the “Java Persistence with Hibernate” book the best. The similarities between hibernate and JPA enabled me to quicker learn the basics. So I started reading, I came to the conclusion I had or wanted to start using annotations. It struck me how well Intellij was helping me again.
Just a few tips when developing with intellij, maven, jpa, spring, etc.
Create a new project based on an external model, click next and choose maven. Click next again and browse to the folter containing the master pom file. Click next and you have the option to select the project. The finish will create your new project with all modules present.
By default the spring and jpa facets are not present. You need to add them to the modules. Open the module settings (right mouse click and select menu item) and add the plus sign for adding a facet. The following screen shows the result of adding the spring facet and creating a new File Set. Another cool thing is that you can create a datasource to a database and connect this to a persistent unit. Columns and tables are then checked when creating your annotations.
I like the intellij way of creating new projects, but still I am a maven adept, so I wanted to have it all running with maven. You can find the sample online again. Beware, it is work in progress. I am adding a front end and more logic the coming weeks. Check:
http://gridshore.googlecode.com/svn/trunk/RaffleApp/
If you want to start with jpa, spring and maven I can recommend the following archetype:
http://www.rateyourwriting.com/downloads/jpa-hibernate-archetype.tar.gz
I did not try it out myself, but it looks very good. It is create by Chris Maki (
http://www.jroller.com/cmaki/category/JPA+101)
In the reference manual of the springframework I found a sentence that for new applications they prefer not to use the JpaDaoSuppor class. There is another way based on the special bean PersistenceAnnotationBeanPostProcessor. Using this bean you can use annotations like : @Entity, @PersistenceContext from within the spring container.
Back to my problem, for some reason my tests using the AbstractJpaTests did not work with the separate jars for domain and data access (dao). I started by combining them in one module. But I was not satisfied. So I went back to my friend Google. I typed in a query for information about using modules with jpa and springframework. To my surprise I got back a lot of articles about the debate between using DAO’s or not. Yes we are back to the discussion about DDD or Domain Driven Design. After reading a lot of posts I guess the following sentence found on a blog item from Craig Wickesser but written by Adam Bien:
“
I would say: it depends. It depends how complex your application really is. ”
Now back to the original problem, how to design a application using JPA?
Some of the choices you have to make:
- Use annotations or XML or both?
- Use JpaTemplate or annotations and (org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor)
- Create one or multiple modules
Use a DAO layer or step into the DDD world and use the Persistence class.
In the end I did manage to get back to my so well known structure of a DAO layer and domain objects. What I had to do? We will check the persistence.xml file later on. I had to add the specific classes in this file.
Every problem needs a sample
Let me first explain a bit about the example that I am going to use. For a technology evening at my company I had some books that I could give away to the people present. Since it was an evening about the Google Web Toolkit I created a nice front end application using a file as storage to a Raffle application. Check the following application if you want to see it:
http://gridshore.googlecode.com/svn/trunk/Raffle/
I decided this file thing was not really optimal, so I wanted to create a database backed application. What to use? Well let’s try it out JPA, hibernate started to get boring and I wanted to move on. So what is in the raffle applications domain model
Some rules:
- A raffle has multiple prices and multiple participants.
- A price has a winner
- A winner is a participant, or has a participant and a price.
We begin with the project setup using maven:
First the dependencies that you need in your pom:
spring-aop, spring-dao, spring-jpa, spring-hibernate3, hibernate-entitymanager, c3p0, mysql-connector-java, concurrent, spring-mock
That’s about it, put that in the pom.xml, create the structure and do a mvn clean install, or ...
Fire up intelij, create a new project based on this pom.xml and you can do the same things as I showed before.
We’ll begin with the domain objects:
@MappedSuperclass
public class BaseDomain {
@Id
@GeneratedValue
private Long id;
}
@Entity
@Table (name = "participants")
public class Participant extends BaseDomain {
private String name;
@ManyToOne
@JoinColumn(name = "raffle_id")
private Raffle raffle;
}
@Entity
@Table(name = "prices")
public class Price extends BaseDomain {
private String title;
private String description;
@ManyToOne
@JoinColumn(name = "raffle_id")
private Raffle raffle;
@OneToOne (mappedBy = "price")
private Winner winner;
}
@Entity
@Table (name = "winners")
public class Winner extends BaseDomain {
@OneToOne
@JoinColumn(name = "price_id")
private Price price;
@ManyToOne
@JoinColumn(name = "participant_id")
private Participant participant;
}
Next step is to create a DAO interface that does not have anything to do with JPA, I use the interface like this:
public interface BaseDao {
T save(T entity);
T loadByExample(T entity);
T loadById(Long entityId);
List loadAll();
List loadByFilter(T entityFilter);
}
For now I will not focus on the implementation, I am not a JPA expert yet

. One thing I want to mention is the EntityManager. Using a special annotation we make sure the EntityManager is injected by the container, the spring container in our case.
public abstract class BaseDaoJpa implements BaseDao {
@PersistenceContext
private EntityManager entityManager;
...
}
Next step is to configure the spring beans:
<bean id="raffleDao" class="nl.gridshore.samples.raffle.dao.jpa.RaffleDaoJpa"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="raffle"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${hibernate.sql.dialect}"/>
</bean>
</property>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverclass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
Finally we need to configure the the entity manager, this is done with a special file named persistence.xml which is displayed beneath.
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="raffle" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>nl.gridshore.samples.raffle.domain.BaseDomain</class>
<class>nl.gridshore.samples.raffle.domain.Raffle</class>
<class>nl.gridshore.samples.raffle.domain.Price</class>
<class>nl.gridshore.samples.raffle.domain.Participant</class>
<class>nl.gridshore.samples.raffle.domain.Winner</class>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
</properties>
</persistence-unit>
</persistence>
That is enough to start using the application. However, there is one thing I forget. What about testing this application. Spring comes with a special class for testing called AbstractJpaTests. This is class had familiar functionality, auto dependency injection and rolling back a transaction after the test.
Using this test you still need a database. For the data access tests I am using a combination of dbunit, springframework and hsqldb. Most important part of the test class is the injection of the dao:
public class RaffleDaoJpaTest extends AbstractJpaTests {
private RaffleDaoJpa raffleDao;
public void setRaffleDao(RaffleDaoJpa raffleDao) {
this.raffleDao = raffleDao;
}
...
protected String[] getConfigLocations() {
return new String[] {"classpath:test-dao-spring.xml","classpath:dao-config.xml"};
}
}
The following beans are in the special test spring config file together with the datasource for the test database.
<bean id="dbUnitInsertOperation" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
depends-on="transactionManager">
<property name="targetObject">
<bean class="org.dbunit.operation.RefreshOperation" />
</property>
<property name="targetMethod" value="execute" />
<property name="arguments">
<list>
<ref bean="dbUnitConnection" />
<bean id="dbUnitDataSet" class="org.dbunit.dataset.xml.FlatXmlDataSet">
<constructor-arg>
<bean id="refDataFile" factory-bean="referenceData" factory-method="getInputStream" />
</constructor-arg>
</bean>
</list>
</property>
</bean>
<bean id="referenceData" class="org.springframework.core.io.ClassPathResource">
<constructor-arg value="testdata.xml"/>
</bean>
<bean id="dbUnitConnection" class="util.CustomDatabaseConnection">
<constructor-arg>
<bean id="connection" factory-bean="dataSource" factory-method="getConnection" />
</constructor-arg>
</bean>
That is about it, again, check the source code, everything is runnable by maven2 and tested on tomcat 5.5. If you want to read more, I used the following resources while creating learning about jpa and the other topics.
Links:
http://www.infoq.com/news/2007/09/jpa-dao
http://debasishg.blogspot.com/
http://www.vitarara.org/cms/struts_2_cookbook/integration_testing
http://dev2dev.bea.com/pub/a/2006/03/jpa-spring-medrec.html?page=6
http://www.jroller.com/cmaki/entry/domain_model_revisited