글쎄, 내 현재 테스트에서 트랜잭션 관찰자가 JBoss AS 7에서 작동하지 않는다고 생각하게 만들었 기 때문에 나는 관심있는 사람들을 위해 여기서 해결 방법을 제시했다. , AfterFailure
및 AfterSuccess
과 같은 한정어 주석이 먼저 필요합니다. Immediate
, AfterFailure
및 AfterSuccess
. 또한
@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
화재, 이벤트를 발생하려는 경우.
SpecialEventObserver
은 SpecialEvent
을 붙잡고 즉시 Immediate
수식어로 자신의 이벤트를 실행합니다. 또한 완료 후 부분에 대한 이벤트를 큐에 넣습니다. 자신의 메서드 호출 (인터셉터에서 ic.proceed
)의 끝에서
- 는
MyInterceptor
물어 것 SpecialEventObserver
중 하나를 다시 AfterFailure
규정이나 방법의 성공을 따라 AfterSuccess
규정, 모든 이벤트를 발생합니다.
@Observes(during=...)
대신 자신의 관찰자는 @Observes @Immediate
, @Observes @AfterFailure
또는 @Observes @AfterSuccess
과 같은 올바른 한정자로 이벤트를 관찰해야합니다.
동작이 네이티브 @Observes(during=...)
을 제공하는 것과 정확하게 일치하지 않습니다.완료 후 부분은 트랜잭션 상태에 따라 것이 아니라 자신의 메서드 호출 성공 :
JaveEE6에서
- , 당신은 트랜잭션에하지 않으면 성공 후 즉시 호출해야 실패 단계 이후에 트랜잭션 관찰자 같은
IN_PROGRESS
할 것입니다.
- 이 해결 방법에서는 성공 또는 실패 이후의 관찰자는 항상 메서드가 끝날 때 및 성공 또는 실패한 경우에만 호출됩니다.
글쎄, 우리는 7.1.0에 그것을 시도 할 것이다 : 여기에 언급 한 바와 같이 –
늦게 답장을 드려 죄송합니다. 용접 사양은 "during"속성의 특정 값에 대한 관찰자 방법의 트랜잭션 컨텍스트와 관련하여 정의되지 않은 동작을 "정의"한다고 알았습니다. 제어 흐름의 관점에서 볼 때 트랜잭션이 여전히 사용 가능해야한다고 여겨집니다. 옵저버 메소드를 트랜잭션이 필요한 것으로 선언하면 트릭을 수행합니다. – bennidi