Jakarta ee javax.transaction.Synchronization.beforeCompletion与javax.EJB.beforeCompletion中的EJB上下文

Jakarta ee javax.transaction.Synchronization.beforeCompletion与javax.EJB.beforeCompletion中的EJB上下文,jakarta-ee,ejb,jta,apache-tomee,openejb,Jakarta Ee,Ejb,Jta,Apache Tomee,Openejb,在TOME中,当ejb在事务同步注册表中注册同步时,在完成之前没有ejb上下文。当使用bean javax.ejb.before完成时,会出现以下情况。根据jee/ejb规范,应该期望什么 请参阅下面的代码测试用例testWithWrappedUserTransaction失败: import java.util.Properties; import java.util.concurrent.Callable; import javax.annotation.Resource; import

在TOME中,当ejb在事务同步注册表中注册同步时,在完成之前没有ejb上下文。当使用bean javax.ejb.before完成时,会出现以下情况。根据jee/ejb规范,应该期望什么

请参阅下面的代码测试用例testWithWrappedUserTransaction失败:

import java.util.Properties;
import java.util.concurrent.Callable;

import javax.annotation.Resource;
import javax.ejb.AfterBegin;
import javax.ejb.AfterCompletion;
import javax.ejb.BeforeCompletion;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.Stateful;
import javax.ejb.embeddable.EJBContainer;
import javax.enterprise.context.RequestScoped;
import javax.transaction.Synchronization;
import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.UserTransaction;

import org.apache.openejb.core.ThreadContext;

import junit.framework.TestCase;

public class TransactionTest extends TestCase
{
@Resource
private TransactionSynchronizationRegistry  registry;

@Resource
private UserTransaction transaction;
@EJB
private Caller transactionalCaller;

@EJB
private Caller transactionalCaller2;

@Override
protected void setUp() throws Exception {
    final Properties p = new Properties();
    p.put("movieDatabase", "new://Resource?type=DataSource");
    p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
    p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");

    EJBContainer.createEJBContainer(p).getContext().bind("inject", this);
}

private void doWork() throws Exception {
    registry.registerInterposedSynchronization(new SynchronizationImplementation());
}

class SynchronizationImplementation implements Synchronization
{
    @Override
    public void beforeCompletion() {
        System.out.println("XXX: beforeCommit");
        assertEJBContext();
    }

    @Override
    public void afterCompletion(int paramInt) {
        System.out.println("XXX: afterCommit");
        assertEJBContext();
    }
}

private static void assertEJBContext() {
    assertTrue(ThreadContext.getThreadContext() != null);
}

public void testWithWrappedUserTransaction() throws Exception {
    transaction.begin();
    try {
        transactionalCaller.call(() -> {
            doWork();
            return null;
        });
    } finally {
        transaction.commit();
    }
}

public void testWithDoubleBeanTransaction() throws Exception {
    transactionalCaller.call(() -> {
        doWork2();
        return null;
    });
}

private void doWork2() throws Exception {
    System.out.println("XXX: doWork2");
    transactionalCaller2.call(() -> {
        doWork();
        return null;
    });
}

public void testWithTransaction() throws Exception {
    transactionalCaller.call(() -> {
        doWork();
        return null;
    });
}

public static interface Caller
{
    public <V> V call(Callable<V> callable) throws Exception;
}
import java.util.Properties;
导入java.util.concurrent.Callable;
导入javax.annotation.Resource;
导入javax.ejb.AfterBegin;
导入javax.ejb.AfterCompletion;
在完成之前导入javax.ejb.com;
导入javax.ejb.ejb;
导入javax.ejb.EJBException;
导入javax.ejb.Stateful;
导入javax.ejb.embeddeble.EJBContainer;
导入javax.enterprise.context.RequestScope;
导入javax.transaction.Synchronization;
导入javax.transaction.TransactionSynchronizationRegistry;
导入javax.transaction.UserTransaction;
导入org.apache.openejb.core.ThreadContext;
导入junit.framework.TestCase;
公共类TransactionTest扩展了TestCase
{
@资源
私有事务同步注册表;
@资源
私人用户交易;
@EJB
私人来电者事务性来电者;
@EJB
私人呼叫者事务性呼叫者2;
@凌驾
受保护的void setUp()引发异常{
最终属性p=新属性();
p、 put(“电影数据库”new://Resource?type=DataSource");
p、 put(“movieDatabase.JdbcDriver”、“org.hsqldb.JdbcDriver”);
p、 put(“movieDatabase.JdbcUrl”,“jdbc:hsqldb:mem:moviedb”);
创建EJBContainer(p).getContext().bind(“注入”,this);
}
私有void doWork()引发异常{
registry.registerInterposedSynchronization(新的SynchronizationImplementation());
}
类同步实现实现同步
{
@凌驾
竣工前公共作废(){
System.out.println(“XXX:beforeCommit”);
assertEJBContext();
}
@凌驾
完成后公共无效(int参数){
System.out.println(“XXX:afterCommit”);
assertEJBContext();
}
}
私有静态void assertEJBContext(){
assertTrue(ThreadContext.getThreadContext()!=null);
}
public void testWithWrappedUserTransaction()引发异常{
transaction.begin();
试一试{
transactionalCaller.call(()->{
销钉();
返回null;
});
}最后{
commit();
}
}
public void testWithDoubleBeanTransaction()引发异常{
transactionalCaller.call(()->{
doWork2();
返回null;
});
}
私有void doWork2()引发异常{
System.out.println(“XXX:doWork2”);
transactionalCaller2.call(()->{
销钉();
返回null;
});
}
public void testWithTransaction()引发异常{
transactionalCaller.call(()->{
销钉();
返回null;
});
}
公共静态接口调用者
{
public V call(Callable Callable)抛出异常;
}
}


ps:我为TomEE记录了ticket,但没有得到响应:

您不能假设它存在,因为钩子是在ejb调用之后执行的,所以可能在EJBContext之外,使用UT,它由您负责,而不是由ejb容器负责。

如果我在web上下文a中启动一个事务,然后在web上下文B中调用一个bean,该怎么办?我希望B的事务挂钩是在web上下文A中执行的,对吗?有没有办法在web上下文B中再次执行事务挂钩?事务绑定到线程,但JNDI上下文是上下文挂钩。如果您的提交在EJB之外,那么您没有任何EJB上下文。