2011-03-22 66 views
1

我試圖讓CMT與JPA EntityManagers和EJB一起工作,但提出了下面的錯誤。 (堆棧恍惚截斷):如何獲得使用EJB 3.1,Hibernate 3.6,JPA 2.0,JBoss和MySQL的容器管理事務(CMT)

Caused by: java.lang.RuntimeException: **Could not resolve @EJB reference: [EJB Reference: beanInterface 'com.mydomain.beans.TestBean2', beanName 'testBean2', mappedName 'null', lookupName 'null',** owning unit '[email protected]{vfs:///Users/willtardy/Documents/workspace/.metadata/.plugins/org.jboss.ide.eclipse.as.core/JBoss_6.0_Runtime_Server1300532851414/deploy/mydomainWeb.war}'] 
for environment entry: env/com.mydomain.action.SearchAction/testBean in unit [email protected]{vfs:///Users/willtardy/Documents/workspace/.metadata/.plugins/org.jboss.ide.eclipse.as.core/JBoss_6.0_Runtime_Server1300532851414/deploy/mydomainWeb.war} 

我的課:

的Servlet訪問該會話Bean:

public class SearchActionExample extends Action { 
    @EJB 
    private static TestBeanServiceInterface testBean; 

    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 
     testBean.addSource("TEST SOURCE NAME", 88, 99); 
     Service service = testBean.findService("HBA", "MEL"); 

     return mapping.findForward("success"); 
    } 
} 

遠程接口:

@Remote 
public interface TestBeanServiceInterface { 
    // Source is my own custom entity 
    void addSource(String sourceName, int newthreadsleeptime, int maxactivehttpclients); 

    // Service is my own Custom entity  
    Service findService(String departureAirportCode, String arrivalAirportCode); 
} 

Stateless Session Bean的定義:

@Stateless 
public class TestBeanService implements TestBeanServiceInterface { 

    @PersistenceContext(unitName="mydomainJPA") 
    private EntityManager em; 

    public void addSource(String sourceName, int newthreadsleeptime, int maxactivehttpclients) { 
     Source source = new Source(); 
     source.setName(sourceName); 
     source.setNewThreadSleepTime(newthreadsleeptime); 
     source.setMaxActiveHttpClients(maxactivehttpclients); 
     em.persist(source); 
    } 
    public Service findService(String departureAirportCode, String arrivalAirportCode) { 
     String queryString = "from Service where departureairportcode = '" + departureAirportCode + "' and arrivalairportcode = '" + arrivalAirportCode + "'"; 
     Service service = (Service)em.createQuery(queryString).getSingleResult(); 
     return service; 
    } 
} 

文件persistnce.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> 
<persistence-unit name="mydomainJPA" transaction-type="JTA"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <jta-data-source>java:/MySqlDS</jta-data-source> 
    <class>com.mydomain.entities.Service</class> 
<class>com.mydomain.entities.Source</class> 
    <properties> 
     <property name="hibernate.query.factory_class" value="org.hibernate.hql.classic.ClassicQueryTranslatorFactory"/> 
     <property name="hibernate.archive.autodetection" value="class"/> 
     <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/> 
     <property name="hibernate.current_session_context_class" value="jta"/> 
    </properties> 
</persistence-unit> 

當它說: 「無法解析引用」,在這裏我還可以定義豆? EJB3不需要ejb-jar.xml。有沒有其他的配置文件,我錯過了?


UPDATE:

  • 我已經更新了代碼段的上方,使得該bean作爲接口類型創建代替,如下面的答案。

  • 是否需要在web.xml中定義或映射EJB?

  • 假設一個參考在web.xml需要,我加一個EJB裁判的web.xml(見下文),但現在我收到一個新的錯誤(見下文)

線加到web.xml中:現在正在接收

<ejb-ref> 
    <ejb-ref-name>ejb/TestBeanEJBname</ejb-ref-name> 
    <ejb-ref-type>Session</ejb-ref-type> 
    <home>com.mydomain.action.TestBeanService</home> 
    <remote>com.mydomain.action.TestBeanServiceInterface</remote> 
</ejb-ref> 

新的錯誤消息:

12:11:00,980 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] Error installing to PostClassLoader: name=vfs:///Users/willtardy/Documents/workspace/.metadata/.plugins/org.jboss.ide.eclipse.as.core/JBoss_6.0_Runtime_Server1300532851414/deploy/purejetWeb.war state=ClassLoader mode=Manual requiredState=PostClassLoader: org.jboss.deployers.spi.DeploymentException: java.lang.IllegalStateException: Failed to find ContainerDependencyMetaData for interface: au.com.purejet.action.TestBeanServiceInterface 

