WebSphere 8.5.5:PuId 没有活动事务
WebSphere 8.5.5: No active transaction for PuId
我正在 WebSphere 8.5.5 上开发 JaveEE6 Web 应用程序 运行。
为了访问数据库,我使用 CDI 将 @Stateless EJB 注入到我的支持 bean 中。查询数据库工作正常,但在尝试保留实体时抛出以下异常:
javax.persistence.TransactionRequiredException: No active transaction for PuId=...
应用程序打包在一个包含四个模块 (EAR setup) 的 EAR 中:
- 包含用于与数据库交互的 JPA 实体和 EJB 的实用程序模块
- 包含 Primefaces 5.2 的实用模块
- 使用 DB 实用程序模块的 JAX-RS Web 服务
- 一个使用 DB Utility Module 的 JSF web 应用程序
事务在 Web 服务模块中或将数据库 classes 和 Web 应用程序合并到一个模块中时工作正常(尽管我真的很想避免这种情况)。
我已经尝试应用类似问题的答案中提供的一些解决方案,但到目前为止还没有解决问题。非常感谢任何帮助。
谢谢,
卡尔
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
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">
<persistence-unit name="hcms" transaction-type="JTA">
<jta-data-source>jdbc/hcms</jta-data-source>
</persistence-unit>
</persistence>
EJB 示例片段:
@Stateless
public class CommunityAddressDao extends Dao<CommunityAddressEntity, Integer> {
@PersistenceContext(unitName="hcms")
private EntityManager em;
public CommunityAddressDao() {
super(CommunityAddressEntity.class);
}
@Override
protected EntityManager getEntityManager() {
return em;
}
...
}
来自 Web 服务的工作示例:
@Stateless
@Path("/addresses")
@Produces(MediaType.APPLICATION_JSON)
@RolesAllowed({"user"})
public class CommunityAddressService {
@Inject
private CommunityAddressDao addressDao;
...
@POST
@Consumes(MediaType.APPLICATION_JSON)
public CommunityAddressDto registerAddress(CommunityAddressDto address) throws DuplicateAddressException, ManagedAddressException, BadRequestException {
// Validation
CommunityAddressEntity entity = new CommunityAddressEntity();
entity.setCommunityUuid(address.getCommunityUuid());
...
addressDao.persist(entity);
return new CommunityAddressDto(entity);
}
}
来自 Web 应用程序的问题示例:
@ViewScoped
@Named("addressBean")
public class CommunityAddressBean implements Serializable {
private static final long serialVersionUID = -1685666287294618708L;
@Inject
private CommunityAddressDao addressDao;
private List<CommunityAddressEntity> addresses;
...
@PostConstruct
private void init() {
// Retrieve first 10 addresses - Works fine
addresses = addressDao.findAll(10, 0);
}
public void createAddress(ActionEvent event) {
CommunityAddressEntity entity = new CommunityAddressEntity();
entity.setCommunityUuid("some UUID");
...
// Throws javax.persistence.TransactionRequiredException: No active transaction for PuId=...
addressDao.persist(entity);
}
}
更新 (2016-11-02)
所有用于与数据库交互的 EJB 都继承自提供基本 CRUD 功能的抽象 class。
抽象 DAO 基础 class:
public abstract class Dao<E, K> {
protected Class<E> entityClass;
public Dao(Class<E> type) {
entityClass = type;
}
protected abstract EntityManager getEntityManager();
protected abstract String[] getFilterAttributes();
...
public void persist(E entity) {
getEntityManager().persist(entity);
}
public void merge(E entity) {
getEntityManager().merge(entity);
}
public void remove(E entity) {
getEntityManager().remove(entity);
}
public E findById(K id) {
return getEntityManager().find(entityClass, id);
}
}
完整堆栈跟踪:
[err] javax.persistence.TransactionRequiredException: No active transaction for PuId=hcms#de.holistic.hcms.admin.war#hcms
[err] at com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:230)
[err] at [internal classes]
[err] at de.holistic.hcms.data.Dao.persist(Dao.java:84)
[err] at de.holistic.hcms.admin.beans.CommunityAddressBean.createAddress(CommunityAddressBean.java:38)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)
[err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
[err] at java.lang.reflect.Method.invoke(Method.java:618)
[err] at org.apache.el.parser.AstValue.invoke(AstValue.java:268)
[err] at [internal classes]
[err] at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:78)
[err] at javax.faces.event.ActionEvent.processListener(ActionEvent.java:51)
[err] at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:404)
[err] at javax.faces.component.UICommand.broadcast(UICommand.java:103)
[err] at javax.faces.component.UIData.broadcast(UIData.java:772)
[err] at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:993)
[err] at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:276)
[err] at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1305)
[err] at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:731)
[err] at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:34)
[err] at [internal classes]
[err] at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
[err] at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1287)
[err] at [internal classes]
[err] at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:226)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at org.ocpsoft.rewrite.servlet.impl.HttpRewriteResultHandler.handleResult(HttpRewriteResultHandler.java:42)
[err] at org.ocpsoft.rewrite.servlet.RewriteFilter.rewrite(RewriteFilter.java:297)
[err] at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:198)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1156)
[err] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:626)
[err] at java.lang.Thread.run(Thread.java:804)
更新 2 (2016-11-02)
使用 @EJB
而不是 @Inject
会导致 com.ibm.ejs.container.EJBNotFoundException:
CWNEN0030E: The server was unable to obtain an object instance for the java:comp/env/de.holistic.hcms.admin.beans.CommunityAddressBean/addressDao reference. The exception message was: The EJB reference in the de.holistic.hcms.admin.war module of the hcms application could not be resolved; nested exception is: com.ibm.ejs.container.EJBNotFoundException: EJB with interface de.holistic.hcms.data.CommunityAddressDao not present in application hcms.
[ERROR ] An error occurred while executing [@PostConstruct.]
java.lang.NullPointerException
[ERROR ] Error Rendering View[/addresses.xhtml]
java.lang.NullPointerException
[ERROR ] An exception occurred
java.lang.NullPointerException
所以服务器正在错误的模块中查找 EJB。我尝试使用@EJB 注释的属性(查找、名称等)来正确指定我的 EJB,但到目前为止运气不佳。由于我对这个主题不是很熟悉,因此我将对此进行一些阅读。
不过,我想知道为什么 CDI + 事务在 Web 服务而不是 Web 应用程序中工作。 :-\
正如@Gas 在评论中提到的,事实证明这是类路径/EAR 设置的问题。
我能够通过以下方式让它与 @EJB
和 @Inject
一起工作:
- 将 DB 实用程序模块转换为 EJB 模块(Project Facets)
在 EAR 的 application.xml 文件中引用 EJB 模块 (EAR setup)
application.xml:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
<application-name>hcms</application-name>
<module id="Module_1473757101927">
<web>
<web-uri>de.holistic.hcms.web.service.war</web-uri>
<context-root>hcms</context-root>
</web>
</module>
<module id="Module_1476173932514">
<web>
<web-uri>de.holistic.hcms.admin.war</web-uri>
<context-root>hcms/admin</context-root>
</web>
</module>
<module id="Module_1478169092726">
<ejb>de.holistic.hcms.data.jar</ejb>
</module>
</application>
并在我的 WAR 清单中引用该模块
MANIFEST.MF:
Manifest-Version: 1.0
Class-Path: de.holistic.hcms.data.jar
我正在 WebSphere 8.5.5 上开发 JaveEE6 Web 应用程序 运行。 为了访问数据库,我使用 CDI 将 @Stateless EJB 注入到我的支持 bean 中。查询数据库工作正常,但在尝试保留实体时抛出以下异常:
javax.persistence.TransactionRequiredException: No active transaction for PuId=...
应用程序打包在一个包含四个模块 (EAR setup) 的 EAR 中:
- 包含用于与数据库交互的 JPA 实体和 EJB 的实用程序模块
- 包含 Primefaces 5.2 的实用模块
- 使用 DB 实用程序模块的 JAX-RS Web 服务
- 一个使用 DB Utility Module 的 JSF web 应用程序
事务在 Web 服务模块中或将数据库 classes 和 Web 应用程序合并到一个模块中时工作正常(尽管我真的很想避免这种情况)。
我已经尝试应用类似问题的答案中提供的一些解决方案,但到目前为止还没有解决问题。非常感谢任何帮助。
谢谢,
卡尔
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
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">
<persistence-unit name="hcms" transaction-type="JTA">
<jta-data-source>jdbc/hcms</jta-data-source>
</persistence-unit>
</persistence>
EJB 示例片段:
@Stateless
public class CommunityAddressDao extends Dao<CommunityAddressEntity, Integer> {
@PersistenceContext(unitName="hcms")
private EntityManager em;
public CommunityAddressDao() {
super(CommunityAddressEntity.class);
}
@Override
protected EntityManager getEntityManager() {
return em;
}
...
}
来自 Web 服务的工作示例:
@Stateless
@Path("/addresses")
@Produces(MediaType.APPLICATION_JSON)
@RolesAllowed({"user"})
public class CommunityAddressService {
@Inject
private CommunityAddressDao addressDao;
...
@POST
@Consumes(MediaType.APPLICATION_JSON)
public CommunityAddressDto registerAddress(CommunityAddressDto address) throws DuplicateAddressException, ManagedAddressException, BadRequestException {
// Validation
CommunityAddressEntity entity = new CommunityAddressEntity();
entity.setCommunityUuid(address.getCommunityUuid());
...
addressDao.persist(entity);
return new CommunityAddressDto(entity);
}
}
来自 Web 应用程序的问题示例:
@ViewScoped
@Named("addressBean")
public class CommunityAddressBean implements Serializable {
private static final long serialVersionUID = -1685666287294618708L;
@Inject
private CommunityAddressDao addressDao;
private List<CommunityAddressEntity> addresses;
...
@PostConstruct
private void init() {
// Retrieve first 10 addresses - Works fine
addresses = addressDao.findAll(10, 0);
}
public void createAddress(ActionEvent event) {
CommunityAddressEntity entity = new CommunityAddressEntity();
entity.setCommunityUuid("some UUID");
...
// Throws javax.persistence.TransactionRequiredException: No active transaction for PuId=...
addressDao.persist(entity);
}
}
更新 (2016-11-02)
所有用于与数据库交互的 EJB 都继承自提供基本 CRUD 功能的抽象 class。
抽象 DAO 基础 class:
public abstract class Dao<E, K> {
protected Class<E> entityClass;
public Dao(Class<E> type) {
entityClass = type;
}
protected abstract EntityManager getEntityManager();
protected abstract String[] getFilterAttributes();
...
public void persist(E entity) {
getEntityManager().persist(entity);
}
public void merge(E entity) {
getEntityManager().merge(entity);
}
public void remove(E entity) {
getEntityManager().remove(entity);
}
public E findById(K id) {
return getEntityManager().find(entityClass, id);
}
}
完整堆栈跟踪:
[err] javax.persistence.TransactionRequiredException: No active transaction for PuId=hcms#de.holistic.hcms.admin.war#hcms
[err] at com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:230)
[err] at [internal classes]
[err] at de.holistic.hcms.data.Dao.persist(Dao.java:84)
[err] at de.holistic.hcms.admin.beans.CommunityAddressBean.createAddress(CommunityAddressBean.java:38)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)
[err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
[err] at java.lang.reflect.Method.invoke(Method.java:618)
[err] at org.apache.el.parser.AstValue.invoke(AstValue.java:268)
[err] at [internal classes]
[err] at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:78)
[err] at javax.faces.event.ActionEvent.processListener(ActionEvent.java:51)
[err] at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:404)
[err] at javax.faces.component.UICommand.broadcast(UICommand.java:103)
[err] at javax.faces.component.UIData.broadcast(UIData.java:772)
[err] at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:993)
[err] at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:276)
[err] at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1305)
[err] at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:731)
[err] at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:34)
[err] at [internal classes]
[err] at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
[err] at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1287)
[err] at [internal classes]
[err] at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:226)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at org.ocpsoft.rewrite.servlet.impl.HttpRewriteResultHandler.handleResult(HttpRewriteResultHandler.java:42)
[err] at org.ocpsoft.rewrite.servlet.RewriteFilter.rewrite(RewriteFilter.java:297)
[err] at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:198)
[err] at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
[err] at [internal classes]
[err] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1156)
[err] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:626)
[err] at java.lang.Thread.run(Thread.java:804)
更新 2 (2016-11-02)
使用 @EJB
而不是 @Inject
会导致 com.ibm.ejs.container.EJBNotFoundException:
CWNEN0030E: The server was unable to obtain an object instance for the java:comp/env/de.holistic.hcms.admin.beans.CommunityAddressBean/addressDao reference. The exception message was: The EJB reference in the de.holistic.hcms.admin.war module of the hcms application could not be resolved; nested exception is: com.ibm.ejs.container.EJBNotFoundException: EJB with interface de.holistic.hcms.data.CommunityAddressDao not present in application hcms.
[ERROR ] An error occurred while executing [@PostConstruct.]
java.lang.NullPointerException
[ERROR ] Error Rendering View[/addresses.xhtml]
java.lang.NullPointerException
[ERROR ] An exception occurred
java.lang.NullPointerException
所以服务器正在错误的模块中查找 EJB。我尝试使用@EJB 注释的属性(查找、名称等)来正确指定我的 EJB,但到目前为止运气不佳。由于我对这个主题不是很熟悉,因此我将对此进行一些阅读。
不过,我想知道为什么 CDI + 事务在 Web 服务而不是 Web 应用程序中工作。 :-\
正如@Gas 在评论中提到的,事实证明这是类路径/EAR 设置的问题。
我能够通过以下方式让它与 @EJB
和 @Inject
一起工作:
- 将 DB 实用程序模块转换为 EJB 模块(Project Facets)
在 EAR 的 application.xml 文件中引用 EJB 模块 (EAR setup)
application.xml:
<?xml version="1.0" encoding="UTF-8"?> <application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6"> <application-name>hcms</application-name> <module id="Module_1473757101927"> <web> <web-uri>de.holistic.hcms.web.service.war</web-uri> <context-root>hcms</context-root> </web> </module> <module id="Module_1476173932514"> <web> <web-uri>de.holistic.hcms.admin.war</web-uri> <context-root>hcms/admin</context-root> </web> </module> <module id="Module_1478169092726"> <ejb>de.holistic.hcms.data.jar</ejb> </module> </application>
并在我的 WAR 清单中引用该模块
MANIFEST.MF:
Manifest-Version: 1.0 Class-Path: de.holistic.hcms.data.jar