Home > Other > JPA 2.0 and Spring 3.0 with Maven

JPA 2.0 and Spring 3.0 with Maven

I’m currently updating WicketCool to use Spring 3.0, JPA2.0 and latest Wicket. Here is a short summary of my research, a quick tutorial showing how to jump into Spring3.0 + JPA2.0 development using Maven.

1. Dependencies

a) Spring

To use 3.0 release of the Spring framework you can’t no longer add one dependency as you used to do it

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring</artifactId>
   <version>2.5.6</version>
</dependency>

This will no longer work. Spring framework is divided into 20 modules:

If you create web appliactions, you will probably need modules listed below:

  1. all from Core Container: Beans, Core, Context and Expression Language
  2. AOP
  3. from Data Access/Integration: Transactions, ORM
  4. from Web: Web (even if you don’t use SpringMVC, you still might consider OpenEntityManagerInViewFilter which is inside Web module
  5. Test

Thus set of dependencies that you need to include in your pom.xml are:

<properties>
 <spring.version>3.0.0.RELEASE</spring.version>
</properties>

<dependencies>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-beans</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-aop</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-tx</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-jdbc</artifactId>
   <version>${spring.version}</version>
 </dependency>
 <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>${spring.version}</version>
 </dependency>
</dependecies>

b) JPA 2.0

Now that we have Spring dependencies sorted out, we can look at the JPA2.0.  We must remember that JPA itself is only standard, thus when setting dependencies we are really choosing the provider. I could go with Hibernate or EclipseLink. Hibernate is still in beta state and EclispeLink is a reference implementation of the standard, so I thought that EclipseLink is a good way to go. However after recent discoveries (which took me quite some to figure out by the way), I thought I will stick with the Hibernate’s beta.

What is new in Hibernate’s recent release is that you no longer need to define dependencies to core, annotations, commons-annotations ect. It is now only one, single dependency.  Second dependency is the API of the standard.

<dependencies>
  <dependency>
    <groupId>org.hibernate.java-persistence</groupId>
    <artifactId>jpa-api</artifactId>
    <version>2.0-cr-1</version>
  </dependency>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>3.5.0-Beta-2</version>
  </dependency>
</dependencies>

You might also need to add JBoss repository:

<repositories>
 <repository>
   <id>JBoss Repo</id>
   <url>http://repository.jboss.com/maven2</url>
 </repository>
</repositories>

2. Configuration

The simples application context configuration file can look like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd  http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

 <!-- holding properties for database connectivity /-->
   <context:property-placeholder location="classpath:jdbc.properties"/>
   <!-- enabling annotation driven configuration /-->
<context:annotation-config/>
<context:component-scan base-package="wcpackage"/>
   <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean
       class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

    <bean id="dataSource"
       class="org.springframework.jdbc.datasource.DriverManagerDataSource"
       p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}"/>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
       p:entityManagerFactory-ref="entityManagerFactory"/>

    <bean id="entityManagerFactory"
       class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
       p:dataSource-ref="dataSource"
       p:jpaVendorAdapter-ref="jpaAdapter">
       <property name="loadTimeWeaver">
          <bean
             class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>
        <property name="persistenceUnitName" value="wctemplatePU"></property>
    </bean>

    <bean id="jpaAdapter"
         class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
         p:database="${jpa.database}"
         p:showSql="${jpa.showSql}"/>
</beans>

Given that wcpackage is a root package for component scan and wctemplatePU is name of the persistent unit.
Now all we need to do is to define persistence unit in META-INF/persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence">

	<persistence-unit name="wctemplatePU" transaction-type="RESOURCE_LOCAL">
		<properties>
			<property name="hibernate.hbm2ddl.auto" value="validate" />
		</properties>
	</persistence-unit>
</persistence>

And that is basically it. You have Spring configuration and now can use EntityManager in your services classes.

@Repository(value = "userDAO")
public class UserDefaultDAO implements UserDAO {

