Could not open JPA EntityManager for transaction in spring
Asked Answered
S

4

4

I am building a testing application with JPA Hibernate 4.1.7 and Spring 3.1.3 on top.

I am getting a NPE at jta causing JPA EntityManager to fail, here is the stack trace

    DEBUG TestContext - Retrieved ApplicationContext for test class [class cvut.dp.foodtables.service.FoodServiceImplTest] from cache with key [[MergedContextConfiguration@61cc1457 testClass = FoodServiceImplTest, locations = '{classpath:/WEB-INF/context/applicationContext.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']].
DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean 'txManager'
DEBUG JpaTransactionManager - Creating new transaction with name [testSome]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG SessionImpl - Opened session at timestamp: 13525989368
DEBUG TransactionCoordinatorImpl - Skipping JTA sync registration due to auto join checking
DEBUG AbstractEntityManagerImpl - Looking for a JTA transaction to join
WARN  TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@16f88474] to process 'before' execution of test method [public void cvut.dp.foodtables.service.FoodServiceImplTest.testSome()] for test instance [cvut.dp.foodtables.service.FoodServiceImplTest@3210a146]
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.NullPointerException
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:427)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.startTransaction(TransactionalTestExecutionListener.java:514)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener.startNewTransaction(TransactionalTestExecutionListener.java:272)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener.beforeTestMethod(TransactionalTestExecutionListener.java:165)
    at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:358)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
Caused by: java.lang.NullPointerException
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:73)
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:115)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149)
    at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1220)
    at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:178)
    at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89)
    at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:179)
    at org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:445)
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:366)
    ... 31 more
