1

我试图让 CMT 与 JPA EntityManagers 和 EJBs 一起工作,但出现了以下错误。(堆栈恍惚被截断):

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 'AbstractVFSDeploymentContext@2008455195{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 AbstractVFSDeploymentContext@2008455195{vfs:///Users/willtardy/Documents/workspace/.metadata/.plugins/org.jboss.ide.eclipse.as.core/JBoss_6.0_Runtime_Server1300532851414/deploy/mydomainWeb.war}

我的课程:

访问会话 Bean 的 Servlet:

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);
}

无状态会话 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;
    }
}

文件持久化.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>

当它说“无法解析引用”时,我还能在哪里定义 bean?EJB3 不需要 ejb-jar.xml。我还缺少其他一些配置文件吗?


更新:

  • 根据下面的答案,我已经更新了上面的代码段,以便将 bean 创建为接口类型。

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

  • 假设 web.xml 中需要引用,我已向 web.xml 添加了一个 EJB 引用(见下文),但现在我收到一个新错误(见下文)

添加到 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 中的 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>

会话Bean类:

@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;
}
4

3 回答 3

1

您需要注入远程接口而不是 Bean

public class SearchActionExample extends Action {
    @EJB
    private static TestBean2Remote testBean;
于 2011-03-22T08:02:36.297 回答
0
public class SearchActionExample extends Action {
    @EJB
    private static TestBeanServiceInterface testBean;

不要对静态字段进行注入,注入是实例成员并在创建对象时发生,而静态字段是成员。这很可能是异常的原因。

于 2011-03-29T04:20:45.780 回答
0

我已经获得了一个可行的解决方案:

@Local 接口工作得很好(即不必是远程的)

在 web.xml、ejb-jar.xml、application.xml 或任何 jboss 配置文件中不需要对 bean 的引用。

我通过在 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);
}

会话Bean类:

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>");
}

文件持久化.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-server-dir/server/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>

注意:如果 Eclipse JPA 项目(即包含您的 JPA 2.0 实体类和 persistence.xml 的项目)

注意:此解决方案基于:EJB3.1、Eclipse Helios SR2、Hibernate 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 与 EntityManager)之间令人困惑的地方。请随时对我的解决方案的这一部分发表更多评论,因为我仍然只是在思考它!将要

于 2011-03-30T01:25:56.407 回答