Thanks..I was trying different combinations and finally got confused. Well, as suggested (also David Blevins said earlier), I would always try to use JTA transactions incase I am using EM in an EJB.

Thanks
Phani

On Mon, Jun 16, 2008 at 11:09 PM, David Jencks <david_jencks@yahoo.com> wrote:

On Jun 16, 2008, at 5:21 AM, Phani Madgula wrote:

Hi,

I tried to create a application managed entity manager as follows.

persistence.xml
-----------------------
<?xml version="1.0" encoding="UTF-8"?>
<persistence    xmlns="http://java.sun.com/xml/ns/persistence"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"
                xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

    <persistence-unit name="AccountUnit" transaction-type="RESOURCE_LOCAL">

        <description>BeanManagedJPA</description>

        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>

        <jta-data-source>AccountDS</jta-data-source>

        <class>sample.jpa.Account</class>
        <class>sample.jpa.Person</class>

    </persistence-unit>
</persistence>

Here the 'AccountDS' is the datasource deployed over 'AccountDB' in embedded derby database.
---------------

I have the stateful 'AccountBean' that has the following code
---------------
@Stateful
@Local(AccountInterface.class)
@TransactionManagement(TransactionManagementType.BEAN)
public class AccountBean implements AccountInterface{
   
    @PersistenceUnit(unitName="AccountUnit")
     private EntityManagerFactory emf;
   
    private EntityManager em;
   
    Account account;
    Person person;
   
    @PostConstruct
    public void init(){
        em = emf.createEntityManager();
    }
   
    public void initialize(int accountNumber){
       
        account = em.find(Account.class, accountNumber);
       
        if(account == null)throw
           new IllegalStateException("Account number ("+accountNumber+") not found");


        person = em.find(Person.class, account.getPersonId());
       
        if(person == null)throw new IllegalStateException       
         ("Person Id("+account.getPersonId()+
           ") not found. There is a descripancy in the database for account number
          ("+accountNumber+")");

    }
   
    [...]
   
        public void updateAllValues(String address, String personName, double balance){
            em.getTransaction().begin();
            System.out.println("Local Transaction Begin-->");
            setAddress(address);
            setPersonName(personName);
            setBalance(balance);
            em.getTransaction().commit();
            System.out.println("Local Transaction Commit-->");
    }
   
    [...]
        public void withdraw(double amount){

            if(amount > getBalance())

             throw new
IllegalStateException("The amount("+amount+
              ") to be withdrawn is more than the
              available balance("+getBalance()+")");

            try{
                System.out.println("Method withdraw : message ---> 1");
                em.joinTransaction();
                System.out.println("Method withdraw : message ---> 2");
                setBalance(getBalance() - amount);
                System.out.println("Method withdraw : message ---> 3");
        }catch(Exception e){
            throw new IllegalStateException(e);
        }
       
    }
   
    public void deposit(double amount){
        try{
            em.joinTransaction();
            setBalance(getBalance() + amount);
        }catch(Exception e){
            throw new IllegalStateException(e);
        }
       
    }

The setAddress(address), setPersonName(personName), setBalance(balance) methods simply set the values to 'Account' and 'Person' entities declared at the class level. I also call 'initialize()' method to initialize 'person' and 'account' fields in the stateful session bean. Please also note that @TransactionManagement(TransactionManagementType.BEAN) is declared.
---------------

The 'updateAllValues()' method uses local transaction to update name, address, balance fields in 'account' and 'person' entities. It is expected that the method is called with no active transaction.

However, 'withdraw(amount)' and 'deposit(amount)' methods are called in a transaction. Hence, the entity managers are joined to the active transaction.

I think this is your mistake.  Since you declared the ejb to have bean-managed tx, when you call any method on the ejb, any existing jta transaction (such as the one you just started in the servlet using UserTransaction) is suspended so that your ejb can do its own transaction control.  I don't think you can mix the styles of tx control as you appear to be trying to do.

Also I don't think that a resource-local em is enrolled in any jta transactions under any circumstances, although I'm not too sure about this.  I'm pretty sure it doesn't happen without a method call.


thanks
david jencks



The typical web client for the bean is as follows.
---------------

    [...]
   
    int debitAccount = Integer.parseInt(request.getParameter("accountNumber1"));
    int creditAccount = Integer.parseInt(request.getParameter("accountNumber2"));
   
    double amount = Double.parseDouble(request.getParameter("amount"));
   
    Context ctx = new InitialContext();
   
    AccountInterface debitAccountBean = (AccountInterface)ctx.lookup("java:comp/env/ejb/AccountInterface");
    debitAccountBean.initialize(debitAccount);
   
    AccountInterface creditAccountBean = (AccountInterface)ctx.lookup("java:comp/env/ejb/AccountInterface");
    creditAccountBean.initialize(creditAccount);

    UserTransaction ut = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
   
    ut.begin();
   
    debitAccountBean.withdraw(amount);
    creditAccountBean.deposit(amount);
   
    ut.commit();
   
    [...]
---------------

When I exceute this part of code, I am getting the following exception at the point where 'em.joinTransaction()' is performed in the 'withdraw(amount)' method above.

*********************
Method withdraw : message ---> 1
14:47:38,828 ERROR [[jsp]] Servlet.service() for servlet jsp threw exception
java.rmi.NoSuchObjectException: Not Found
        at org.apache.openejb.core.stateful.StatefulInstanceManager.activateInst
ance(StatefulInstanceManager.java:317)
        at org.apache.openejb.core.stateful.StatefulInstanceManager.obtainInstan
ce(StatefulInstanceManager.java:282)
        at org.apache.openejb.core.stateful.StatefulInstanceManager.getBeanEntry
(StatefulInstanceManager.java:560)
        at org.apache.openejb.core.stateful.StatefulInstanceManager.setBeanTrans
action(StatefulInstanceManager.java:126)
        at org.apache.openejb.core.stateful.StatefulBeanManagedTxPolicy.afterInv
oke(StatefulBeanManagedTxPolicy.java:77)
        at org.apache.openejb.core.stateful.StatefulContainer._invoke(StatefulCo
ntainer.java:467)
        at org.apache.openejb.core.stateful.StatefulContainer.businessMethod(Sta
tefulContainer.java:413)
        at org.apache.openejb.core.stateful.StatefulContainer.invoke(StatefulCon
tainer.java:271)
        at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbO
bjectProxyHandler.java:217)
        at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectPr
oxyHandler.java:77)
        at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHa
ndler.java:321)
        at org.apache.openejb.util.proxy.Jdk13InvocationHandler.invoke(Jdk13Invo
cationHandler.java:49)
        at $Proxy152.withdraw(Unknown Source)
        at org.apache.jsp.TransferAmount_jsp._jspService(TransferAmount_jsp.java
:85)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper
.java:388)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:3
20)
        at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
icationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
ilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV
alve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV
alve.java:175)
        at org.apache.geronimo.tomcat.valve.DefaultSubjectValve.invoke(DefaultSu
bjectValve.java:56)
        at org.apache.geronimo.tomcat.GeronimoStandardContext$SystemMethodValve.
invoke(GeronimoStandardContext.java:406)
        at org.apache.geronimo.tomcat.valve.GeronimoBeforeAfterValve.invoke(Gero
nimoBeforeAfterValve.java:47)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j
ava:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j
ava:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal
ve.java:109)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:
563)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.jav
a:263)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java
:844)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.proce
ss(Http11Protocol.java:584)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:44
7)
        at java.lang.Thread.run(Thread.java:803)
******************

I verified with both AG2.1 and AG2.1.1. Can somebody throw some light on this issue??

Thanks
Phani