mardi 26 septembre 2017

Spring 4.3.7 and Hibernate 5.2.9 JTA transacations based create functionality integration tests

I have code that supports JTA transactions that runs in weblogic using Spring 4.3.7 and Hibernate 5.2.9. I tested the code in application server and it works fine.

But the integration tests that run outside the application server are failing with this exception is JNDI exception.

Questions: 1) how to make tests work outside the application server? 2) Is there a way to make the tests work without using open source transaction managers? 3) Is it possible to use DBCP connection pooling with Oracle XA Datasource?

Your help is much appreciated. Thanks a lot in advance.

The details of source code that works and the test code are below.

Exception stack trace:

`**org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [javax.transaction.TransactionManager]**org.springframework.orm.hibernate5.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:542) at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) at com.sun.proxy.$Proxy53.insertData(Unknown Source) at xTest.insertData(xTest.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55) at java.lang.reflect.Method.invoke(Method.java:508) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 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:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Caused by: org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [javax.transaction.TransactionManager] at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:124) at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:95) at org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform.locateTransactionManager(WeblogicJtaPlatform.java:24) at org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform.retrieveTransactionManager(AbstractJtaPlatform.java:87) at org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform.getTransactionManager(AbstractJtaPlatform.java:98) at org.hibernate.engine.transaction.jta.platform.internal.TransactionManagerBasedSynchronizationStrategy.canRegisterSynchronization(TransactionManagerBasedSynchronizationStrategy.java:39) at org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform.canRegisterSynchronization(AbstractJtaPlatform.java:131) at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.pulse(JtaTransactionCoordinatorImpl.java:141) at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.(JtaTransactionCoordinatorImpl.java:92) at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl.buildTransactionCoordinator(JtaTransactionCoordinatorBuilderImpl.java:29) at org.hibernate.internal.AbstractSharedSessionContract.(AbstractSharedSessionContract.java:202) at org.hibernate.internal.AbstractSessionImpl.(AbstractSessionImpl.java:29) at org.hibernate.internal.SessionImpl.(SessionImpl.java:248) at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1202) at org.hibernate.internal.SessionFactoryImpl.openSession(SessionFactoryImpl.java:441) at org.springframework.orm.hibernate5.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:434) ... 37 more Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:673) at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:324) at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:361) at javax.naming.InitialContext.getNameParser(InitialContext.java:516) at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:118) ... 52 more

`Source Code:

    import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.hibernate.Session;

@EnableTransactionManagement
@EnableAspectJAutoProxy
public class XYZ
{
    @Transactional(value="xxTransactionManager", propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED, readOnly=false)
    public String insertData( String id )
        throws PersistenceException
    {
        Session session = null;


        try
        {
            session = getSessionFactory( id ).getCurrentSession();
        }
    }
}

Spring context file:`

<tx:annotation-driven transaction-manager="xxTransactionManager" />

<bean id="xxTransactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager">
        <property name="allowCustomIsolationLevels" value="true" />
        </bean>

    <bean id="xDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="xxx-xa-jniname" />
    </bean> 

    <bean id="xxsessionFactory"  class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="xDataSource" />
        <property name="mappingResources">
            <list>
                <value>xyz.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</prop>
                <prop key="hibernate.show_sql">${hibernate.show.sql}</prop>
                <prop key="hibernate.jdbc.batch_size">100</prop>
                <prop key="hibernate.query.plan_cache_max_strong_references">${hibernate.query.plan_cache_max_strong_references.size}</prop>
                <prop key="hibernate.query.plan_cache_max_soft_references">${hibernate.query.plan_cache_max_soft_references.size}</prop>
                <prop key="hibernate.statement_cache.size">${hibernate.statement_cache.size}</prop>
                <prop key="hibernate.prepare_sql">${hibernate.prepare_sql}</prop>
                <prop key="hibernate.connection.release_mode">after_statement</prop>
                <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
                <prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform</prop>    
                <prop key="hibernate.transaction.jta.coordinator_class">org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl</prop>                    
            </props>
        </property>     
    </bean>`

Test class:

@RunWith( SuiteAwareSpringRunner.class )
@ContextConfiguration( locations = { "classpath:nnContext.xml", 
                "classpath:vvContext.xml" } )
public class XYZTest
{

    @Test
    @Suite( groups = { "zztest" } )
    @Transactional
    public void testInsert( ){
    }
}

Test context file:

<bean id="xxTransactionManager" 
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sSessionFactory"/>

    <bean id="testDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="defaultAutoCommit" value="true"/>
    </bean>

    <bean id="sSessionFactory"  class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="testDataSource" />
        <property name="mappingResources">
            <list>
                <value>x.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.jdbc.batch_size">100</prop>            
                <prop key="hibernate.query.plan_cache_max_strong_references">1</prop>
                <prop key="hibernate.query.plan_cache_max_soft_references">1</prop>
                <prop key="hibernate.statement_cache.size">0</prop>
            </props>
        </property>     
    </bean>

Aucun commentaire:

Enregistrer un commentaire