2011-10-03 2 views
0

는 트랜잭션이 성공하면 말을하거나 실패, 내가 트랜잭션 관찰자에 대한 지정된 문서의 다음 해요 : http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html_single/#d0e4075JBoss AS 7에서 실행 된 이벤트에서 트랜잭션 @observes가 작동합니까? 이벤트를 사용하기 위해서는

을 ...하지만 제이 보스 AS7에 내 코드가 작동하도록 관리 할 수 ​​없습니다. 여기

내 EJB입니다 : 여기

@LocalBean 
@Stateful 
@TransactionAttribute(TransactionAttributeType.NEVER) 
public class MyController 
{ 
    @Inject 
    private transient Event<MyEvent> myEventLauncher; 

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void save() 
    { 
     myEventLauncher.fire(new MyEvent()); 
    } 

    @AfterCompletion 
    protected void afterSave(boolean isCommitted) 
    { 
     // do stuff 
    } 
} 

그리고 내 기본 리스너 :

public class MyHandler 
{ 
    protected void listenMyEvent(@Observes(during=TransactionPhase.AFTER_SUCCESS) MyEvent event) 
    { 
     // do stuff 
    } 

    protected void listenMyEvent2(@Observes(during=TransactionPhase.AFTER_FAILURE) MyEvent event) 
    { 
     // do stuff 
    } 
} 

내가, 내가 이벤트가 발생되는 거래에있어 말할 수 EJB의 afterSave 방법 때문에 호출됩니다. 슬프게도, listenMyEventlistenMyEvent2 메소드는 항상 트랜잭션 컨텍스트가 아닌 것처럼 둘 다 호출됩니다.

GlassFish 3에서 동일한 코드를 시도했는데 완벽하게 작동하므로 JBoss AS 7에 문제가있는 것 같지만 버그 보고서를 찾을 수 없습니다.

답변

0

글쎄, 내 현재 테스트에서 트랜잭션 관찰자가 JBoss AS 7에서 작동하지 않는다고 생각하게 만들었 기 때문에 나는 관심있는 사람들을 위해 여기서 해결 방법을 제시했다. , AfterFailureAfterSuccess과 같은 한정어 주석이 먼저 필요합니다. Immediate, AfterFailureAfterSuccess. 또한

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.FIELD, ElementType.PARAMETER }) 
public @interface AfterFailure 
{} 

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.FIELD, ElementType.PARAMETER }) 
public @interface AfterSuccess 
{} 

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.FIELD, ElementType.PARAMETER }) 
public @interface Immediate 
{} 

, 세 가지 기본 AnnotationLiteral이 세 가지 주석의 런타임 경우에 만들 수 있습니다.

그런 다음 실제 이벤트에 캡슐 레이터가 필요합니다. 이름은 SpecialEvent입니다.

public class SpecialEvent 
{ 
    private Object event; // the real event you want 

    public SpecialEvent(Object event) 
    { 
     super(); 
     this.event = event; 
    } 

    public Object getEvent() 
    { 
     return event; 
    } 
} 

그리고 마침내

,이 특별한 이벤트에 대한 관찰자 및 이벤트 이런 종류의 (아래 자세한 설명을) 발사하려는 클래스 인터셉터.
@RequestScoped 
public class SpecialEventObserver 
{ 
    @Inject 
    private Event<Object> anyEventFirer; // firer for real events 
    private List<Object> events; // queued events 

    public SpecialEventObserver() 
    { 
     events = new ArrayList<Object>(); 
    } 

    // remove all queued events 
    public void reset() 
    { 
     this.events.clear(); 
    } 

    public void fireAfterFailureEvents() throws Exception 
    { 
     this.fireAllEventsOnce(new AfterFailureLiteral()); 
    } 

    public void fireAfterSuccessEvents() throws Exception 
    { 
     this.fireAllEventsOnce(new AfterSuccessLiteral()); 
    } 

    protected void listenSpecialEvent(@Observes SpecialEvent specialEvent) 
    { 
     Object event = specialEvent.getEvent(); 
     this.events.add(event); 
     this.fireEvent(event, new ImmediateLiteral()); 
    } 