    @PersistenceContext
    private EntityManager entityManager;

Injected EntityManager will be with transaction-scoped persistence context, resource_local transaction type (meaning transactions used from database not JTA). Hope everything is comprehensive. If you have any questions, please let me know.

See also:

  1. A proper way for JPA entities instantiation
ale macie fajnie
Categories: Other Tags: , , ,
  1. Wesslan
    January 11, 2010 at 10:04 am

    Although it worked frpn Spring < 3.0, it has never been a good idea to use "spring”. 🙂

    • paulszulc
      January 11, 2010 at 10:23 am

      True. And also recently I realized, that there is dependency spring-full. I wonder if it still works 😉 I might try it just to see what happens

  2. January 11, 2010 at 7:52 pm

    Spring 3.0 is broken in this area: http://jira.springframework.org/browse/SPR-6408.
    AFAIK 3.1 will support JPA 2.0 fully.

    • paulszulc
      January 11, 2010 at 10:01 pm

      Will it be solved by providing second support for JPA2 only or will Spring stick with one provider and will update those methods when thinks that JPA1.0 is obsolete?

  3. January 13, 2010 at 12:58 am

    Update: It will get into the 3.0.1 release: http://jira.springframework.org/browse/SPR-6408

    • paulszulc
      January 13, 2010 at 7:35 am

      Yep, I’ve seen JIRA yesterday as well 🙂 Once again thx for the info

  4. daniel
    January 13, 2010 at 11:47 am

    supports spring 3.0 all jpa 2.0?
    i’m trying to create a CriteriaQuery and this is the result:

    $Proxy146 cannot be cast to javax.persistence.TypedQuery

    on this line:

    TypedQuery tq = getEntityManager().createQuery(query);

    where is the problem? thanks

    • paulszulc
      January 20, 2010 at 12:50 pm

      daniel: sorry for not replying, shouldn;t yuor code look like this:

      TypedQuery tq = getEntityManager().createQuery(query, SomeEntityClass.class);

      this should work,if you dont provide enitty class, you get normal Query, otherwise TypedQuery

      • daniel
        January 24, 2010 at 11:28 pm

        OK, I just see Ke CAI’s message and I agree that is a Spring problem, because I tried with

        TypedQuery tq = getEntityManager().createQuery(query, SomeEntityClass.class);

        too and the result was the same. I will try to update my Spring dependencies and I will write you the result.

        Thx for de info 🙂

  5. Vivek Anand
    January 13, 2010 at 12:05 pm

    We have used Spring3.0 testing framework with JPA and Hibernate3.
    After successful integration of all these, we are able to perform CRUD operations on entities from UI.

    When we tried creating test cases for DAO, we stuck with a problem of NOT Saving/Updating the data in DB except successful retreival.

    Please help, if you have some solution.

    • paulszulc
      January 20, 2010 at 9:54 pm

      I would really need to see some code if you want my help.

  6. paulszulc
    January 13, 2010 at 2:48 pm

    Vivek Andan and Daniel: I will try look into it as soon as possible. Will let you know with the research.

  7. Michael
    January 14, 2010 at 3:28 am

    Thanks for the reference material. I was looking for some XSD URLs and your site was at the top.

  8. January 20, 2010 at 12:09 pm

    daniel :
    supports spring 3.0 all jpa 2.0?
    i’m trying to create a CriteriaQuery and this is the result:
    $Proxy146 cannot be cast to javax.persistence.TypedQuery
    on this line:
    TypedQuery tq = getEntityManager().createQuery(query);
    where is the problem? thanks

    I have the same problem:

    java.lang.ClassCastException: $Proxy50 cannot be cast to javax.persistence.TypedQuery
    at $Proxy38.createQuery(Unknown Source)

    • paulszulc
      January 20, 2010 at 12:51 pm

      show me your code that throws exception

      • January 20, 2010 at 1:13 pm

