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

时间:2015-08-26 12:08:53

标签: tomcat servlets transactions ejb tomee

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

1 个答案:

答案 0 :(得分:0)

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

感谢一位同事,我通过以下方式与TomEE合作:

结构是拥有两个Web应用程序和一个接口jar:

  1. APPA。公开一个呼叫无状态的RESTfull Web服务 会话bean(BeanA),它从AppB重用无状态会话bean。 这是作为WAR构建的。
  2. APPB。暴露无状态会话bean BeanB。这是作为WAR构建的。
  3. AppBItf。包含本地接口 BeanB。这是作为JAR构建的,它将在AppA之间共享 和AppB。
  4. AppA的内容

    在AppA中,我们有三件事:REST服务,bean及其本地接口。 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();
        }
    }
    

    BeanALocal.java

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

    AppB的内容

    这只包含bean(其本地接口在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的本地接口:

    BeanBLocal.java

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

    部署

    可以简单地将两个WAR(AppA.war和AppB.war)部署到webapps,但需要将JAR(AppBItf)添加到公共类加载器(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是相同的,因此BeanB的事务将由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开头,而第二笔以2开头。