tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Karan Malhi <karan.ma...@gmail.com>
Subject Re: Extended PersistenceContext and Transactions
Date Thu, 12 Feb 2009 15:06:10 GMT
Hi Thomas,

The issue was related to how to run test within a transaction. You were
trying to obtain a TransactionManager from OpenEJB and then beginning a
transaction from there. I have modified your test to show how you can call
your test within container managed transactions. The code which I added to
your test case was taken from the example at
http://openejb.apache.org/3.0/testing-transactions-example.html . This
example shows details on how to run a test within transaction.

Here is your modified code (MY COMMENTS ARE IN UPPERCASE), I also created a
src/test/resources/META-INF directory (inside the testCase module)and added
the ejb-jar.xml inside it. This allows EJB's to be discovered when OpenEJB
boots. Notice that the directory is src/test/resources and NOT
src/main/resources

package test;

import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable; // ADDED THIS

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;// ADDED THIS
import javax.ejb.TransactionAttributeType; // ADDED THIS
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.transaction.TransactionManager;

import org.apache.openejb.OpenEJB;
import org.testng.annotations.Test;

import test1.entity.AnEntity;
import test1.service.AService;
import testService.service.PersistenceSvc;

@Test(enabled = true)
public class ATest {
    private Context context; // ADDED THIS

