users@glassfish.java.net

Issue with persistence context propagation: SFSB call SLSB

From: <glassfish_at_javadesktop.org>
Date: Sun, 14 Dec 2008 17:51:45 PST

Hi,

The issue I have is with WebSphere 6.1 + EJB 3 feature pack. However the issue itself is generic so I've decided to post it here too. Hopefully somebody can share some insight into it.

According to EJB 3 spec, it seems that we can call a stateless session bean method from inside a stateful session bean. But WAS 6.1 + EJB 3 feature pack does not seem to work in this aspect.

Here is the detail of my test:

I have a simple entity bean called Customer. A simple SLSB called CustomerDAO like this:

@Stateless(name="CustomerDAO")
public class CustomerDAOImpl implements CustomerDAO
{
        @PersistenceContext(unitName="OrderDB")
        EntityManager em;
        
        @TransactionAttribute(TransactionAttributeType.REQUIRED)
        public Customer findCustomer(int customerId) throws CustomerDoesNotExist {
                Customer customer = (Customer) em.find(Customer.class, customerId);
                if (customer == null) {
                        throw new CustomerDoesNotExist("Customer does not exist");
                }
                return customer;
        }
...
}

Now a SFSB:
@Stateful(name="EditCustomerService")
public class EditCustomerServiceImpl implements EditCustomerService
{
        @PersistenceContext(unitName="OrderDB", type=PersistenceContextType.EXTENDED)
        EntityManager em;
        
        @EJB
        CustomerDAO customerDAO;
        
        Customer customer;
        
        @TransactionAttribute(TransactionAttributeType.REQUIRED)
        public void load(PrintWriter out)
        {
                try {
                        customer = customerDAO.findCustomer(1);
// If I comment out the line above and uncomment the line below, everything works
                        //customer = (Customer) em.find(Customer.class, 1);
                        out.println("customer loaded: " + customer);
                } catch (Exception ex) {
                        ex.printStackTrace();
                }
        }
        @TransactionAttribute(TransactionAttributeType.SUPPORTS)
        public void edit(PrintWriter out) {
                out.println("customer edited: " + customer + ", " + customerContained);
                Date now = new Date();
                customer.setName(customer.getName() + " " + now.getTime());
                customerContained = em.contains(customer);
                out.println("customer edited: " + customer + ", " + customerContained);
        }

        @TransactionAttribute(TransactionAttributeType.REQUIRED)
        @Remove
        public void save(PrintWriter out) {
// If customer is detached, I have to call merge.
                //em.merge(customer);
// In extended PC entities are managed so I should not need to call flush
                //em.flush();
                customerContained = em.contains(customer);
                out.println("customer saved: " + customer + ", " + customerContained);
        }
}

However when EditCustomerService.load() is called from inside a servlet, customer becomes a detached object. As a result, after I call edit and save, the change made inside edit is not saved.

The key is the load method. I expect when the load is called, a transaction will be started. But I'm not sure when the persistence context for the SFSB is created. It seems that it is created much later, before a new persistence context is created inside CustomerDAO.findCustomer(). I guess a new persistence context is created inside CustomerDAO.findCustomer() because there is no PC associated with the transaction when the thread enters CustomerDAO.findCustomer().

I read EJB 3 spec again. It seems EJB 3 does not exactly say when an extended PC is created. It just says that an extended PC is created when the corresponding EntityManager is created and its life cycle goes with that of the SFSB itself. EJB 3 spec does not say exactly the extended PC is created. Is it created when the SFSB is constructed? Apparently not in WebSphere.

Can somebody please shed some light into this?
[Message sent by forum member 'anqingxu' (anqingxu)]

http://forums.java.net/jive/thread.jspa?messageID=321655