【问题标题】:EJB context in javax.transaction.Synchronization.beforeCompletion versus javax.ejb.BeforeCompletionjavax.transaction.Synchronization.beforeCompletion 与 javax.ejb.BeforeCompletion 中的 EJB 上下文
【发布时间】:2017-11-29 15:51:09
【问题描述】:

在 TomEE 中,当 ejb 在事务同步注册表中注册同步时,beforeCompletion 中没有 ejb 上下文。使用 bean javax.ejb.BeforeCompletion 时有。根据 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;
}

}

ps:我记录了 TomEE 的票,但没有收到回复:https://issues.apache.org/jira/browse/TOMEE-2135

【问题讨论】:

    标签: jakarta-ee ejb jta apache-tomee openejb


    【解决方案1】:

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

    【讨论】:

    • 如果我在 Web 上下文 A 中开始一个事务,然后在 Web 上下文 B 中调用一个 bean,该怎么办?我希望 B 的事务挂钩在 Web 上下文 A 中执行,对吗?有没有办法在 Web 上下文 B 中再次执行事务挂钩?
    • 事务绑定到线程,但 JNDI 上下文是上下文上下文。您的提交在 EJB 之外,您没有任何 EJB 上下文。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    相关资源
    最近更新 更多