0
TomEE에서 ejb가 트랜잭션 동기화 레지스트리에 동기화를 등록 할 때 beforeCompletion에 ejb 컨텍스트가 없습니다. bean javax.ejb.BeforeCompletion을 사용할 때 존재합니다. jee/ejb 스펙에 따라 예상되는 것은 무엇입니까? javax.transaction.Synchronization.beforeCompletion과 javax.ejb.BeforeCompletion의 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
웹 컨텍스트 A에서 트랜잭션을 시작한 다음 웹 컨텍스트 B에서 bean을 호출하면 어떻게됩니까? B의 트랜잭션 후크가 웹 컨텍스트 A에서 실행될 것이라고 기대합니까? 웹 컨텍스트 B에서 트랜잭션 후크를 다시 실행하는 방법이 있습니까? – wdk
트랜잭션은 스레드에 바인딩되지만 JNDI 컨텍스트는 상황 별 컨텍스트입니다. EJB 외부에 커밋이 있으면 EJB 컨텍스트가 없습니다. –