如何让容器管理事务(CMT)与EJB3.1、Hibernate3.6、JPA2.0、JBoss和MySQL一起工作
我试图让CMT与JPA EntityManager和EJB一起工作,但出现了以下错误。(堆栈恍惚状态被截断): 我的班级: 访问会话Bean的Servlet:如何让容器管理事务(CMT)与EJB3.1、Hibernate3.6、JPA2.0、JBoss和MySQL一起工作,jpa,jboss,ejb,code-injection,entitymanager,Jpa,Jboss,Ejb,Code Injection,Entitymanager,我试图让CMT与JPA EntityManager和EJB一起工作,但出现了以下错误。(堆栈恍惚状态被截断): 我的班级: 访问会话Bean的Servlet: public class SearchActionExample extends Action { @EJB private static TestBeanServiceInterface testBean; public ActionForward execute(ActionMapping mapping,
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;
}
}
文件persistence.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>
<?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>
更新: “本地”界面工作正常(即不必是远程的) 我通过在Eclipse中的一个企业应用程序项目中部署来实现它。web.xml、ejb-jar.xml或application.xml中不需要引用bean EAR中部署到Jboss的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>
<?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>
接口类:
@Local
public interface SessionBeanLocal {
TestTiger addTestTiger(String testTigerName);
package com.myproject.beans;
import javax.ejb.Local;
import com.myproject.entities.Lion;
@Local
public interface SessionBeanLocal {
Lion addLion(String lionName);
}
最重要的改变是:在保存会话的类中,这个类是局部变量,容器(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;
}
@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>");
}
您需要注入远程接口,而不是Bean
public class SearchActionExample extends Action {
@EJB
private static TestBean2Remote testBean;
您需要注入远程接口,而不是Bean
public class SearchActionExample extends Action {
@EJB
private static TestBean2Remote testBean;
不要对静态字段进行注入,注入是实例成员,在创建对象时发生,而静态字段是类成员。这很可能是异常的原因
不要对静态字段进行注入,注入是实例成员,在创建对象时发生,而静态字段是类成员。这很可能是异常的原因。我已经得到了一个有效的解决方案: @本地接口工作正常(即不必是远程接口) web.xml、ejb-jar.xml、application.xml或任何jboss配置文件中都不需要引用bean 我是通过在Eclipse中的“企业应用程序项目”(EAP)中部署来实现的。此项目包含“部署程序集”,其中包含包含JPA实体类的.jar,以及另一个包含其他业务逻辑类的.jar。EAP有这两个项目,加上EJB项目和“动态Web项目”(创建一个.war),在其构建路径上总共有4个项目。Eclipse中的Jboss AS工具将EAP发布/部署到Jboss服务器。部署到Jboss的EAP中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>
<?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;
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 action servlet中,但可以是任何servlet),容器(JBoss AS)需要一个setter方法来创建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;
}
@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>");
}
@EJB()
私有会话bean本地bean;
public void setBean(sessionbeanlocalbean){
System.out.println(“容器(例如Jboss)调用了setBean setter)”;
this.bean=bean;
}
public exampleStrutsServletMethod(ActionMapping映射、ActionForm表单、HttpServletRequest请求、HttpServletResponse响应)引发异常{
PrintWriter out=response.getWriter();
Lion Lion=bean.addLion(“Simba”);//这将在持久化上下文中持久化Lion(并自动生成一个Id),容器将在它刷新到数据库时进行管理
out.print(“LION ID=“+LION.getLionId()+”);
}
文件persistence.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>
<?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>
org.hibernate.ejb.HibernatePersistence
java:/MySqlDS
mysql-dx.xml(在jboss server dir/server/default/deploy目录中):
MySqlDS
jdbc:mysql://localhost:3306/myProjectDatabase
com.mysql.jdbc.Driver
用户名
我的密码
org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
mySQL
注意:如果Eclipse JPA项目(即包含JPA 2.0实体类和persistence.xml的项目)的“Java persistence”项目属性面板中的“persistence class Management”设置为“自动发现带注释的类”,则不需要在persistence.xml中定义类(通过“注:关于“容器管理事务”(CMT)。Hibernate手册引用了它们,并指出需要将persistence.xml属性(如“Hibernate.transaction.factory_class”)设置为值:“org.Hibernate.transaction.CMTTransactionFactory”。如果使用JPA EntityManager而不是本机hibernate,则情况并非如此。我在persistence.xml中不需要任何这样的定制CMT属性。这就是Hibernate在两种实现方式(即SessionFactory和EntityManager)之间混淆的地方。请随时对我的解决方案的这一部分发表更多意见,因为我仍在绞尽脑汁!Will我已经获得了一个有效的解决方案: @本地接口工作正常(即不必是远程接口) web.xml、ejb-jar.xml、application.xml或任何jboss配置文件中都不需要引用bean 我是通过在Eclipse中的“企业应用程序项目”(EAP)中部署来实现的。此项目包含“部署程序集”,其中包含包含JPA实体类的.jar,以及另一个包含其他业务逻辑类的.jar。EAP有这两个项目,加上EJB项目和“动态Web项目”(创建一个.war),在其构建路径上总共有4个项目。Eclipse中的Jboss AS工具将EAP发布/部署到Jboss服务器。部署到Jboss的EAP中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>
<?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;
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 action servlet中,但可以是任何servlet),容器(JBoss AS)需要一个setter方法来创建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;
}
@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>");
}
@EJB()
私有会话bean本地bean;
public void setBean(sessionbeanlocalbean){
System.out.println(“setB