        @Repository
        public class ShopDaoImpl extends GenericDaoJpaImpl implements
        ShopDao {
        @PersistenceContext
        transient EntityManager entityManager;

        @Override
        public Shop findByCrieria() {

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery c = cb.createQuery(Shop.class);
        Root shop = c.from(Shop.class);
        c.select(shop).where(cb.equal(shop.get(“name”), “petstore”));
        TypedQuery q = entityManager.createQuery(c);
        return q.getSingleResult();
        }

        }

        • paulszulc
          January 20, 2010 at 9:51 pm

          Hi

          first of all, does this code really compiles? Shouldn’t it be:

          TypedQuery<Shop> q = entityManager.createQuery(c);
          return q.getSingleResult();

          ?

          I’ve created a method to yours and it’s working here:

          public User findByLogin(String login) {
          CriteriaBuilder cb = entityManager.getCriteriaBuilder();
          CriteriaQuery c = cb.createQuery(User.class);
          Root user = c.from(User.class);
          c.select(user).where(cb.equal(user.get(“login”), login));
          TypedQuery q = entityManager.createQuery(c);
          return q.getSingleResult();
          }

          and test:

          @Test
          public void shouldPersistUserInDataBase() throws Exception {

          // given
          assertEquals(1, userDAO.size());
          User user = new User(“login”, “password”);

          // when
          userDAO.persist(user);

          // then
          assertEquals(2, userDAO.size());
          User result = userDAO.findByLogin(“login”);
          assertEquals(“login”, result.getLogin());
          assertEquals(“password”, result.getPassword());
          }

          passes.

          I will soon release WicketCool 0.7 where you will be able to see it in action.

          If you have any other questions, let me know. You know my email address right?

          • January 20, 2010 at 10:55 pm

            I tried your code, but it still does not work.

            I also asked this question in stackoverflow, some guys think this is a bug.

            http://stackoverflow.com/questions/2101500/spring-3-0-orm-with-jpa-2-0-classcastexception/2102328#2102328

            I created an issue in Spring JIRA. Hope this problem can be sloved soon.

            • paulszulc
              January 20, 2010 at 11:03 pm

              which spring version do you use?

              I recreated your code as close possible as I could, and it still works.

              Is it a maven project? Can I see you pom?

              By the way: Sydney right? You are lucky to have a summer now. Freaking freezing out here right now 🙂

              • January 20, 2010 at 11:12 pm

                You bet, very hot. I miss snow so much.

                My project is maven project,

                because of :http://jira.springframework.org/browse/SPR-6408

                I use Spring, 3.0.1.BUILD-SNAPSHOT, Hibernate 3.5.0-Beta-3 .

                • paulszulc
                  January 20, 2010 at 11:14 pm

                  I user Spring 3.0.0 and 3.5.0-Beta2.

                  I will update my dependencies tomorrow (as I go to bed right now) and tell you if anything changed. Ok?

                  • January 20, 2010 at 11:19 pm

                    Thanks, and have a sweet dream:)

  9. January 21, 2010 at 10:36 pm

    [Spring-JIRA] Resolved: (SPR-6733) Spring 3.0 ORM with JPA 2.0 TypedQuery ClassCastException

    They fixed this bug:)

    • paulszulc
      January 21, 2010 at 10:52 pm

      ok, so it was hibernate3.5-beta3 problem (i’m still on beta2). Thx for the info.

  10. wytten
    March 29, 2010 at 3:10 pm

    Thanks for posting, the world needs more like this 🙂

  11. Naresh
    July 29, 2010 at 3:17 pm

    I am trying to build/define a project and I am new to Maven. I wanted to develop web application on tomcat using Spring 3.0.3 , JPA and using Maven. I tried your article but I lost in middle as it doesn’t tell you steps from start i.e. step starting from maven to create project and then to configure it with JPA etc… Is it possible for you to write a article or give me guidance to write about project, may be with user login getting password using JPA from database. Actually I wanted to define good project structure using MAVEN.

  1. January 11, 2010 at 2:55 pm

Leave a comment

  • Design a site like this with WordPress.com
    Get started