DEBUG DirtiesContextTestExecutionListener - After test method: context [[TestContext@5579d6f9 testClass = FoodServiceImplTest, testInstance = cvut.dp.foodtables.service.FoodServiceImplTest@3210a146, testMethod = testSome@FoodServiceImplTest, testException = org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.NullPointerException, mergedContextConfiguration = [MergedContextConfiguration@61cc1457 testClass = FoodServiceImplTest, locations = '{classpath:/WEB-INF/context/applicationContext.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]], class dirties context [false], class mode [null], method dirties context [false].
DEBUG DirtiesContextTestExecutionListener - After test class: context [[TestContext@5579d6f9 testClass = FoodServiceImplTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@61cc1457 testClass = FoodServiceImplTest, locations = '{classpath:/WEB-INF/context/applicationContext.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]], dirtiesContext [false].
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 11.134 sec <<< FAILURE!

I have googled the error to death and still can't find any solution.

Here is the test:

package cvut.dp.foodtables.service;

import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class FoodServiceImplTest extends BaseServiceTest
{
    @Autowired
    private FoodService foodService;

    public FoodServiceImplTest()
    {
        super();
    }

    @Test
    public void testSome()
    {        
        Long id = foodService.addFood("test", 15, "test");
        assertEquals(1, foodService.getAllFood().size());
    }
}

Which extends

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath:/WEB-INF/context/applicationContext.xml"})
@TransactionConfiguration(defaultRollback=true, transactionManager="txManager")
@Transactional //extend the transactions to whole tests in order to rollback the tests
public class BaseServiceTest
{
    public BaseServiceTest()
    {
    }
}

I presume the error to be somewhere in my configuration, so I won't post all of the sources here...

Here is my applicationContext.xml (edit: changed to 3.1.xds files, no change)

<!--<?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:webflow="http://www.springframework.org/schema/webflow-config" 
       xmlns:faces="http://www.springframework.org/schema/faces" 
       xmlns:p="http://www.springframework.org/schema/p" 
       xmlns:context="http://www.springframework.org/schema/context" 
       xmlns:tx="http://www.springframework.org/schema/tx" 
       xmlns:aop="http://www.springframework.org/schema/aop" 

       xsi:schemaLocation=" http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
            http://www.springframework.org/schema/webflow-config 
            http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd 
            http://www.springframework.org/schema/faces 
            http://www.springframework.org/schema/faces/spring-faces-2.0.xsd 
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd 
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" 
       default-autowire="byType"
>

<!-- Enable annotions -->
    <context:annotation-config />
    <context:component-scan base-package="cvut.dp.foodtables"/>
<!-- @Configurable -->
    <context:spring-configured/> 

<!-- Property files -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>/WEB-INF/properties/jdbc.properties</value>
                <value>/WEB-INF/properties/jpa.properties</value>
            </list>
        </property>
    </bean>        
<!-- JDBC data source -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="initialSize" value="2" />
        <property name="minIdle" value="2" />
    </bean>
<!-- JPA settings --> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="databasePlatform" value="${jpa.platform}"/>
                <property name="generateDdl" value="true"/>
                <property name="showSql" value="true"/>

            </bean>
        </property>
        <property name="packagesToScan" value="cvut.dp.foodtables" />
    </bean> 

<!-- Define transaction manager -->
    <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

<!-- @Transactional support-->
    <tx:annotation-driven transaction-manager="txManager" /> 

</beans>

I don't have persistence.xml

jdbc.properties:

jdbc.driverClassName=org.hibernate.dialect.MySQLDialect
jdbc.url=jdbc:mysql://localhost:3306/FoodTables
jdbc.username=root

jpa.properties:

jpa.platform=org.hibernate.dialect.MySQLDialect

Here is web.xml

<?xml version="1.0" encoding="UTF-8"?>

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


<!-- SPRING -->
    <context-param>
        <description>Spring config files</description>
        <param-name>contextConfigLocation</param-name>
        <param-value>
                /WEB-INF/context/*.xml
        </param-value>
    </context-param>

    <listener>
        <description>Loads Spring on server start</description>
        <listener-class>
               org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <listener>
        <description>Request -> thread association</description>
        <listener-class>
               org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>  
<!-- SPRING END --> 
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

And my pom.xml

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cvut.dp</groupId>
    <artifactId>FoodTables</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>

    <name>FoodTables</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.1.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-documentation</artifactId>
            <version>3.6.0.Beta2</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.1.8.Final</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <groupId>org.hibernate.javax.persistence</groupId>
            <type>jar</type>
            <version>1.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
        </dependency>
    </dependencies>

    <build>
        <testResources>
            <testResource>
                <directory>src/test/resources</directory>
                <filtering>true</filtering>
            </testResource>

            <testResource>
                <directory>src/main/webapp</directory>

                <filtering>true</filtering>

                <includes>
                    <include>**/context/applicationContext*.xml</include>
                    <include>**/properties/*.properties</include>
                </includes>
            </testResource>
        </testResources>  
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>6.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

The most googled up answer was that I should be setting hibernate.transaction.jta.platform property in persistance.xml, which I don't have. This is my first ever Java EE app and I really don't exactly know what I am doing yet. But this error is frustrating.

Supportable answered 11/11, 2012 at 2:11 Comment(0)
G
5

I had the same problem. The solution is to use default-autowire="byName" instead of "byType" in your xml configuration. If you have "byType" Spring automatically autowire also the property "jtaDataSource" in the LocalContainerEntityManagerFactoryBean with your definied datasource bean.

Grosberg answered 28/5, 2013 at 20:58 Comment(0)
M
1

While jens answer is correct and solves your problem, i just wanted to add that you don't have to change the default-autowiring for this. You can also set that on every bean itself.

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
autowire="byName">
...

Now you still have byType-autowiring on all of your beans except "entityManagerFactory"

Meow answered 26/6, 2015 at 5:53 Comment(0)
D
0

This is no password entry defined in your jdbc.projects.

<property name="password" value="${jdbc.password}"/>

It is better to create a standalone user/password for your projects, do not use root in your production.

Disulfiram answered 11/11, 2012 at 3:58 Comment(1)
I ommited that final line for obvious reasons... database connects fine and creates tables with no difficuilties.Hydrometallurgy
C
0

Try adding a "META-INF/persistence.xml":

    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
    </persistence-unit>
    </persistence>

Putting a breakpoint at org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo line 91 (PersistenceUnitTransactionType getTransactionType()) might also help you determine why spring thinks you have a jta-datasource or transaction type.

Celtuce answered 13/11, 2012 at 16:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.