    public void aSimpleTest() throws Exception {

        System.setProperty("log4j.category.OpenEJB", "debug");
        System.setProperty("log4j.category.openjpa", "debug");
        Properties p = new Properties();
        p.put(Context.INITIAL_CONTEXT_FACTORY,
                "org.apache.openejb.client.LocalInitialContextFactory");

        p.put("openejb.deployments.classpath.ear", "true");

        p.put("testDatabase", "new://Resource?type=DataSource");
        p.put("testDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
        p.put("testDatabase.JdbcUrl", "jdbc:hsqldb:mem:testdb"); // CHANGED
TO IN MEMORY JDBC URL -- NOT REQUIRED -- I DID NOT WANT TO START A
//SEPARATE INSTANCE OF HSQLDB

        p.put("testDatabaseUnmanaged", "new://Resource?type=DataSource");
        p.put("testDatabaseUnmanaged.JdbcDriver", "org.hsqldb.jdbcDriver");
        p.put("testDatabaseUnmanaged.JdbcUrl", "jdbc:hsqldb:mem:testdb");
        p.put("testDatabaseUnmanaged.JtaManaged", "false");
        context = new InitialContext(p);
// IF YOU UNCOMMENT THE BELOW COMMENT, IT SHOULD WORK FINE. NO ISSUES HERE
        /*
         * AStatefulService service = (AStatefulService)
         * context.lookup("AStatefulServiceImplLocal");
service.addEntity(new
         * AnEntity());
         */
// THIS IS WHERE THE ISSUE WAS -- I HAVE PULLED OUT THE CODE AND PUT IT
INSIDE doWork() TO SHOW HOW TO RUN WITHIN TRANSACTION
/*
        TransactionManager tx = OpenEJB.getTransactionManager();
        tx.begin();

        PersistenceSvc ps = (PersistenceSvc) context
                .lookup("PersistenceSvcImplLocal");

        tx.commit();
*/
    }
// ADDED THIS METHOD
    private void doWork() throws Exception {
        AService service2 = (AService) context.lookup("AServiceImplLocal");
        service2.addEntity(new AnEntity());
    }
// TransactionBean IS DEFINED BELOW AS AN INNER CLASS. THE doWork() METHOD
WILL RUN IN A TX
    public void testWithTransaction() throws Exception {
        Caller transactionBean = (Caller) context
                .lookup("TransactionBeanLocal");

        transactionBean.call(new Callable() {
            public Object call() throws Exception {
                doWork();
                return null;
            }
        });
    }
// IF YOU WANTED TO CALL doWork() OUTSIDE A TRANSACTION, THEN UNCOMMENT THE
BELOW METHOD
/*    public void testWithoutTransaction() throws Exception {
        try {
            doWork();

        } catch (javax.ejb.EJBTransactionRequiredException e) {

        }
    }
*/
// THE @Local INTERFACE
    public static interface Caller {
        public <V> V call(Callable<V> callable) throws Exception;
    }
// THE BEAN CLASS. NOTICE THE REQUIRES_NEW ATTRIBUTE
    /**
     * This little bit of magic allows our test code to execute in the scope
of
     * a container controlled transaction.
     *
     * The src/test/resource/META-INF/ejb-jar.xml will cause this EJB to be
     * automatically discovered and deployed when OpenEJB boots up.
     */
    @Stateless
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public static class TransactionBean implements Caller {

        public <V> V call(Callable<V> callable) throws Exception {
            return callable.call();
        }

    }

}


On Thu, Feb 12, 2009 at 5:01 AM, <Thomas.TH.Hamacher@partner.bmw.ch> wrote:

> Karan,
>
> Sure I do! I am glad, when I can help you!
> I´m not sure where exactly the error appears, so I simply quickly assembled
> the classes I used without tracking down the exact cause.
> So there might be some overhead which has nothing to do with the error.
>
> Just a short explanation:
> TestCase-service and TestCase-entity are just libraries, holding some
> persistence-info or additional services.
> So just build them and that´s it.
> TestCase holds a simple TestNG-TestCase. When I run that one, the error
> appears.
>
> If you need any further help, please let me know.
> If I have a misconcept violating the EJB3-specifications, please let me
> know as well.
>
> Thomas
>
>
> -----Ursprüngliche Nachricht-----
> Von: Karan Malhi [mailto:karan.malhi@gmail.com]
> Gesendet: Donnerstag, 12. Februar 2009 00:58
> An: users@openejb.apache.org
> Betreff: Re: Extended PersistenceContext and Transactions
>
> Hi Thomas,
> I could not reproduce the error. Could you share the code?
>
> On Mon, Feb 9, 2009 at 6:50 AM, <Thomas.TH.Hamacher@partner.bmw.ch> wrote:
>
> > Hi @all,
> >
> > so now I tracked down my problem with the Extended PersistenceContext.
> > The reason for failure was the TransactionManagement.
> > Anyhow I tried to work with different possibilities of Transactions,
> > but did not find a solution yet. So maybe someone can point me to the
> > right direction.
> >
> > My scenario is as follows and pretty easy. I have one
> > EntityManagerProvider using the injected EntityManager as described in
> > http://www.nabble.com/Re%3A-Obtaining-an-EntityManager-instance-outsid
> > e-an-EJB-p21701466.html
> > .
> > The I have another SessionBean, which should also be injected with an
> > Extended EntityManager.
> >
> > The EntityManager is injected perfectly into my EntityManagerProvider,
> > but when trying to use the second sessionBean with the extended
> > EntityManager I run into various problems. As I read from the
> > documentations, the Extended PersistenceContext works as follows: Any
> > changes made to the entities are queued to the EntityManager. As soon
> > as a new Transaction is started, the EntityManager joins this Transaction
> and commits changed to database.
> >
> > So therefor my first idea was, not to use a Transaction, because this
> > should be done by the container - in this case openEJB.
> > When I do so, it results in the following exception, when trying to
> > obtain the delegate of the EntityManager:
> >
> > java.lang.IllegalStateException: InternalError: an entity manager
> > should already be registered for this entended persistence unit
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManagerRegistry.getEntityManager(JtaEntityManagerRegistry.java:91)
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManager.getEntityManager(JtaEntityManager.java:61)
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManager.getDelegate(JtaEntityManager.java:92)
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManager.getDelegate(JtaEntityManager.java:41)
> >        at
> >
> com.sepus.testUtil.commons.service.BaseApplicationServerProvider.getPersistenceProvider(BaseApplicationServerProvider.java:106)
> >        at
> >
> company.commons.service.impl.PopulatorServiceImpl.<init>(PopulatorServiceImpl.java:47)
> >        at
> >
> company.commons.environment.TestEnvironment.start(TestEnvironment.java:130)
> >        at
> > company.commons.environment.TestBase.startEnvironment(TestBase.java:29)
> >        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:580)
> >        at
> > org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:398)
> >        at
> > org.testng.internal.Invoker.invokeConfigurations(Invoker.java:145)
> >        at
> org.testng.internal.Invoker.invokeConfigurations(Invoker.java:82)
> >        at
> >
> org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:167)
> >        at
> > org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:104)
> >        at org.testng.TestRunner.runWorkers(TestRunner.java:712)
> >        at org.testng.TestRunner.privateRun(TestRunner.java:582)
> >        at org.testng.TestRunner.run(TestRunner.java:477)
> >        at org.testng.SuiteRunner.runTest(SuiteRunner.java:324)
> >        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:319)
> >        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
> >        at org.testng.SuiteRunner.run(SuiteRunner.java:198)
> >        at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:821)
> >        at org.testng.TestNG.runSuitesLocally(TestNG.java:788)
> >        at org.testng.TestNG.run(TestNG.java:708)
> >        at
> >
> org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:74)
> >        at
> >
> org.apache.maven.surefire.testng.TestNGXmlTestSuite.execute(TestNGXmlTestSuite.java:92)
> >        at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
> >        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.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
> >        at
> > org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.ja
> > va:1009)
> >
> >
> > (By the way: there is probably a typo in the Exception-message)
> >
> >
> > Second try was to use the javax.persistence.EntityTransaction of the
> > EntityManager. But as soon as I try to obtain the EntityTransaction I
> > get the following Exception:
> >
> > java.lang.IllegalStateException: A JTA Entity Manager can not use an
> > entity transaction
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManager.getTransaction(JtaEntityManager.java:220)
> >        at
> >
> com.sepus.testUtil.commons.environment.TestEnvironment.start(TestEnvironment.java:127)
> >        at
> >
> com.sepus.testUtil.commons.environment.TestBase.startEnvironment(TestBase.java:29)
> >        at
> >
> org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:74)
> >        at
> >
> org.apache.maven.surefire.testng.TestNGXmlTestSuite.execute(TestNGXmlTestSuite.java:92)
> >        at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
> >        at
> >
> org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
> >        at
> > org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.ja
> > va:1009)
> >
> >
> > Third solution was to use the javax.Transaction.TransactionManager.
> > Not even better:
> >
> > DEBUG - finished invoking method create with
> > exception:javax.ejb.EJBException: nested exception is:
> > org.apache.openejb.persistence.EntityManagerAlread
> > yRegisteredException: Another entity manager is already registered for
> > this persistence unit
> > javax.ejb.EJBException: nested exception is:
> > org.apache.openejb.persistence.EntityManagerAlreadyRegisteredException:
> > Another entity manager is already
> >  registered for this persistence unit
> > org.apache.openejb.persistence.EntityManagerAlreadyRegisteredException:
> > Another entity manager is already registered for this persistence unit
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManagerRegistry$ExtendedRegistry.addEntityManagers(JtaEntityManagerRegistry.java:191)
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManagerRegistry$ExtendedRegistry.access$100(JtaEntityManagerRegistry.java:169)
> >        at
> >
> org.apache.openejb.persistence.JtaEntityManagerRegistry.addEntityManagers(JtaEntityManagerRegistry.java:129)
> >        at
> >
> org.apache.openejb.core.stateful.StatefulContainer.createEJBObject(StatefulContainer.java:288)
> >        at
> >
> org.apache.openejb.core.stateful.StatefulContainer.invoke(StatefulContainer.java:263)
> >        at
> >
> org.apache.openejb.core.ivm.EjbHomeProxyHandler.create(EjbHomeProxyHandler.java:270)
> >        at
> >
> org.apache.openejb.core.ivm.EjbHomeProxyHandler._invoke(EjbHomeProxyHandler.java:161)
> >        at
> >
> org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:286)
> >        at $Proxy77.create(Unknown Source)
> >        at
> >
> org.apache.openejb.core.ivm.naming.BusinessLocalReference.getObject(BusinessLocalReference.java:33)
> >        at
> > org.apache.openejb.core.ivm.naming.IvmContext.lookup(IvmContext.java:150)
> >        at
> >
> org.apache.openejb.core.ivm.naming.ContextWrapper.lookup(ContextWrapper.java:115)
> >        at javax.naming.InitialContext.lookup(InitialContext.java:351)
> >        at
> >
> company.testUtil.commons.service.BaseApplicationServerProvider.lookup(BaseApplicationServerProvider.java:162)
> >        at
> >
> company.testUtil.commons.service.BaseApplicationServerProvider.getService(BaseApplicationServerProvider.java:145)
> >        at
> >
> company.testUtil.commons.service.BaseApplicationServerProvider.getService(BaseApplicationServerProvider.java:136)
> >        at
> >
> company.testUtil.commons.environment.TestEnvironment.getService(TestEnvironment.java:332)
> >        at
> >
> company..iis.test.core.populator.IISPopulator.getSvc(IISPopulator.java:39)
> >        at
> >
> company..iis.test.core.populator.RegionPopulator.populate(RegionPopulator.java:27)
> >        at
> >
> company.testUtil.commons.service.impl.PopulatorServiceImpl.doPopulate(PopulatorServiceImpl.java:176)
> >        at
> >
> company.testUtil.commons.service.impl.PopulatorServiceImpl.recursivePopulation(PopulatorServiceImpl.java:121)
> >        at
> >
> company.testUtil.commons.service.impl.PopulatorServiceImpl.populate(PopulatorServiceImpl.java:91)
> >        at
> >
> company.testUtil.commons.environment.TestEnvironment.start(TestEnvironment.java:133)
> >        at
> >
> company.testUtil.commons.environment.TestBase.startEnvironment(TestBase.java:29)
> >        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:580)
> >        at
> > org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:398)
> >        at
> > org.testng.internal.Invoker.invokeConfigurations(Invoker.java:145)
> >        at
> org.testng.internal.Invoker.invokeConfigurations(Invoker.java:82)
> >        at
> >
> org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:167)
> >        at
> > org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:104)
> >        at org.testng.TestRunner.runWorkers(TestRunner.java:712)
> >        at org.testng.TestRunner.privateRun(TestRunner.java:582)
> >        at org.testng.TestRunner.run(TestRunner.java:477)
> >        at org.testng.SuiteRunner.runTest(SuiteRunner.java:324)
> >        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:319)
> >        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
> >        at org.testng.SuiteRunner.run(SuiteRunner.java:198)
> >        at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:821)
> >        at org.testng.TestNG.runSuitesLocally(TestNG.java:788)
> >        at org.testng.TestNG.run(TestNG.java:708)
> >        at
> >
> org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:74)
> >        at
> >
> org.apache.maven.surefire.testng.TestNGXmlTestSuite.execute(TestNGXmlTestSuite.java:92)
> >        at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
> >        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.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
> >        at
> > org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.ja
> > va:1009)
> >
> >
> > And lastly, using the UserTransaction did not succeed, as no
> > UserTransaction has been injected and therefor has a null-value.
> >
> > So now I am a bit confused, how to work with the Extended
> > PersistenceContext using openEJB and Hibernate as EntityManager.
> >
> > Can anybody maybe tell me, what I am missing or what I have to do to
> > make it work?
> >
> > Thanks
> > Thomas
> >
>
>
>
> --
> Karan Singh Malhi
>



-- 
Karan Singh Malhi

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message