2013-05-28 2 views
6

로그인 메소드 중에 통계를 비동기 적으로 저장하여 로그인 시간을 절약하려고합니다. 하지만 어떻게 든 비동기 메서드에 thread.sleep을 추가하면 로그인 프로세스가 더 오래 걸립니다. 왜 그런가요? 나는 authenticate 메소드가 writeResultToStats 메소드가 끝날 때까지 기다리지 않을 것이라고 생각했다.호출 방법 EJB의 비동기

@Stateless 
    @LocalBean 
    @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) 
    @TransactionManagement(TransactionManagementType.CONTAINER) 
    public class CustomerBeanTest { 

     @PersistenceContext(unitName = WebPersistenceUnits.QISADS) 
     private EntityManager em_local; 

     @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
     public void authenticate(Long loginid, String cmppassword) { 
      try { 
       Login l = em_local.find(Login.class, loginid); 
       String s = l.getPassword(); 
       if (!s.equalsIgnoreCase(cmppassword)) 
        throw new PasswordMissmatchException(); 
       writeResultToStats(loginid, true); 
      } catch (PasswordMissmatchException e) { 
       writeResultToStats(loginid, false); 
      } 
     } 

     @Asynchronous 
     @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
     private void writeResultToStats(Long loginID, boolean success) { 

      try { // just for testing 
       Thread.sleep(10000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      LogUtils log = new LogUtils(this); 
      Login l = em_local.find(Login.class, loginID); 
      if (success) { 
       l.setSuccessLast(new Date()); 
       l.setSuccessCount(l.getSuccessCount()+1); 
       log.log(Level.INFO, "Update Login Stat Success [%d, %s, %d]", l.getId(), l.getName(), Thread.currentThread().getId()); 
      } else { 
       l.setFailureLast(new Date()); 
       l.setFailureCount(l.getFailureCount()+1); 
       log.log(Level.INFO, "Update Login Stat Fail [%d, %s, %d]", l.getId(), l.getName(), Thread.currentThread().getId()); 
      } 

     } 

    } 
+1

:

하지만 그 대신 다른 빈을 만드는, 당신은의 SessionContext를 통해 비동기 Bean 메소드를 호출 할 수 있습니다. 지금은 로컬 메서드 호출로 처리됩니다. –

+0

이 문제를 해결하고 다시 돌아 오게하십시오 –

+0

그것은 작동합니다. 감사. –

답변

9

비동기식 메소드를 별도의 ejb로 분해 해보십시오. 동일한 ejb 내부에서 호출 된 메소드는 로컬 메소드 호출과 같이 처리됩니다. 컨테이너는 메소드 호출을 인터셉트 할 수 없습니다.

EJB 주석은 컨테이너에 의해 호출이 수행 될 때에 만 실행됩니다.

대체

동일한 EJB의 방법이있을 수 있지만 빈을 조회하고 methord에 액세스 할 EJB 로컬 인터페이스를 사용할 수 있는지 확인하십시오.

6

예를 들어 this을 보시면 별도의 EJB를 만들 필요가 없음을 보여줍니다.

동기 및 비동기 메소드가 모두있는 bean이있는 경우, 컨테이너가이를 인터셉트하지 않으므로 비동기 메소드를 동기식 메소드에서 호출 할 수 없습니다. 난 당신이 다른 EJB에 비동기 방법을 깰 필요가 있다고 생각

@Stateless 
public class OrderProcessorBean { 
    @Inject 
    SessionContext ctx; 
    //synchronous method invoked from EJB call outside this class 
    public void synch() { 
     //call asynch method 
     ctx.getBusinessObject(OrderProcessorBean.class).asynch(); 
    } 

    @Asynchronous 
    public void asynch() { 
     //asynch logic 
    } 
} 
+2

링크 전용 답변은 권장되지 않으므로 SO 답변은 솔루션 검색의 종단점이어야합니다 (시간이 지남에 따라 오래 걸리는 경향이있는 또 다른 스톱 오버 참조). 링크를 참조 용으로 유지하면서 독립형 시놉시스를 여기에 추가하는 것을 고려해보십시오. – kleopatra