9 Replies Latest reply on Oct 14, 2005 9:39 AM by dunks80

    Transactions in Embedded EJB 3.0

    jacekolszak

      Hi everyone...


      I've a question about transactions in embedded EJB 3.0. I've created some simple entity bean and stateless session bean. My stateless bean doing some things with entity manager (like persist, create queries etc.). I've a simple bussiness method which throws an exception. Here it is:

      public void doSomething() throws Exception {
       Address a = new Address();
       a.setCity("Torun");
       a.setStreet("Wybickiego");
       em.persist(a);
       throw new Exception();
      }
      


      When I run the code, entity Address is creating and persisting in database. But wait a minute! I'm throwing an exception, so data in db must be rollback, isn't it ?

      Please help me, why data aren't rollback ?

      Regards
      Jacek

        • 1. Re: Transactions in Embedded EJB 3.0
          dunks80

          I'm curious about this issue as well. Can you use embeddable ejb3 with transactions? I am able to unit test my entities using embeddeable ejb3 per the microcontainer exmple located jboss-EJB-3.0_Embeddable_ALPHA_3/docs/embedded-tutorial/advanced-deployment/microcontainer-deployment.
          However, if i specifiy a transaction manager in my persistence.xml ...

           <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
           <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
           <property name="jta.UserTransaction" value="java:comp/UserTransaction" />
          


          I get the following exception when i run the test...

          [testng] org.hibernate.HibernateException: Could not locate TransactionManager
           [testng] at org.hibernate.transaction.JNDITransactionManagerLookup.getTransactionManager(JNDITransactionManagerLookup.java:26)
           [testng] at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:304)
           [testng] at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1145)
           [testng] at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:358)
           [testng] at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:484)
           [testng] at org.hibernate.ejb.Ejb3Configuration.createContainerEntityManagerFactory(Ejb3Configuration.java:202)
           [testng] at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:78)
           [testng] at org.jboss.ejb3.Ejb3Deployment.initializeManagedEntityManagerFactory(Ejb3Deployment.java:525)
           [testng] at org.jboss.ejb3.Ejb3Deployment.create(Ejb3Deployment.java:264)
           [testng] at org.jboss.ejb3.embedded.EJB3StandaloneDeployer.create(EJB3StandaloneDeployer.java:381)
          snipped...
          


          Is there a transaction manager that will work with embeddable ejb3 and the microcontainer? If not yet will there be? Also what about security? I saw that Bill was working on simple security with this task EJBTHREE-291. Is there any work around in the meantime? It's difficult to write usefull unit tests of ejbs without transaction and security. I'm not complaining...just curious as to when these features might be available?

          • 2. Re: Transactions in Embedded EJB 3.0
            elkner

            Did you try it without declaring the exception in the method signature ?

            • 3. Re: Transactions in Embedded EJB 3.0
              dunks80

              I think Jacek's point is that yes it works without the exception but that he was trying to test the entity within a transaction and of course my question was is it possible to even do that with embeddable ejb3 yet.

              • 4. Re: Transactions in Embedded EJB 3.0
                jacekolszak

                Hi everyone...


                I've found the problem. Transactions are rollback only when RuntimeException is thrown (not simple Exception).



                Here is my code... and now it's working:

                @Stateless
                @TransactionManagement(TransactionManagementType.CONTAINER)
                public class BankiBean implements BankiLocal {
                 @PersistenceContext(unitName = "ksiegi")
                 private EntityManager em;
                
                 public List<Bank> getBanki() {
                 return em.createNamedQuery("getBanki").getResultList();
                 }
                
                 public void addBank(String nrBank, String nazwaBank) {
                 Bank b = new Bank(nrBank, nazwaBank);
                 em.persist(b);
                 }
                
                 public void removeBank(Bank bank) {
                 em.remove(bank);
                 }
                
                 @TransactionAttribute(TransactionAttributeType.REQUIRED)
                 public void updateBank(Bank bank) {
                 Bank b = new Bank("powbyc", "powbyc");
                
                 em.persist(b);
                 throw new EJBException();
                 }
                
                }
                


                Regards
                Jacek

                • 5. Re: Transactions in Embedded EJB 3.0
                  dunks80

                  Jacek,
                  Since you got transaction working could you explain what method you used to bootstrap the ejb container?
                  Thanks

                  • 6. Re: Transactions in Embedded EJB 3.0
                    bill.burke

                    Only Runtime/Remote exceptions automatically rollback transactions.

                    If you want a checked exception to rollback the transaction automatically then you must do

                    @ApplicationException(rollback=true)
                    public class MyCheckedException extends Exception {}

                    • 7. Re: Transactions in Embedded EJB 3.0
                      jacekolszak

                      Dunks, I've used an example from embedded-tutorial from ejb3embeddable archive (example called embedded-war, class Main).

                      Here is the code:

                      
                      EJB3StandaloneBootstrap.boot(null);
                      
                      deployer = new EJB3StandaloneDeployer();
                      deployer.setJndiProperties(getInitialContextProperties());
                      deployer.create();
                      deployer.start();
                      ctx = getInitialContext();
                      .
                      .
                      .
                      public static InitialContext getInitialContext() throws Exception {
                       Hashtable props = getInitialContextProperties();
                       return new InitialContext(props);
                      }
                      
                      private static Hashtable getInitialContextProperties() {
                       Hashtable<String, String> props = new Hashtable<String, String>();
                       props.put("java.naming.factory.initial",
                       "org.jnp.interfaces.LocalOnlyContextFactory");
                       props.put("java.naming.factory.url.pkgs",
                       "org.jboss.naming:org.jnp.interfaces");
                       return props;
                      }
                      
                      


                      • 8. Re: Transactions in Embedded EJB 3.0
                        dunks80

                        Thanks for the reply Jacek, Still having some problems...maybe you or someone here can help. So instead of following the embedded-war example I'm following the EmbeddedEjb3TestCase from the new test-with-junit tutorial. I'm able to get an entity manager and a transaction manager. I begin the transaction...and try to persist my entity but i get the following error.

                        javax.persistence.TransactionRequiredException: no transaction is in progress
                         at org.hibernate.ejb.AbstractEntityManagerImpl.checkTransactionActive(AbstractEntityManagerImpl.java:130)
                         at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:135)
                         at org.jboss.ejb3.entity.InjectedEntityManager.persist(InjectedEntityManager.java:97)
                         at core.service.Test.authenticationTest(Test.java:51)
                         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                         at java.lang.reflect.Method.invoke(Method.java:585)
                         at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:352)
                         at org.testng.internal.Invoker.invokeMethod(Invoker.java:343)
                         at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:509)
                         at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:90)
                         at org.testng.TestRunner.privateRun(TestRunner.java:620)
                         at org.testng.TestRunner.run(TestRunner.java:503)
                         at org.testng.SuiteRunner.privateRun(SuiteRunner.java:200)
                         at org.testng.SuiteRunner.run(SuiteRunner.java:126)
                         at org.testng.eclipse.runner.RemoteTestNG.run(RemoteTestNG.java:99)
                         at org.testng.eclipse.runner.RemoteTestNG.main(RemoteTestNG.java:138)
                        
                        


                        it may be worth noting that i am not going against a local Hypersonic database but a remote SQL Server database. Here is a snippet from my embedded-jboss-beans.xml file

                        
                        <bean name="DefaultDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
                         <property name="driverClass">net.sourceforge.jtds.jdbc.Driver</property>
                         <property name="connectionURL">jdbc:jtds:sqlserver://myserver:1433/mydb</property>
                         <property name="userName">username</property>
                         <property name="password">****</property>
                         <property name="jndiName">java:jdbc/mydb</property>
                         <property name="minSize">0</property>
                         <property name="maxSize">10</property>
                         <property name="blockingTimeout">1000</property>
                         <property name="idleTimeout">100000</property>
                         <property name="transactionManager"><inject bean="TransactionManager"/></property>
                         <property name="cachedConnectionManager"><inject bean="CachedConnectionManager"/></property>
                         <property name="initialContextProperties"><inject bean="InitialContextProperties"/></property>
                         </bean>
                        


                        it seems to create the datasource no problem...one thing I'm curious about is if I'm going against a remote database should my DefaultDSBootstrap class be something else instead of org.jboss.resource.adapter.jdbc.local.LocalTxDataSourc or is that Ok?

                        Basically I'm trying to run a testng test that uses embeddable ejb to first persist a record to the db using the entity manager and then pull the record out again using a stateless session bean.

                        Here is my test sorry for all the pasting...
                        public class Test
                        {
                         private TransactionManager transactionManager;
                         private EntityManager entityManager;
                         private EJB3StandaloneDeployer deployer;
                        
                         @org.testng.annotations.Test()
                         public void authenticationTest() throws Exception
                         {
                         User user=new User();
                         user.setUsername("username");
                         user.setPassword("password");
                         user.setEmail("someemail@somewhere.com");
                         user.setCreated(new Date(System.currentTimeMillis()));
                         transactionManager.begin();
                         entityManager.persist(user);
                         transactionManager.commit();
                        
                         AuthenticationService service = (AuthenticationService) getInitialContext().lookup(AuthenticationService.class.getName());
                         User user2 = service.authenticate("username", "password");
                         assert (user != null);
                         assert(user2.equals(user));
                        
                         }
                        
                        
                         public void setupEmbeddedEJB()throws Exception
                         {
                         EJB3StandaloneBootstrap.boot(null);
                         EJB3StandaloneBootstrap.deployXmlResource("ejb3-deployment.xml");
                        
                        
                         //
                         }
                        
                         /**
                         * Used for your initial lookup of an ejb
                         *
                         * @return
                         * @throws Exception
                         */
                         public InitialContext getInitialContext() throws Exception
                         {
                         Hashtable props = getInitialContextProperties();
                         InitialContext context = new InitialContext(props);
                         return context;
                         }
                        
                         private Hashtable getInitialContextProperties()
                         {
                         Hashtable props = new Hashtable();
                         props.put("java.naming.factory.initial", "org.jnp.interfaces.LocalOnlyContextFactory");
                         props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
                         return props;
                         }
                        
                        
                        
                         @Configuration(beforeSuite=true)
                         private void setup() throws Exception
                         {
                         setupEmbeddedEJB();
                         transactionManager=(TransactionManager) getInitialContext().lookup("java:/TransactionManager");
                         entityManager=(EntityManager) getInitialContext().lookup("java:/EntityManagers/insight");
                         }
                        
                         @Configuration(afterTest=true)
                         private void cleanup() throws Exception
                         {
                        
                         Connection con=((Session)entityManager).connection();
                         Statement statement=con.createStatement();
                         statement.execute("delete * from usr");
                         }
                        
                        
                        
                        }
                        




                        • 9. Re: Transactions in Embedded EJB 3.0
                          dunks80

                          I got it working just like the EmbeddedEjb3TestCase. My problem was that while i was trying to figure alll this out I had commented out some properties in the default.persistence.properties...that was messing me up. Thanks to everyone for the help.