Announcement Announcement Module
Collapse
No announcement yet.
JTA UserTransaction is not available at JNDI location [java Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JTA UserTransaction is not available at JNDI location [java

    Hi everybody,
    I am getting an exception related with jta when I am unit testing DAO objects that I created.
    My conf:
    - using spring+hibernate
    - using JTA as trans. mgm.
    - I have multiple datasources (Oracle,SQL Server)

    I am getting the following exception while I try to unit test my DAO class...
    Code:
    junit.framework.AssertionFailedError: Exception in constructor: testSaveAndRemoveUser (org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in URL [file:D:/Workspaces/SpringTestWS/SpringTemplate/WebContent/WEB-INF/applicationContext.xml]: Initialization of bean failed; nested exception is [b]org.springframework.transaction.TransactionSystemException: JTA UserTransaction is not available at JNDI location [java:comp/UserTransaction];[/b] nested exception is 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
    org.springframework.transaction.TransactionSystemException: JTA UserTransaction is not available at JNDI location [java:comp/UserTransaction]; nested exception is 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
    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:652)
    	at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:255)
    	at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:292)
    	at javax.naming.InitialContext.lookup(InitialContext.java:359)
    	at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:123)
    	at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:85)
    	at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:121)
    	at org.springframework.transaction.jta.JtaTransactionManager.lookupUserTransaction(JtaTransactionManager.java:346)
    	at org.springframework.transaction.jta.JtaTransactionManager.afterPropertiesSet(JtaTransactionManager.java:311)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:991)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:288)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:208)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:136)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:230)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:284)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>&#40;ClassPathXmlApplicationContext.java&#58;80&#41;
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>&#40;ClassPathXmlApplicationContext.java&#58;65&#41;
    	at com.elikasu.springtemplate.dao.BaseDAOTestCase.<init>&#40;BaseDAOTestCase.java&#58;20&#41;
    	at com.elikasu.springtemplate.dao.UserDAOTest.<init>&#40;UserDAOTest.java&#58;11&#41;
    	at java.lang.reflect.Constructor.newInstance&#40;Native Method&#41;
    	at junit.framework.TestSuite.createTest&#40;TestSuite.java&#58;131&#41;
    	at junit.framework.TestSuite.addTestMethod&#40;TestSuite.java&#58;114&#41;
    	at junit.framework.TestSuite.<init>&#40;TestSuite.java&#58;75&#41;
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.getTest&#40;RemoteTestRunner.java&#58;331&#41;
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests&#40;RemoteTestRunner.java&#58;369&#41;
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run&#40;RemoteTestRunner.java&#58;276&#41;
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main&#40;RemoteTestRunner.java&#58;167&#41;
    &#41;
    	at junit.framework.Assert.fail&#40;Assert.java&#58;47&#41;
    	at junit.framework.TestSuite$1.runTest&#40;TestSuite.java&#58;263&#41;
    	at junit.framework.TestCase.runBare&#40;TestCase.java&#58;127&#41;
    	at junit.framework.TestResult$1.protect&#40;TestResult.java&#58;106&#41;
    	at junit.framework.TestResult.runProtected&#40;TestResult.java&#58;124&#41;
    	at junit.framework.TestResult.run&#40;TestResult.java&#58;109&#41;
    	at junit.framework.TestCase.run&#40;TestCase.java&#58;118&#41;
    	at junit.framework.TestSuite.runTest&#40;TestSuite.java&#58;208&#41;
    	at junit.framework.TestSuite.run&#40;TestSuite.java&#58;203&#41;
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests&#40;RemoteTestRunner.java&#58;392&#41;
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run&#40;RemoteTestRunner.java&#58;276&#41;
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main&#40;RemoteTestRunner.java&#58;167&#41;

  • #2
    You should run your Tests inside a container that provide a UserTransaction or use an external OTM like JTOM.

    Comment


    • #3
      I am using WebSphere AppServer 5.1 . My tests work fine when using CactusStrutsTestCase for struts actions testing.
      This works fine:
      Code:
      public class UserActionTest extends CactusStrutsTestCase &#123;
      	public UserActionTest&#40;String arg0&#41; &#123;
      		super&#40;arg0&#41;;
      	&#125;
      
      	public static void main&#40;String&#91;&#93; args&#41; &#123;
      		junit.textui.TestRunner.run&#40;UserActionTest.class&#41;;
      	&#125;
      
      	public void testAddUser&#40;&#41;&#123;		
      		setRequestPathInfo&#40;"/user"&#41;;
      		addRequestParameter&#40;"method","save"&#41;;
      		addRequestParameter&#40;"user.firstName","Simon"&#41;;
      		addRequestParameter&#40;"user.lastName","Simon"&#41;;
      		actionPerform&#40;&#41;;
      		verifyForward&#40;"listUsers"&#41;;
      		verifyNoActionErrors&#40;&#41;;
      	&#125;
      &#125;
      But when I want to test my DAO classes which are defined in applicationContext.xml, I get the exception which is in my previous post. Dao test class:
      Code:
      public class UserDAOTest extends BaseDAOTestCase &#123;
      	private User user=null;
      	private UserDAO dao=null;
      	/* &#40;non-Javadoc&#41;
      	 * @see junit.framework.TestCase#setUp&#40;&#41;
      	 */
      
      	protected void setUp&#40;&#41; throws Exception &#123;
      		super.setUp&#40;&#41;;
      		logger=Logger.getLogger&#40;UserDAOTest.class&#41;;
      		dao=&#40;UserDAO&#41;ctx.getBean&#40;"userDAO"&#41;;
      	&#125;
      	public void testSaveUser&#40;&#41;&#123;
      		user=new User&#40;&#41;;
      		user.setFirstName&#40;"Meggie"&#41;;
      		user.setLastName&#40;"Glynhall"&#41;;
      		
      		dao.saveUser&#40;user&#41;;
      		assertTrue&#40;"primarykey assigned&#58;",user.getId&#40;&#41;!=null&#41;;
      		logger.info&#40;user&#41;;	
      		assertTrue&#40;user.getFirstName&#40;&#41;!=null&#41;;
      	&#125;
      &#125;
      and BaseDaoTestCase:

      Code:
      public class BaseDAOTestCase extends TestCase &#123;
      	protected static Logger logger = Logger.getLogger&#40;BaseDAOTestCase.class&#41;;
      	protected ApplicationContext ctx = null;
      
      	public BaseDAOTestCase&#40;&#41; &#123;		
      		String&#91;&#93; paths = &#123;"file&#58;D&#58;/Workspaces/SpringTestWS/SpringTemplate/WebContent/WEB-INF/applicationContext.xml"&#125;;
      		ctx = new ClassPathXmlApplicationContext&#40;paths&#41;;
      	&#125;
      &#125;
      Are there any examples of in-container testing with Spring...
      Thanks for your helps...

      Comment


      • #4
        UserDAOTest / BaseDAOTestCase do not seem to be running inside a container. So one thing you can do is to extract the UserTransaction from Jndi and configure a JtaTransactionManager:
        Code:
        <bean id="userTransaction" class="org.springframework.jndi.JndiObjectFactoryBean"> 
            <property name="jndiName"> 
              <value>java&#58;comp/UserTransaction</value> 
            </property> 
            <property name="environment"> 
              <props> 
                <!-- provide WebSphere AppServer 5.1 environment properties here -->
                <prop key="key1">value1</prop> 
                <prop key="key2">value2</prop> 
                <prop key="key3">value3</prop> 
              </props> 
            </property> 
          </bean>
        
          <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
            <constructor-arg><ref local="userTransaction" /></contructor-arg>
          </bean>
        I never tried this before...
        I have however a question with regards to your Tests: Why are you Unit Testing your class inside the container? Did you consider UnitTesting the class outside of the container using a plain HibernateTransactionManager?

        HTH

        Comment


        • #5
          Thanks Omar,
          regarding to your question:
          I have however a question with regards to your Tests: Why are you Unit Testing your class inside the container?
          I don't really want to test my classes inside a container but I have defined my dataSources(3 XA DataSources) in my web-server (WebSphere 5.1). And I reach them through jndi:
          Code:
          <bean id="DB2DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                  <property name="jndiName">
                  	<value>jdbc/DB2DS_XA</value>
                  </property>
              </bean>
              <bean id="DB2DataSource2" class="org.springframework.jndi.JndiObjectFactoryBean">
                  <property name="jndiName">
                  	<value>jdbc/DB2DS_XA2</value>
                  </property>
              </bean>
              <bean id="SQLSRVDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                  <property name="jndiName">
                  	<value>jdbc/SQLSRV_XA</value>
                  </property>
              </bean>
          How can I remove this dependency from container. How can I define my XA dataSources in applicationContext without depending on the container.
          Thanks,

          Comment


          • #6
            If you don't actually need XA, i.e. in the case of a single DataSource respectively SessionFactory, you could use Spring's DataSourceTransactionManager or HibernateTransactionManager (just for test environments or also for production).

            In your case where you need XA for your three DataSources, you could use a local JOTM instance (ObjectWeb's JTA implementation) with locally defined XADataSources (instead of fetching DataSources from JNDI). This is directly supported in Spring: Have a look at JotmFactoryBean's javadoc.

            Obviously, you'd need to duplicate your DataSource configuration for the latter scenario (once for WebSphere, once for the local XADataSources), but as a benefit you'll be able to run your business code (depending on XA transactions) completely outside the J2EE server.

            Juergen

            Comment


            • #7
              Juergen, what if you used per-datasource transaction management (DataSourceTransactionManager or HibernateTransactionManager) just during development and unit testing, then to switch your Spring config to use JTA (JtaTransactionManager) when doing full integrated testing? Do you see a problem with this or is it just as easy to use JotmFactoryBean from the start? I'm in the same boat - I need JTA across multiple datasources, but I don't want to make testing a pain.

              Thanks in advance, Scott

              Comment


              • #8
                Well there's nothing wrong with switching your config later, per se, but you'll be going from non XA/2PC to XA/2PC with multiple datasources, then there are obviously differences in how things can interact. If you need to work with multiple datasources and XA, then going that route from the start might ensure you don't have surprises later. On the other hand, if somebody is eventually going to run in a container and need JTA, but currently don't really need it, as they only use one datasource, then it's very common to develop with something like HibernateTransactionManager, and later switch to JTATransactionManager when you switch containers...

                Comment

                Working...
                X