我试图让CMT使用JPA EntityManagers和EJB,但是我想出了下面的错误。 (堆栈恍惚截断):
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;
}
}
文件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>
当它说“无法解析引用”时,我还能在哪里定义bean? EJB3不需要ejb-jar.xml。是否有一些我缺少的其他配置文件?
更新
我已经更新了上面的代码段,以便根据以下答案创建bean作为接口类型。
是否需要在web.xml中定义或映射EJB?
假设web.xml中需要引用,我在web.xml中添加了一个EJB引用(见下文),但现在我收到一个新错误(见下文)
< / LI>添加到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。
部署到Jboss的EAR中的application.xml的内容:
<?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 :(得分:1)
您需要注入远程接口而不是Bean
public class SearchActionExample extends Action {
@EJB
private static TestBean2Remote testBean;
答案 1 :(得分:0)
public class SearchActionExample extends Action {
@EJB
private static TestBeanServiceInterface testBean;
不要在静态字段中进行注入,注入是实例成员,并且在创建对象时发生,而静态字段是类成员。这很可能是异常的原因。
答案 2 :(得分: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);
}
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方法来创建豆:
@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-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>
注意:如果“持久性类管理”在“Java持久性”项目属性面板中设置为“自动发现带注释的类”,则不需要在persistence.xml中定义类(通过“&lt; class&gt;”) Eclipse JPA项目(即容纳JPA 2.0 Entity类和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而不是本机hibernate,则情况并非如此。我在persistence.xml中没有要求任何这样的自定义CMT属性。这是Hibernate在实现它的两种方式之间变得混乱的地方(即SessionFactory vs EntityManager)。请随时对我解决方案的这一部分发表更多评论,因为我仍然只是围绕着它!将