2017-11-29 49 views
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

답변

1

당신이 후크부터 존재 가정 기운을 ejb 호출 이후 EJBContext 외부에서 실행될 수 있으며 UT를 사용하면 EJB 컨테이너가 아닌 사용자의 책임하에 수행됩니다.

+0

웹 컨텍스트 A에서 트랜잭션을 시작한 다음 웹 컨텍스트 B에서 bean을 호출하면 어떻게됩니까? B의 트랜잭션 후크가 웹 컨텍스트 A에서 실행될 것이라고 기대합니까? 웹 컨텍스트 B에서 트랜잭션 후크를 다시 실행하는 방법이 있습니까? – wdk

+0

트랜잭션은 스레드에 바인딩되지만 JNDI 컨텍스트는 상황 별 컨텍스트입니다. EJB 외부에 커밋이 있으면 EJB 컨텍스트가 없습니다. –