tomcat - 如何在 TomEE 中的同一事务中执行子请求?

标签 tomcat servlets transactions ejb apache-tomee

在 TomEE 中(最好使用容器管理的事务)我想做一个子请求并在我当前的请求中使用它的输出,但两者必须是同一事务的一部分。欢迎所有(甚至是疯狂的想法,但最好只使用标准 API 而不是 TomEE 特定的)如何做到这一点。

最佳答案

这个 stackoverflow 问题提供了一个提示来回答我的问题:Acessing Remote/Local Session Beans

感谢一位同事,我通过以下方式将其与 TomEE 一起使用:

结构是有两个 web 应用程序和一个接口(interface) jar:

  1. AppA。公开调用无状态的 RESTfull Web 服务 重用来自 AppB 的无状态 session bean 的 session bean (BeanA)。 这是作为 WAR 构建的。
  2. 应用程序 B。公开无状态 session bean BeanB。这是作为 WAR 构建的。
  3. AppBItf.包含本地接口(interface) BeanB的。这是构建为 JAR,将在 AppA 之间共享 和 AppB。

AppA 的内容

在 AppA 中,我们拥有三样东西:REST 服务、bean 及其本地接口(interface)。 RestService.java

import javax.ejb.EJB;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;


@Path("/RestService/")
public class RestService
{
    @EJB
    BeanALocal bean;

    @GET
    @Path("/doInTransaction")
    public Response doInTransaction() {
        return Response.ok().entity("Transaction result: " + bean.doInTransaction()).build();
    }
}

BeanA.java

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.transaction.TransactionSynchronizationRegistry;
import BeanBLocal;

@Stateless
@LocalBean
public class BeanA implements BeanALocal
{
    @EJB
    BeanBLocal beanB;
    @Resource
    TransactionSynchronizationRegistry txReg;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public String doInTransaction() {
        return "Transaction: " + txReg.getTransactionKey() + "; BeanB: " + beanB.doInTransaction();
    }
}

BeanALLocal.java

import javax.ejb.Local;
@Local
public interface BeanALocal {
    String doInTransaction();
}

AppB的内容

这仅包含 bean(其本地接口(interface)在 AppBItf 中定义):

BeanB.java

import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.transaction.TransactionSynchronizationRegistry;

@Stateless
@LocalBean
public class BeanB implements BeanBLocal
{
    @Resource
    TransactionSynchronizationRegistry txReg;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public String doInTransaction() {
        return "BeanB: Transaction: " + txReg.getTransactionKey();
    }
}

AppBItf 的内容

这只包含 BeanB 的本地接口(interface):

BeanBLocal.java

import javax.ejb.Local;

@Local
public interface BeanBLocal {
    String doInTransaction();
}

部署

这两个WAR(AppA.war和AppB.war)可以简单地部署到webapps,但是JAR(AppBItf)需要添加到公共(public)类加载器(common.loader)。

结果

在上面的代码中,BeanB 被注解为 TransactionAttributeType.REQUIRED。调用 REST 服务(即在 http://localhost:8080/AppA/RestService/doInTransaction 上执行 GET)会导致以下输出:

 [Xid:globalId=1000000047544d4944,length=64,branchId=0,length=64];
 [Xid:globalId=1000000047544d4944,length=64,branchId=0,length=64]

注意第一个和第二个事务ID是一样的,所以BeanA的事务被BeanB复用了。这就是我所需要的。

当我将注释更改为 TransactionAttributeType.REQUIRES_NEW 时,容器会自动为 BeanB 启动一个新事务:

[Xid:globalId=1000000047544d4944,length=64,branchId=0,length=64];
[Xid:globalId=2000000047544d4944,length=64,branchId=0,length=64]

第一笔交易ID以1开头,第二笔交易ID以2开头。

关于tomcat - 如何在 TomEE 中的同一事务中执行子请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32226242/

相关文章:

java - Servlet 映射 url 模式

java - 根据servlet中当前位置获取附近的纬度和经度

java - Blender 3D 渲染 Java servlet 接口(interface)

java - JPA:读取并坚持一个事务,同时阻塞不同线程中的读取

java - 如何使用 Tomcat 8.0 从 WSDL 生成 Java 客户端? WSDL 文件有多个 xsd 导入

java - 部署期间的 Hibernate 异常

数据库 |服务提供商 | CURSOR - 获取游标到变量返回 null

java - 将 HIbernate 与 Spring 的 @Transactional Annotation 结合使用,数据不会持续存在

Maven tomcat 部署失败(连接由对等方重置)

java - Request.getattribute 在一个 Servlet 中工作,同时在其他 Servlet 中抛出空指针