views:

40

answers:

1

Seam advises using an Extended persistent context in a Stateful Session Bean, in order to have Seam-managed persistence.

I am not clear on whether the above advice casts any implications on the way we want to have Seam-managed transactions. This is because our architecture is different. We have the following persistence context in a Stateless EJB:

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class CrudServiceBean implements CrudService {

    @PersistenceContext(type = PersistenceContextType.TRANSACTION)
    private EntityManager em;
...
}

Our DAOs invoke the above CrudServiceBean are Stateless EJBs (some of them are also Seam components) with @TransactionAttribute(TransactionAttributeType.REQUIRED). So, our transactions are handled by the container (WebLogic) and not Seam.

However, we now need to satisfy the following scenario: We need to have a front-end Seam component (non-EJB) invoke multiple DAO (EJB) methods and wrap all of them in a single transaction. If I understand correctly, we need to have Seam-managed transactions.

Can we have Seam-managed transactions as in the scenario I described, without having a Seam-managed persistence context? Or are the two irrelevant?

+1  A: 

As said

We need to have a front-end Seam component (non-EJB) invoke multiple DAO (EJB) methods and wrap all of them in a single transaction

But

Our transactions are handled by the container - Also called Container Managed Transaction (The container Takes care of calling begin and commit method used by each underlying resource-manager Transaction)

The first issue is That you have a scenario where a non-EJB invoke multiple DAO, each one an EJB. You could Think of

@Name("nonEjbComponent")
public class NonEjbComponent {

    private @In DaoEjbComponent daoEjbComponent;
    private @In OtherDaoEjbComponent otherDaoEjbComponent;
    private @In AnotherDaoEjbComponent anotherDaoEjbComponent;

    private @In UserTransaction userTransation;

    public void wrapperAllOfThem() {

         userTransation.begin();

             daoEjbComponent.save(someEntity);
             otherDaoEjbComponent.update(otherEntity);
             anotherDaoEjbComponent.delete(anotherEntity);

         userTransation.commit();

    }

}

But JEE specification 3.0 states

The enterprise bean with Either bean-managed or container-managed transaction demarcation must be a session bean or a message-driven bean.

So you can not use the scenario above. And because all of your DAO are container-managed Transaction, JEE specification does not allow you To use container-managed and bean-managed Transaction at the same time

So The solution is

Wrap all of DAO in a EJB Stateless session bean whose Transaction is container-managed. It will behave like a delegate component

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Name("wrapperStateless")
public class WrapperStatelessImpl implements WrapperStateless {

    private @In DaoEjbComponent daoEjbComponent;
    private @In OtherDaoEjbComponent otherDaoEjbComponent;
    private @In AnotherDaoEjbComponent anotherDaoEjbComponent;

    public void wrapperAllOfThem() {

        daoEjbComponent.save(someEntity);
        otherDaoEjbComponent.update(otherEntity);
        anotherDaoEjbComponent.delete(anotherEntity);

    }

}

And inside your non-EJB component, use

@Name("nonEjbComponent")
public class NonEjbComponent {

    private @In WrapperStateless wrapperStateless;

    public void wrapperAllOfThem() {
        wrapperStateless.wrapperAllOfThem();
    }

}
Arthur Ronald F D Garcia