2011-02-14 2 views
3

RequestFactory에서 persist attached entities까지 얻으려면 각 요청마다 동일한 EntityManager을 사용해야합니다.GWT RequestFactory : 요청 당 단일 EntityManager 사용 방법

ThreadLocal 구현을 기반으로 내 공장 클래스를 함께 자갈링했지만 리소스를 적절하게 해제하는 방법 (예 : 요청이 완료되었음을 알 수있는 방법 및 close())에 대한 확신이 없습니다.

full-on J2EE/CDI를 사용하지 않고 주어진 ServletRequest에서 단일 EntityManager를 사용하는 간단한 방법이 있습니까? 필자가해야한다면 그 길을 택할 것이지만 GWT와 함께 제공되는 경량급 개발 서버를 계속 사용하고 싶기 때문에 일을 단순하게하기를 바라고 있습니다.

답변

6

여기는 GWT Google Group,BobV의 피드백을 기반으로 궁극적으로 생각해 냈습니다.

EntityManager에 대한 스레드 로컬 홀더를 만듭니다.

public class PersistenceFilter implements Filter 
{ 
    protected static final Logger log = Logger.getLogger(PersistenceFilter.class.getName()); 
    private EntityManagerFactory factory; 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException 
    { 
     factory = Persistence.createEntityManagerFactory("my_persistence"); 
    } 

    @Override 
    public void destroy() 
    { 
     factory.close(); 
    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
    { 
     EntityManager em = factory.createEntityManager(); 
     ThreadLocalEntityManager.set(em); 

     EntityTransaction tx = em.getTransaction(); 
     tx.begin(); 

     try 
     { 
      chain.doFilter(req, res); 
      tx.commit(); 
     } 
     catch (Exception e) 
     { 
      tx.rollback(); 
     } 
     finally 
     { 
      log.info("closing EntityManager: " + EMF.entityManager()); 
      em.close(); 
     } 

    } 
} 

가 그런 다음/gwtRequest의 URL에 필터를 적용

public class ThreadLocalEntityManager 
{ 
    private static ThreadLocal<EntityManager> holder = new ThreadLocal<EntityManager>(); 

    private ThreadLocalEntityManager() 
    { 
    } 

    public static EntityManager get() 
    { 
     return holder.get(); 
    } 

    public static void set(EntityManager em) 
    { 
     holder.set(em); 
    } 
} 

그런 다음 요청에 대한 초기 EntityManager를 설정합니다 필터를 만들 : 그들이 EntityManager를 얻을 필요로 할 때 당신의 기관이 참조 패턴 :

그것은 당신의 기본 대구에서 사용하든,이 서블릿을 통과 여기 - EntityManager에 각 요청에 대해 생성되는 결함이 있음을
<filter> 
    <filter-name>PersistenceFilter</filter-name> 
    <filter-class>com.example.PersistenceFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>PersistenceFilter</filter-name> 
    <url-pattern>/gwtRequest</url-pattern> 
</filter-mapping> 

주 e 또는 아닙니다. 아마도 더 강력해질 수 있으며, 요청이있을 때만 EntityManager (및 트랜잭션)를 지연 생성 할 수 있습니다.

그러나이 코드는 지금까지 RequestFactory과 잘 작동하는 것으로 보입니다. 개선을위한 제안은 매우 환영 받는다.

참고 :이 경험을 통해 나는 이와 같은 부분을 구현하려고 시도하지 않고 CDI 전체로 전환 할 가치가 있다고 가르쳐주었습니다. 나는이 프로젝트 동안 그러한 움직임에 사용할 시간이 없었다.

+0

이 필터를 통해 EntityManager가 필요하지 않은 요청이 많을 것으로 생각됩니다. 이것은 내가 한 일이며, 나 역시 잘 작동합니다! appengine에서 트랜잭션 비트는 작동하지 않지만 JDO에서 지속성 관리자를 열고 닫는 것만으로도 잘 작동합니다. –

4

DynaTableRf 샘플 응용 프로그램은 web.xml 파일에 지속성 컨텍스트를 설정하기 위해 서블릿 필터를 추가하여 유사한 작업을 수행합니다. 또는 이 반환 될 때 RequestFactoryServlet의 하위 클래스를 만들고 doPost() 메서드를 재정 의하여 finally 블록의 EntityManager을 분해 할 수 있습니다.

+0

Thanks (again), BobV. 나는 서블릿 필터 접근법을 시도하고있다. 요청 당 한 개의 EntityManager가 작동하며, 이는 확실히 내 RequestFactory 문제를 해결합니다. 하지만 지금은 자원이 새고 있습니다. 그것은 항상 무언가입니다. :-) 버그가 해결되면 다시 돌아와 요약 해 보겠습니다. –

2

Spring을 사용한다면 web.xml에 OpenEntityManagerInView 서블릿 필터 만 추가하면됩니다.

<filter> 
    <filter-name>entityManagerFilter</filter-name> 
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>entityManagerFilter</filter-name> 
    <url-pattern>/gwtRequest</url-pattern> 
</filter-mapping> 
관련 문제