0

I created a basic Spring MVC / JPA / Hibernate app. I am trying to save a UserProfile entity to test if I can actualy persist it, but nothing gets saved and no exception is thrown either.

In the controller method I create a simple UserProfile (which is an @Entity) and I am sending that to a service method. The UserProfileServiceImpl class is annotated with @Service and the addUserProfile(UserProfile profile) method is annotated with @Transactional.

In the service method, all I do is call a DAO method (class annotated with @Repository). In the DAO method all I do is call entityManager.persist(object), with object being the user profile object.

  • Nothing gets written to the server log and the log level is at INFO.
  • Nothing appears in the Mysql query log (and I know the query log works)
  • The entityManager gets properly injected.
  • The datasource is properly initiated, because when I enter faulty credentials I get SQLExceptions.

I hope you can tell me what's wrong. I'll post some of my code and config files below.

The service method:

// The service method gets called from the controller. 
// Its class is annotated with @Service

@Transactional(readOnly = false)
public void addUserProfile(UserProfile userProfile) {
    userProfileDao.save(userProfile);
}

The Dao method:

// The save(T object) method is in the GenericDaoJpa class, which is the superclass
// of the UserProfileDaoJPA class that is referenced from the service.
// I have established that the entityManager is there and the object is a
// UserProfile. The @Repository annotation is on the child class UserProfileDaoJpa.

public void save(T object) {
    entityManager.persist(object);
}

Main application-context.xml

<context:property-placeholder location="classpath*:**/*.properties"/>
<import resource="spring-jpa.xml"/>

The application-context-web.xml file

<mvc:annotation-driven />
<context:component-scan base-package="nl.codebasesoftware.produx" />

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>

spring-jpa.xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${db.driverClassName}"
      p:url="${db.url}" p:username="${db.username}" p:password="${db.password}"/>

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

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

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>

persistence.xml

<persistence-unit name="mysqlPersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
    </properties>
</persistence-unit>

<!-- Needed to properly process @PersistenceContext -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

Somehow no SQL is sent to Mysql with this setup, but no exception is thrown either, so I have no idea what's going on. Hope you can help :)

Julius
  • 2,784
  • 6
  • 32
  • 54
  • which hibernate and spring version you are using? – Jigar Parekh Jul 18 '12 at 05:55
  • Spring 3.1.1 and Hibernate 4.1.4 – Julius Jul 18 '12 at 09:42
  • I did notice just now that when I call entityManager.flush() after entityManager.persist() in the DAO method I get the following error: - Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress. Apparently there is no transaction.... – Julius Jul 18 '12 at 09:49
  • I put up my project here for if someone is interested in taking a closer look: www.exprofesso.nl/project.zip – Julius Jul 18 '12 at 09:55

2 Answers2

2

i think you are missing transaction propagation at service. marking readonly=false just set session to auto flush. but setting up proper transaction propogation will make sure start of trnasaction and commit/rollback.

after removing mode="aspectj" it has started working because i think because of as per spring doc

The default mode "proxy" will process annotated beans to be proxied using Spring's AOP framework (following proxy semantics, as discussed above, applying to method calls coming in through the proxy only). The alternative mode "aspectj" will instead weave the affected classes with Spring's AspectJ transaction aspect (modifying the target class byte code in order to apply to any kind of method call). AspectJ weaving requires spring-aspects.jar on the classpath as well as load-time weaving (or compile-time weaving) enabled. (See the section entitled Section 6.8.4.5, “Spring configuration” for details on how to set up load-time weaving.)

and probably you have not configured load time weaving

Jigar Parekh
  • 6,163
  • 7
  • 44
  • 64
  • 1
    from exception which you have mention it is very clear that hibernate was not instrcuted to start transaction. – Jigar Parekh Jul 18 '12 at 09:55
  • true... but why? I think it has something to do with where I placed annotations and component scanning or something. I have placed my '@Transactional' annotations on methods in a '@Service' class. I also tried placing the @Transactional annotations in the Dao ('@Repository') layer, but that doesn't work either. I am going to recreate my settings files this afternoon, because I think it must have something to do with component scanning and the location of my annotations or something.. – Julius Jul 18 '12 at 10:24
0

Ok, I got it. First I thought I found the answer here

Declarative transactions (@Transactional) doesn't work with @Repository in Spring

But after some more testing I found it was not the location of

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

but its contents.

After removing the mode="aspectj" attribute it started working! If anyone would like to comment why that is, please do.

Let me share my full setup with you. This is for Spring 3.1 with Hibernate 4. NOTE: for 'brevity' I only posted the contents of the configuration files, and omitted the outer tags <beans> and <persistence> and the namespace declarations. I removed spring-jpa.xml altogether and moved its contents into application-context.xml.

Contents of web.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<display-name>My Spring MVC web application</display-name>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:**/application-context.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>produxDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:**/application-context-web.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>produxDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
</web-app> 

Contents of application-context.xml:

<!-- main setup -->
<context:property-placeholder location="classpath*:**/*.properties"/>
<context:annotation-config/>
<context:component-scan base-package="nl.codebasesoftware.produx.domain" />
<context:component-scan base-package="nl.codebasesoftware.produx.service" />
<context:component-scan base-package="nl.codebasesoftware.produx.dao" />
<!-- Data and JPA setup -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${db.driverClassName}"
      p:url="${db.url}" p:username="${db.username}" p:password="${db.password}"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"/>
<tx:annotation-driven  transaction-manager="transactionManager"/>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>

Contents of application-context-web.xml:

<mvc:annotation-driven />

<context:component-scan base-package="nl.codebasesoftware.produx.controller" />

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>

Contents of webapps/META-INF/persistence.xml

<persistence-unit name="mysqlPersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        <!-- <property name="hibernate.hbm2ddl.auto" value="create-drop"/>  -->
    </properties>
</persistence-unit>

<!-- Needed to properly process @PersistenceContext which injects the entity manager -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

Contents of environment.properties:

db.url=jdbc:mysql://localhost:3306/yourDatabaseName
db.driverClassName=com.mysql.jdbc.Driver
db.username=yourUsername
db.password=yourPassword
Community
  • 1
  • 1
Julius
  • 2,784
  • 6
  • 32
  • 54
  • have a look at my edit in answer [link](http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html) – Jigar Parekh Jul 19 '12 at 08:32