为了使用仅在事务成功或失败时监听的事件,我正在关注有关事务观察者的给定文档: http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html_single/#d0e4075
...但无法让我的代码在JBoss 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
方法。唉,方法listenMyEvent
和listenMyEvent2
总是被调用,就像我不在事务上下文中一样。
我在GlassFish 3上尝试了相同的代码并且它完全有效,所以我猜JBoss AS 7存在问题,但我找不到任何关于它的错误报告。
答案 0 :(得分:0)
好吧,由于我目前的测试让我觉得交易观察员不在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=...)
的行为。完成后部分不是基于事务状态,而是基于您自己的方法调用成功:
IN_PROGRESS
那样。答案 1 :(得分:0)
这适用于版本7.1.0.Final,它应该是完全符合Java EE的(与你永远不知道的Jboss一起使用)。此外,您的bean不是线程安全的,因为它使用列表而不是并发队列。
答案 2 :(得分:0)
你的观察者方法需要REQUIRES_NEW,如下所述: