Hello everyone,
I'm trying to use Spring(3.2.0.RELEASE) + Hibernate(4.2.0) + C3P0(0.9.2.1). I have a test-case that executes update on the database and I get this error:
Code:
testCreateModifications(com.xxxxxx.core.ModelServiceTest) Time elapsed: 0.091 sec <<< ERROR!
org.springframework.transaction.TransactionSystemException: Could not roll back JPA transaction; nested exception is javax.persistence.PersistenceException: unexpected error when rollbacking
at org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.java:543)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:588)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:297)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:192)
at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:396)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:91)
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.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
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:236)
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: javax.persistence.PersistenceException: unexpected error when rollbacking
at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.java:109)
at org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.java:539)
... 31 more
Caused by: org.hibernate.TransactionException: rollback failed
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:215)
at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.java:106)
... 32 more
Caused by: org.hibernate.TransactionException: unable to rollback against JDBC connection
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:167)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:209)
... 33 more
Caused by: java.sql.SQLException: You can't operate on a closed Connection!!!
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:77)
at com.mchange.v2.c3p0.impl.NewProxyConnection.rollback(NewProxyConnection.java:866)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:163)
... 34 more
Caused by: java.lang.NullPointerException
at com.mchange.v2.c3p0.impl.NewProxyConnection.rollback(NewProxyConnection.java:860)
... 35 more
My configurations are below:
spring xml context
Code:
<!-- Scan for annotation configured controller -->
<context:component-scan base-package="com.xxxx"/>
<cache:annotation-driven cache-manager="cacheManager"/>
<tx:annotation-driven transaction-manager="transactionManager" mode="proxy" proxy-target-class="true"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="ehcache">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaAdapter"/>
<property name="packagesToScan" value="com.xxxxx" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaProperties">
<props>
<prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
<prop key="hibernate.archive.autodetection">class</prop>
<!-- prop key="hibernate.max_fetch_depth">2</prop-->
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.connection.driver_class">${jdbc.driverClassName}</prop>
<prop key="hibernate.connection.password">${jdbc.password}</prop>
<prop key="hibernate.connection.url">${jdbc.url}</prop>
<prop key="hibernate.connection.username">${jdbc.username}</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</prop>
<prop key="hibernate.c3p0.acquire_increment">3</prop>
<prop key="hibernate.c3p0.preferredTestQuery">select 1;</prop>
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">20</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">50</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
<prop key="hibernate.c3p0.automaticTestTable">MY_TEST_TABLE</prop>
<prop key="hibernate.connection.characterEncoding">utf-8</prop>
<prop key="hibernate.connection.CharSet">utf-8</prop>
<prop key="hibernate.connection.useUnicode">true</prop>
<!-- prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory</prop-->
<!-- prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop-->
<prop key="hibernate.jdbc.batch_size">50</prop>
<!-- prop key="current_session_context_class">jta</prop-->
<prop key="hibernate.order_update">true</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.DefaultNamingStrategy</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_minimal_puts">true</prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="acquireIncrement" value="1" />
<property name="idleConnectionTestPeriod" value="100" />
<property name="maxStatements" value="0" />
<property name="checkoutTimeout" value="60000" />
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false"/>
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
</bean>
My testcase:
Code:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
@ContextConfiguration(value = {"classpath:coreservices-context.xml", "classpath:coreservices-test-context.xml"})
@TransactionConfiguration(transactionManager = "transactionManager")
public class ModelServiceTest {
@Resource(name = "modelService")
private ModelService modelService;
@Before
public void setupMethod() {
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("admin", "pass", Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMINGROUP"))));
}
@Test
@Transactional(propagation = Propagation.REQUIRED)
public void testCreateModifications() {
UnitModel unit = modelService.get(1L, UnitModel.class);
unit.setName("my-custom-name");
modelService.update(unit);
....
}
}
My ModelService, which never gets called:
Code:
@Override
public void saveOrUpdate(AbstractEntityModel model) {
if (model.getPk() != null) {
LOG.info("SaveOrUpdate merging...." + model.getClass().getSimpleName());
getEntityManager().merge(model);
} else {
LOG.info("SaveOrUpdate persisting...." + model.getClass().getSimpleName());
getEntityManager().persist(model);
}
getEntityManager().flush();
}
The method in my ModelService never gets called because I have this on my method interface declaration:
Code:
@PreAuthorize("hasPermission(#model, 'WRITE') or hasPermission(#model, 'ADMINISTRATION') or hasRole('ROLE_ADMINGROUP')")
so I'm using Spring ACL to restrict the access to this method to only admin users. Any help will be much appreciated.
Thank you for your time.