Caused by: java.lang.IllegalStateException: Failed to find ContainerDependencyMetaData for interface: com.mydomain.action.TestBeanServiceInterface 
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.resolveEjbInterface(MappedReferenceMetaDataResolverDeployer.java:1255) [:6.0.0.Final] 
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.resolveEjbRefs(MappedReferenceMetaDataResolverDeployer.java:1099) [:6.0.0.Final] 
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.resolve(MappedReferenceMetaDataResolverDeployer.java:807) [:6.0.0.Final] 
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.internalDeploy(MappedReferenceMetaDataResolverDeployer.java:181) [:6.0.0.Final] 
... 39 more 

更新:

「本地」 接口只是罰款(即並不一定是遠程的)

我通過在Eclipse中的企業應用程序項目中進行部署來實現它。在web.xml,ejb-jar.xml或application.xml中不需要引用bean。

應用程序的內容。EAR中的XML部署到JBoss:

<?xml version="1.0" encoding="UTF-8"?> 
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6"> 
<display-name>myprojects</display-name> 
<module> 
<web> 
<web-uri>myproject.war</web-uri> 
<context-root>myproject</context-root> 
</web> 
</module> 
<module> 
<ejb>myprojectsEJB.jar</ejb> 
</module> 
</application> 

的SessionBean類:

@Stateless 
@Local(SessionBeanLocal.class) 

public class SessionBean implements SessionBeanLocal { 

@PersistenceContext(unitName="JPAtestProjectPersistenceUnit") 
private EntityManager em; 

接口類:持有該會話的類中:

@Local 
public interface SessionBeanLocal { 

TestTiger addTestTiger(String testTigerName); 

該得到的東西的工作最重要的變化是本地變量,容器(JBoss AS)需要一個設置來創建bean:

@EJB() 
private TestBean3Local beanVariable; 

public void setBeanVariable(TestBean3Local beanVariable) { 
    System.out.println("=====\n\nSET BEAN VARIABE SETTER WAS CALLED. (BY CONTAINER?) \n\n======="); 
    this.beanVariable = beanVariable; 
} 

回答

0

我得到了一個工作的解決方案:

@Local接口只是罰款(即不必是遠程)

豆類沒有引用的web.xml,EJB-JAR中必需的。 xml,application.xml或任何jboss配置文件。

我通過在Eclipse中的「企業應用程序項目」(EAP)中進行部署來實現它。該項目包含「部署程序集」,其中包含包含JPA實體類的.jar以及包含其他業務邏輯類的另一個.jar。 EAP擁有這兩個項目,加入EJB項目和「動態Web項目」(創建.war),共有4個項目在其構建路徑上。 Eclipse中的Jboss AS工具將EAP發佈/部署到Jboss服務器。內EAP application.xml中的內容被部署到JBoss:

<?xml version="1.0" encoding="UTF-8"?> 
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6"> 
    <display-name>myprojects</display-name> 
    <module> 
     <web> 
      <web-uri>myproject.war</web-uri> 
      <context-root>myproject</context-root> 
     </web> 
    </module> 
    <module> 
     <ejb>myprojectsEJB.jar</ejb> 
    </module> 
</application> 

本地接口類:

package com.myproject.beans; 
import javax.ejb.Local; 

import com.myproject.entities.Lion; 

@Local 
public interface SessionBeanLocal { 
Lion addLion(String lionName); 
} 

的SessionBean類:

package com.myproject.beans; 

import javax.ejb.Local; 
import javax.ejb.Stateless; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 

import com.myproject.Lion; 

@Stateless 
@Local(SessionBeanLocal.class) 
public class SessionBean implements SessionBeanLocal { 

@PersistenceContext(unitName="PersistenceUnitNameInPersistenceXML") 
private EntityManager em; 

public Lion addLion(String lionName) { 
    Lion lion = new Lion(lionName); 
    em.persist(lion); 
} 

該得到的東西的工作最重要的變化:內部持有會話的類是可變的(例如,在Struts動作servlet中,但可以是任何servlet),容器(JBoss AS)需要setter方法來創建bean:

@EJB() 
private SessionBeanLocal bean; 

public void setBean(SessionBeanLocal bean) { 
    System.out.println("setBean setter was called by container (e.g. Jboss)"); 
    this.bean = bean; 
} 

public exampleStrutsServletMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 
    PrintWriter out = response.getWriter(); 

