2011-10-20 50 views
0

我的項目是一個用seam-gen生成的WAR項目。它包含了這樣的的RESTEasy Web服務類(簡化,僅相關部分):什麼是從RESTEasy服務正確使用EntityManager? (SEAM,JBoss)

@Scope(ScopeType.APPLICATION) 
public abstract class RestService { 

    @In 
    protected EntityManager entityManager; 

    @GET 
    @POST 
    @Produces("application/json") 
    public Object proxy() { 
     // invokes various subclass methods 
     // based on request parameters 
     // and returns the result 
    } 
    // further method and logic 
} 

和:

@Path("/my") 
@Name("myRestService") 
public class MyRestService extends RestService { 

    public Object login(/*...*/) { 
     User user = getUser(email); 

     // ... 

     Token token = user.getToken(); 
     if (token != null) { 
      entityManager.remove(token); 
     } 
     token = new Token(); 
     entityManager.persist(token); 
     user.setToken(token); 
     user.setLastlogin(new Date()); 
     entityManager.persist(user); 

     // ... 
    } 

    private User getUser(String email) { 
     try { 
      return (User) entityManager 
        .createQuery("FROM User WHERE UPPER(email) = UPPER(:email)") 
        .setParameter("email", email) 
        .getSingleResult(); 
     } catch (NoResultException e) { 
      return null; 
     } 
    } 
} 

如果我通過Web瀏覽器調用登錄方法,找到正確的用戶(基於get參數),爲它實例化一個Token(我可以在Hibernate的STDOUT中看到詢問數據庫的下一個序列),但persist()方法不會將Token保存到數據庫,用戶對象(令牌標識,上次登錄日期)。

我用Google搜索這個現在兩天了,這裏就是我能想出:

  • 我的項目使用Seam管理的事務(components.xml中):

    <persistence:managed-persistence-context name="entityManager" auto-create="true" 
            persistence-unit-jndi-name="java:/MyEntityManagerFactory"/> 
    
  • 我的項目用途JTA進行交易處理(persistence.xml):

    <persistence-unit name="MyProject" transaction-type="JTA"> 
        <provider>org.hibernate.ejb.HibernatePersistence</provider> ... 
    
  • the En tityManager.persist()不更改提交到數據庫,只需排隊改變目前的交易(?)

  • 的Seam管理的事務默認

我試圖用綁對話。 flush(),拋出一個異常,說沒有正在進行的事務。

我試圖使用.joinTransaction()和.getTransaction()。begin(),拋出另一個異常,說JTA EntityManager不能訪問事務。

也嘗試在類上使用不同的作用域類型,或在我的login()方法上使用@Transactional註釋,但沒有運氣。

還試圖用@PersistenceContext註釋注入EntityManager,這導致了一個異常,說@PersistenceContext只能用於會話bean。

也試圖將我的課程標記爲@Stateless,導致我無法訪問我的服務(404)。

我應該如何使用EntityManager將我的實體保留在RESTEasy服務中?

系統規格:

  • 的JBoss 5.1.0 GA
  • SEAM 2.2.1最終
  • 的Postgres 8.3

請注意,我完全新的,缺乏經驗的JavaEE帶/ JBoss的/ SEAM。

任何評論將是有用的!謝謝。

回答

0

事務註釋對登錄方法很重要。這將確保事務攔截器在必要時創建事務。 (如果還沒有交易)。查找攔截器是否應用的最簡單方法是調試登錄方法並檢查堆棧。我不確定課程是如何召集的,但我會盡快更新這篇文章,以便我在工作中檢查它。 如果這個攔截器不在那裏,這意味着你沒有使用seam事務。你的components.xml文件中沒有顯示你這樣做。

馬丁

更新時間: 所以這裏的堆棧跟蹤。看看TransactionInterceptor,如果你的堆棧中沒有這個,你就沒有事務管理。

Daemon Thread [http-18081-1] (Suspended (breakpoint at line 170 in QueryHome)) 
    QueryHome.getCandidatesCount() line: 170  
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    Reflections.invoke(Method, Object, Object...) line: 22 
    RootInvocationContext.proceed() line: 32  
    SeamInvocationContext.proceed() line: 56  
    RollbackInterceptor.aroundInvoke(InvocationContext) line: 28  
    SeamInvocationContext.proceed() line: 68  
    BijectionInterceptor.aroundInvoke(InvocationContext) line: 77 
    SeamInvocationContext.proceed() line: 68  
    ConversationInterceptor.aroundInvoke(InvocationContext) line: 65  
    SeamInvocationContext.proceed() line: 68  
    TransactionInterceptor$1.work() line: 97  
    TransactionInterceptor$1(Work<T>).workInTransaction() line: 61 
    TransactionInterceptor.aroundInvoke(InvocationContext) line: 91 
    SeamInvocationContext.proceed() line: 68  
    MethodContextInterceptor.aroundInvoke(InvocationContext) line: 44 
    SeamInvocationContext.proceed() line: 68  
    JavaBeanInterceptor(RootInterceptor).invoke(InvocationContext, EventType) line: 107 
    JavaBeanInterceptor.interceptInvocation(Method, Object[]) line: 185 
    JavaBeanInterceptor.invoke(Object, Method, Method, Object[]) line: 103 
+0

我剛剛意識到你寫的是使用Seam 2.另一方面,你使用的是CDI的@Produces?我不確定這兩種技術是否兼容?大概有人可以提供一個提示? –

+0

@Transactional是解決方案,但我需要把它放在代理方法上,而不是在login()上。謝謝! – Istvan

1

您卸下一個管理域:

entityManager.remove(token); 

創建一個新問題:

token = new Token(); 

但在這裏:

entityManager.persist(token); 

令牌與用戶的關係(我不這種關係是什麼 - oneToMany,oneToOne,你是從用戶級聯,抓取等),但只是調用堅持toke ñ不會重新建立這種關係。 看一看 http://www.objectdb.com/java/jpa/persistence/crud

相關問題