[
https://issues.apache.org/struts/browse/WW-1399?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_42823
]
ahardy66 edited comment on WW-1399 at 12/23/07 10:04 AM:
-----------------------------------------------------------
Simplified my previous entry
The following is a servlet filter written for the most stripped-down,
standards-compliant JPA implementation that I can currently reasonably put
together. It's probably too specific to my requirements to be any use, but here
it is anyway.
For transaction management by the Spring Framework, the Spring context config
sets up a transaction manager using
org.springframework.orm.jpa.JpaTransactionManager which takes the
EntityManagerFactory as a constructor parameter.
The DAOs can retrieve the same entity manager that Spring is given. (I don't
use the Spring DAO component.) Any call to
EntityManagerFactory.createEntityManager() from the same thread will retrieve
the same EntityManager - this is in the JPA spec. See section 5.2.
This is only for the extended persistence context paradigm - I haven't looked
at implementing it in container with JEE transactions.
public class OpenEntityManagerInViewFilter implements Filter
{
public final void doFilter(ServletRequest request,
ServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{
EntityManagerFactory entityManagerFactory =
ContextManager.getEntityManagerFactory();
EntityManager entityManager = ContextManager.getEntityManager();
try
{
filterChain.doFilter(request, response);
}
finally
{
ContextManager.closeEntityManager();
}
}
public void destroy()
{
}
public void init(FilterConfig newArg0) throws ServletException
{
}
}
public class ContextManager
{
private static ThreadLocal<EntityManager> entityManagerThreadLocal =
new ThreadLocal<EntityManager>();
public static EntityManager getEntityManager()
{
EntityManager entityManager = entityManagerThreadLocal.get();
if (entityManager == null)
{
EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("myPersistenceUnit",
getJpaParameters());
entityManager = entityManagerFactory.createEntityManager();
entityManagerThreadLocal.set(entityManager);
}
return entityManager;
}
public static void closeEntityManager()
{
EntityManager entityManager = entityManagerThreadLocal.get();
if (entityManager != null && entityManager.isOpen())
{
entityManager.close();
}
// dump reference to EntityManager
entityManagerThreadLocal.remove();
}
}
was (Author: ahardy66):
The following is a servlet filter written for the most stripped-down,
standards-compliant JPA implementation that I can currently reasonably put
together. It's probably too specific to my requirements to be any use, but here
it is anyway.
As you can see, it feeds an entity manager into the Spring Framework use in
transaction management, and it is managed by the org.permacode.ContextManager,
from which the DAOs can retrieve the same entity manager that Spring is given.
(I don't use the Spring DAO component.)
Fortunately part of the JPA spec says that the EntityManagerFactory must serve
up the same entity manager to any calls made by the same thread (5.2).
This is only for the extended persistence context paradigm - I haven't looked
at implementing it in container with JEE transactions.
package org.permacode.web;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.permacode.ContextManager;
import org.permacode.PermacodeException;
import org.springframework.orm.jpa.EntityManagerHolder;
import
org.springframework.transaction.support.TransactionSynchronizationManager;
public class OpenEntityManagerInViewFilter implements Filter
{
/**
* Binds the JPA EntityManager for the thread into the Spring Framework's
* (@link
*
org.springframework.transaction.support.TransactionSynchronizationManager)
* for use by the Spring Frameworks non-standardised Transaction
Management,
* using the EntityManagerFactory as the key.
*
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public final void doFilter(ServletRequest request,
ServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{
EntityManagerFactory entityManagerFactory =
ContextManager.getEntityManagerFactory();
try
{
EntityManager entityManager = ContextManager.getEntityManager();
TransactionSynchronizationManager.bindResource(
entityManagerFactory, new EntityManagerHolder(entityManager));
}
catch (PersistenceException ex)
{
throw new PermacodeException("Could not create JPA EntityManager",
ex);
}
try
{
filterChain.doFilter(request, response);
}
finally
{
TransactionSynchronizationManager
.unbindResource(entityManagerFactory);
ContextManager.closeEntityManager();
}
}
public void destroy()
{
}
public void init(FilterConfig newArg0) throws ServletException
{
}
}
In attempt to make this more useful, I thought I should include the relevant
ContextManager methods as pseudo-code (it was a bit more complex actually):
public static EntityManager getEntityManager()
{
EntityManager entityManager = threadLocalEntityManager.get();
if (entityManager == null)
{
entityManagerFactory =
Persistence.createEntityManagerFactory(persistenceUnitName,
getJpaParameters());
entityManager = getEntityManagerFactory().createEntityManager();
threadLocalEntityManager.set(entityManager);
}
return entityManager;
}
public static void closeEntityManager()
{
EntityManager entityManager = threadLocalEntityManager.get();
if (entityManager != null && entityManager.isOpen())
{
EntityTransaction dbTransaction = entityManager.getTransaction();
if (dbTransaction != null && dbTransaction.isActive())
{
logger.debug("rolling back transaction - "
+ "should be closed at this point normally");
dbTransaction.rollback();
}
logger.debug("closing entity manager");
entityManager.close();
}
else
{
logger.warn("EntityManager closed already.");
}
// dump reference to EntityManager
threadLocalEntityManager.remove();
}
> MailReader - Migrate to JPA and Derby
> -------------------------------------
>
> Key: WW-1399
> URL: https://issues.apache.org/struts/browse/WW-1399
> Project: Struts 2
> Issue Type: Improvement
> Components: Example Applications
> Reporter: Ted Husted
> Assignee: Ted Husted
> Priority: Minor
> Fix For: 2.1.x
>
>
> The in-memory XML database used by the MailReader is interesting, but a
> best-practices example that used the JPA and a SQL DBMS would be more
> instructive.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.