I really love JPA’s EntityListeners feature - a really lightweight way of doing AOP, but without all the bytecode shenanigans at compiletime. But under EE6 there are a few gotchas - and one of the big ones is that these EntityListeners are not subject to CDI injection. Eeek!
So what do you when you want to get a handle to a CDI Bean? Or what about if you want to raise a CDI Event?
The answer to all your questions is the humble BeanManager. This cheery fellow gives you ways of firing events, grabbing handles to Beans (or creating them), and doing other CDI magic. But chicken and egg time: how to inject the BeanManager without CDI? Well, while you can’t inject it into an EntityListener via CDI, you can actually look it up through your ancient friend JNDI. Behold the magic of Stack Overflow:
public static BeanManager getBeanManager() { try { InitialContext initialContext = new InitialContext(); return (BeanManager) initialContext.lookup("java:comp/BeanManager"); } catch (NamingException e) { log.error("Error in EntityListener resolution of Bean Manager", e); throw new IllegalStateException(e); } }
And once you have yourself a BeanManager, you have the trivial job of raising your events for which the BeanManager’s [fireEvent](http://docs.oracle.com/javaee/6/api/javax/enterprise/inject/spi/BeanManager.html#fireEvent(java.lang.Object, java.lang.annotation.Annotation…)) method will work nicely:
@PrePersist void onCreate(Object object) { getBeanManager().fireEvent(new AuditEvent("create", object)); // your other secret sauce.. }
And all your other CDI Event Observers will work as you expected. Simple, yet profound.
Go forth and raise events from your Listeners!