    protected void fireAllEventsOnce(Annotation qualifier) throws Exception 
    { 
     try 
     { 
      for (Object event : this.events) 
      { 
       this.fireEvent(event, qualifier); 
      } 
     } 
     catch (Exception e) 
     { 
      throw e; 
     } 
     finally 
     { 
      this.events.clear(); 
     } 
    } 

    protected void fireEvent(Object event, Annotation qualifier) 
    { 
     Event eventFirer = anyEventFirer.select(event.getClass(), qualifier); 
     eventFirer.fire(event); 
    } 
} 

@Interceptor 
@LocalInterception 
public class MyInterceptor implements Serializable 
{ 
    @Inject 
    private SpecialEventObserver specialEventObserver; 

    @AroundInvoke 
    public Object intercept(InvocationContext ic) throws Exception 
    { 
     specialEventObserver.reset(); 
     try 
     { 
      // call the real method 
      Object proceedResult = ic.proceed(); 

      // real method succeeded, fire successful events 
      specialEventObserver.fireAfterSuccessEvents(); 

      return proceedResult; 
     } 
     catch (Exception e) 
     { 
      // real method failed, fire failed events 
      specialEventObserver.fireAfterFailureEvents(); 

      throw e; 
     } 
    } 
} 

메커니즘

은 매우 간단합니다 :

  • 당신이 진정한 이벤트를 누르고 있습니다 SpecialEvent 화재, 이벤트를 발생하려는 경우.
  • SpecialEventObserverSpecialEvent을 붙잡고 즉시 Immediate 수식어로 자신의 이벤트를 실행합니다. 또한 완료 후 부분에 대한 이벤트를 큐에 넣습니다. 자신의 메서드 호출 (인터셉터에서 ic.proceed)의 끝에서
  • MyInterceptor 물어 것 SpecialEventObserver 중 하나를 다시 AfterFailure 규정이나 방법의 성공을 따라 AfterSuccess 규정, 모든 이벤트를 발생합니다.
  • @Observes(during=...) 대신 자신의 관찰자는 @Observes @Immediate, @Observes @AfterFailure 또는 @Observes @AfterSuccess과 같은 올바른 한정자로 이벤트를 관찰해야합니다.

동작이 네이티브 @Observes(during=...)을 제공하는 것과 정확하게 일치하지 않습니다.완료 후 부분은 트랜잭션 상태에 따라 것이 아니라 자신의 메서드 호출 성공 :

JaveEE6에서
  • , 당신은 트랜잭션에하지 않으면 성공 후 즉시 호출해야 실패 단계 이후에 트랜잭션 관찰자 같은 IN_PROGRESS 할 것입니다.
  • 이 해결 방법에서는 성공 또는 실패 이후의 관찰자는 항상 메서드가 끝날 때 및 성공 또는 실패한 경우에만 호출됩니다.
0

이것은 완벽하게 Java EE를 준수하는 것으로 보이는 버전 7.1.0.Final (아마 Jboss와 함께)에서 작동합니다. 또한 빈은 동시 대기열 대신 목록을 사용하므로 스레드로부터 안전하지 않습니다. 솔기가 성공적입니다 그것에 대해 문제가있다 (그 안에 포함됩니다 직면했을 때

http://www.seamframework.org/Documentation/WhyIsThereNoActiveTransactionInMySFSBTransactionalObserver

+0

글쎄, 우리는 7.1.0에 그것을 시도 할 것이다 : 여기에 언급 한 바와 같이 –

+0

늦게 답장을 드려 죄송합니다. 용접 사양은 "during"속성의 특정 값에 대한 관찰자 방법의 트랜잭션 컨텍스트와 관련하여 정의되지 않은 동작을 "정의"한다고 알았습니다. 제어 흐름의 관점에서 볼 때 트랜잭션이 여전히 사용 가능해야한다고 여겨집니다. 옵저버 메소드를 트랜잭션이 필요한 것으로 선언하면 트릭을 수행합니다. – bennidi

0

귀하의 관찰자 방법

는 REQUIRES_NEW 필요 우리를 막는). 또한,`@ RequestScoped '이기 때문에 빈은`List`를 사용할 수 있고 스레드가 안전하지 않다고 생각합니다.