3 Replies Latest reply on Aug 23, 2013 11:12 AM by Martin Kouba

    Singleton EJB observer

    seacuke23 Newbie

      I'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

        • 1. Re: Singleton EJB observer
          Martin Kouba Master

          Hi seacuke23,

           

          even if you don't configure EventObserverImpl2 explicitly as a session bean it's recognized as a CDI managed bean with observer method (see also http://docs.jboss.org/cdi/spec/1.0/html/implementation.html#whatclassesarebeans). However resource injection should work on managed beans as well . Do you have a correct JNDI name? Regarding your question: I don't think it's possible and  I see no reason why it should. Simply put the observer method on EJB impl?

          1 of 1 people found this helpful
          • 2. Re: Singleton EJB observer
            seacuke23 Newbie

            Well I need the child implementations to be mutually exclusive...so if Impl1 is observing events and processing it's logic Impl2 should not be observing.  Also, I need the active concrete observer to be determined via configuration.  However, something you said made me think...I can probably use alternatives to accomplish this.  I've annotated each of the impls with @Alternative and only enabled the one I want in beans.xml which seems to do what I want.

             

            Thanks for your time!

            • 3. Re: Singleton EJB observer
              Martin Kouba Master

              Yep, I think alternatives are a good way to go here. But don't forget CDI 1.0 does not allow global selection of alternatives (unlike CDI 1.1) so that you'll have to select the impl bean for every bean archive in your app.

              1 of 1 people found this helpful