Hi everybody, I'm facing a problem with Spring Ldap 1.3.0, Spring framework 3.0.5 and Oracle.
I have a very simple app that uses a few DAOs to read and write data in database and LDAP transactionally (using ContextSourceAndDataSourceTransactionManager).
Maybe it is a too obvious error.
Below is the simplified code and exception thrown.
TestRol.java
Code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-context.xml"})
@Component
public class TestRol {
static Logger logger = Logger.getLogger(TestRol.class);
@Test
public void testEliminaRol() {
Rol rol = createRolPrueba();
try {
ArrayList<Rol> roles = new ArrayList<Rol>();
roles.add(rol);
rolesBO.eliminarRoles(roles);
} catch (SUBusinessException e) {
logger.error(e,e);
fail("Error deleting rol");
}
logger.info("Rol " + rol + " deleted");
assertTrue(true);
}
private Rol createRolPrueba() { ... }
}
RolesBOBean.java
Code:
@Service
@Transactional(readOnly = true)
public class RolesBOBean implements RolesBO {
@Autowired
private RolDao rolDao;
@Autowired
private UsuariosBO usuariosBO;
@Transactional(readOnly = false)
public void eliminarRoles(List<Rol> roles) throws SUBusinessException {
for (Rol rol : roles) {
rolDao.eliminarRol(rol.getKey());
usuariosBO.eliminarRolAUsuarios(rol.getKey()); // Exception is thrown here
}
}
}
UsuariosBOBean.java
Code:
@Service
@Transactional(readOnly = true)
public class UsuariosBOBean implements UsuariosBO {
@Autowired
private UsuarioDao usuarioDao;
@Transactional(readOnly = false)
public void eliminarRolAUsuarios(RolKey rolKey) throws SUBusinessException {
List<UsuarioKey> usuariosKey = usuarioDao.obtenerUsuariosConRol(rolKey);
if(usuariosKey != null && !usuariosKey.isEmpty() ) {
for (UsuarioKey usukey : usuariosKey) {
usuarioDao.eliminarRolAUsuario(usukey, rolKey);
}
}
}
}
Exception java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHold er@12c4768] for key [org.springframework.jdbc.datasource.DriverManagerD ataSource@36d047] bound to thread [main]
Code:
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@12c4768] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@36d047] bound to thread [main]
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:240)
at org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager.doBegin(ContextSourceAndDataSourceTransactionManager.java:79)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy18.eliminarRolAUsuarios(Unknown Source)
at uy.gub.dgr.su.ejb.RolesBOBean.eliminarRoles(RolesBOBean.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy16.eliminarRoles(Unknown Source)
at uy.gub.dgr.su.test.TestRol.testEliminaRol(TestRol.java:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
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:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:94)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:192)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@12c4768] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@36d047] bound to thread [main]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:179)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:234)
... 51 more
Comments:
- If I comment @Transactional in UsuariosBOBean.java no Exception is thrown and test works fine.
- Is it a limitation of Spring Ldap that does not allow to call a @Transactional method from another one?
Thanks in advance for your help.