那麼,正如我目前的測試使我認爲事務觀察員不在JBoss AS 7中工作,我設法爲我感興趣的人提供了一個解決方法。
首先,我們需要限定符註釋: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當縫面將由成功納入它(有一個關於它的問題是阻止我們)。另外,我認爲我的bean可以使用'List'並且是線程不安全的,因爲它是'@ RequestScoped'。 –
對不起,延遲迴復。我發現焊接規範「定義」了關於觀察者方法的事務上下文的未定義行爲,用於「過期」屬性的某些值。似乎即使從控制流程的角度來看,交易應該仍然可用,但事實並非如此。將觀察者方法聲明爲需要事務處理的技巧。 – bennidi