【问题标题】:WebSphere 8.5.5: No active transaction for PuIdWebSphere 8.5.5:PuId 没有活动事务
【发布时间】:2016-10-28 10:10:27
【问题描述】:

我正在开发一个在 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 服务模块中或在将数据库类和 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;
    }

    ...

}

来自网络服务的工作示例:

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

来自网络应用程序的问题示例:

@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 功能的抽象类。

抽象 DAO 基类:

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 应用程序中。 :-\

【问题讨论】:

  • 你能显示完整的异常堆栈跟踪吗?你能展示persist方法吗?
  • 您好 Brett,EJB 继承自一个抽象基类,该基类通过简单地在 EJB 的 EntityManager 实例上调用 .persist(...) 来实现 .persist(...) 方法。我在原始问题中添加了抽象基类和完整的堆栈跟踪。干杯,卡尔
  • 尝试在你的 bean 中覆盖 persist 方法并添加注解 @TransactionAttribute(value=REQUIRED)。检查它是否有任何区别。同样对于第二次测试,尝试将@Inject 更改为@EJB 为addressDao。
  • @Gas 据我所知@TransactionAttribute(value=REQUIRED) 是默认值。无论如何,我都尝试在类和方法级别指定它;可悲的是相同的结果(没有活动交易......)。还没有使用@EJB 而不是@Inject 或者/尚未使用它(请参阅问题更新)。干杯,卡尔
  • 啊哈,所以它只是无法以某种方式找到 bean。他们在 Web 服务中工作,因为您有 @Stateless 作为实现,所以它使用您编写时所需的默认事务。但看起来 CDI 正在注入 POJO 而不是 EJB,因此可能存在一些类路径/程序集问题。您的 ejb 是在单独的应用程序中还是只是 jar?也许那个 jar 不被识别为 ejb jar。因此,首先专注于使用@EJB 修复注入,然后您将确定您正在注入正确的 EJB。

标签: jpa java-ee-6 ear jta websphere-8


【解决方案1】:

正如@Gas 在 cmets 中提到的,事实证明这是类路径/EAR 设置的问题。

我能够通过以下方式使其与 @EJB 和 @Inject 一起工作:

  1. 将 DB 实用程序模块转换为 EJB 模块 (Project Facets)
  2. 在 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>
    
  3. 并在我的 WAR 清单中引用该模块

    MANIFEST.MF:

    Manifest-Version: 1.0
    Class-Path: de.holistic.hcms.data.jar
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 2017-09-25
    相关资源
    最近更新 更多