    Lion lion = bean.addLion("Simba"); // this will persist the Lion within the persistence-context (and auto-generate an Id), and the container will manage when it's flushed to the database 

    out.print("<html>LION ID = " + lion.getLionId() + "<html>"); 
} 

文件persistnce.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> 
<persistence-unit name="PersistenceUnitNameInPersistenceXML" transaction-type="JTA"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <jta-data-source>java:/MySqlDS</jta-data-source> 
    <properties> 
    </properties> 
</persistence-unit> 

的mysql-dx.xml(在目錄中的JBoss服務器-DIR /服務器/ default/deploy目錄):

<?xml version="1.0" encoding="UTF-8"?> 
<datasources> 
    <local-tx-datasource> 
     <jndi-name>MySqlDS</jndi-name> 
     <connection-url>jdbc:mysql://localhost:3306/myProjectDatabase</connection-url> 
     <driver-class>com.mysql.jdbc.Driver</driver-class> 
     <user-name>username</user-name> 
     <password>mypassword</password> 
     <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> 
     <metadata> 
      <type-mapping>mySQL</type-mapping> 
     </metadata> 
    </local-tx-datasource> 
</datasources> 

注意:類不需要在持久性中定義。如果在JPA項目的「Java持久性」項目屬性面板中將「持久性類管理」設置爲「自動發現註釋類」(即,容器的JPA 2.0實體類和持久性的項目),則通過「< class>」 .XML)

注意:此解決方案是基於:EJB3.1時,Eclipse太陽神SR2,休眠3.6,JPA 2.0時,JBoss 6中,MySQL 5.5.10

注:關於 「容器管理事務」(CMT )。 Hibernate手冊引用了它們,並指出您需要將persistence.xml屬性(如「hibernate.transaction.factory_class」)設置爲「org.hibernate.transaction.CMTTransactionFactory」的值。如果您使用JPA EntityManager而不是本地休眠,則不是這種情況。我沒有在persistence.xml中需要任何這樣的自定義CMT屬性。這就是Hibernate在實現它的兩種方式(即SessionFactory vs EntityManager)之間混淆的地方。請隨時對我的解決方案的這一部分發表更多評論,因爲我仍然只是圍繞它進行包裝!將

1

你需要注入遠程接口,而不是豆

public class SearchActionExample extends Action { 
    @EJB 
    private static TestBean2Remote testBean; 
+0

謝謝你的答案,但不幸的是它沒有解決問題。我仍然收到錯誤「java.lang.RuntimeException:無法解析@EJB引用:[EJB引用:beanInterface'com.mydomain.action.TestBeanServiceInterface',beanName'null',mappedName'null',lookupName'null',擁有單元'Abstract' – willtardy 2011-03-23 00:49:27

+0

我需要在web.xml中定義EJB嗎? – willtardy 2011-03-23 00:53:34

+0

取決於你如何打包整個節目?如果.war和ejb-jar在一個.ear中,一切都應該沒問題。如果ejbs在一個不同的部署中,您可能需要在應用程序的名稱前加上,並將其添加到@EJB註釋中。 – 2011-03-23 08:47:45

0
public class SearchActionExample extends Action { 
    @EJB 
    private static TestBeanServiceInterface testBean; 

不要做注射到靜態字段,注射是實例成員和對象被創建的時候發生,而靜態字段是成員。這很可能是例外的原因。

+0

斑點! :)但它一直在工作,沒有拋出異常。如果它通過例外來解決,那對我原來的問題是一個不相關的問題。 – willtardy 2011-03-29 05:14:48

+0

@willtardy,這是一個常識,注射不能是靜態的,並且如果宣佈轉動必須有g/s。即使它適用於靜態,它應該被改變,你永遠不會知道它將來會有什麼後果。坦率地說,我不太瞭解你的問題的地位。如果你已經解決了,那麼請發佈你自己的答案,當他們遇到類似或相同的問題時,它會幫助其他人。 – Osw 2011-03-29 10:01:56

+0

你是對的,擁有「靜態」是錯誤的,事實上它並不適用於靜態,這是一個錯字。我已經發布了一個答案 - 請檢查它以確保它有意義且準確!歡呼聲,請問 – willtardy 2011-03-30 01:39:04