Actually I want to migrate a Seam 2 application to Java EE 7 with CDI and are trying to imitate the behavior of the Seam Home Component.
I am creating a application-managed EntityManager
with a CDI producer and want to use it in a @ConversationScoped
bean. I have defined my own EntityManager as a serializable wrapper around the default EntityManager implementation, which is just calling the methods of the delegate. The CDI producer looks as follows:
@ApplicationScoped
public class EntityManagerProducer
{
@PersistenceUnit(unitName = "showcase")
private EntityManagerFactory emFactory;
@Produces
@RequestScoped
public EntityManager createEntityManager()
{
return new ExtendedEntityManager(emFactory.createEntityManager());
}
public void dispose(@Disposes final EntityManager entityManager)
{
if (entityManager.isOpen())
{
entityManager.close();
}
}
}
Do I need to define my conversationscoped
Home component as @Stateful
? An entity which was loaded by find
on the injected entity manager is in a second step of the conversation not longer managed. A call of joinTransaction
does not reattach the entity to the current EntityManager.
Edit:
I want to give some more information about the use case I am facing: As mentioned I want to imitate the Home component of Seam 2. So I created a own Home super class with CRUD methods for creating, updating and removing an entity. In the method for updating an entity I use following code:
public String update()
{
try
{
joinTransaction();
E tmp = getEntityManager().merge(getInstance());
setInstance(tmp);
getEntityManager().flush();
// updatedMessage();
// raiseAfterTransactionSuccessEvent();
}
catch (Exception ex)
{
log.error("error occured: ", ex);
}
return "updated";
}
public void joinTransaction() {
log.debug("joining transation if EntityManager is open and not joined");
if (getEntityManager().isOpen() && !getEntityManager().isJoinedToTransaction())
{
log.debug("joining transaction");
getEntityManager().joinTransaction();
}
}
If I call joinTransaction I can see in the log that getEntityManager().joinTransaction()
is called. But this gives me the exception:
javax.persistence.TransactionRequiredException: Explicitly joining a JTA transaction requires a JTA transaction be currently activ
If I comment the line jooinTransaction()
I'll get the following exception on the method call getEntityManager().flush()
:
javax.persistence.TransactionRequiredException: no transaction is in progress
So the problem is, that I would like to call flush
and only then the entity should be persisted in database.