Singleton EJB observer
seacuke23 Aug 22, 2013 11:52 AMI'm trying to have my singleton EJB be an event observer. The problem I'm having seems particularly related to the fact that my observer method is in an abstract superclass and I need to do some env-entry injection also. I have class EventObserver which is an abstract superclass implementing a business interface and observing an event. There are 2 child classes EventObserverImpl1 and EventObserverImpl2. My application will have only one of these child classes defined in the ejb-jar file as a singleton. What I'm seeing is that the singleton that is defined has it's observer method called as I expect, however the other child class is also constructed. This is especially problematic because the super class injects an env-entry which fails for the non-ejb class.
@Target({FIELD, PARAMETER}) @Retention(RUNTIME) @Qualifier public @interface MyEvent {}
@Singleton @Startup public class EventFirer { @Inject @MyEvent private Event<String> e; @Resource private TimerService ts; @PostConstruct public void pc(){ ts.createSingleActionTimer(5000, new TimerConfig(null, false)); } @Timeout public void go(){ e.fire("hi"); } }
public interface MyObserverInterface { public void observe(String e); }
public abstract class EventObserver implements MyObserverInterface { private static final Logger l = Logger.getLogger(EventObserver.class); @Resource(name="resourceName") private String resourceName="default"; public EventObserver(){ l.info(this + " -- constructed."); } @Override public void observe(@Observes @MyEvent String e){ l.info(this + " -- " + resourceName + " -- received notification - " + e); } protected abstract void doSomething(); }
public class EventObserverImpl1 extends EventObserver { protected void doSomething() {} }
public class EventObserverImpl2 extends EventObserver { protected void doSomething() {} }
<session> <ejb-name>MyBean</ejb-name> <business-local>com.demo.test.EventTest.test3.MyObserverInterface</business-local> <ejb-class>com.demo.test.EventTest.test3.EventObserverImpl1</ejb-class> <session-type>Singleton</session-type> <env-entry> <env-entry-name>resourceName</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>injectedValue</env-entry-value> </env-entry> </session>
.... 09:28:08,031 INFO [com.demo.test.EventTest.test3.EventObserver] (EJB default - 1) com.demo.test.EventTest.test3.EventObserverImpl2@3b9315b1 -- constructed. .... Caused by: java.lang.RuntimeException: Error looking up java:comp/env/resourceName in JNDI at org.jboss.weld.injection.spi.helpers.AbstractResourceServices.resolveResource(AbstractResourceServices.java:51) at org.jboss.weld.util.Beans.injectEEFields(Beans.java:698) ....
I'm using JBoss EAP 6.1.0.GA (AS 7.2.0.Final-redhat-8). I've tried changing the observes annotation by adding notifyObserver=Reception.IF_EXISTS and making the class ApplicationScoped but then the observer doesn't get called at all. If I remove the child class I'm not using as the singleton, the EJB is called as I expect. My current workaround is not to observe in the EJB but have a POJO observe and call the bean.
So my question is, is it possible to have a superclass implement an observer and have it only call the EJB implementation and not attempt to construct all child implementations?
Message was edited by: seacuke23 -- Clarified logging