10 Replies Latest reply on Oct 29, 2009 6:10 PM by william.drai

    Conditional observers

    william.drai

      Hi,


      I've tried to set up a global event handler like this :


      @SessionScoped
      public class GlobalEventHandler {
      
          public void processEvent(@Observes(notifyObserver=Notify.IF_EXISTS) @Any Object event) {
             // Do something
          }
      }
      



      However it breaks at runtime by trying to handle the BeforeBeanDiscoveryEvent, because of course the session context is not active at this time and the observer processor tries to get the bean reference.
      I wonder if this is a bug or not because it seems to me that IF_EXISTS should apply to both the bean instance and the underlying context.


      The spec on 'conditional observers' does not seem to define a precise behaviour in this case.

        • 1. Re: Conditional observers
          gavin.king

          Hrm. Interesting. Ordinary beans are not allowed to observe container lifecycle events. It seems like we should make that explicit and validated at startup time...

          • 2. Re: Conditional observers
            william.drai

            In fact I don't want to observe container lifecycle events.
            I just want to observe all my application events (thus the Object type) and preferably without having to implement a ApplicationEvent interface, so it would be a problem for me if what I do became forbidden by the spec.

            • 3. Re: Conditional observers
              gavin.king

              I don't see how we could really make this work. You've explicitly specified that you want everything, by using @Any. To be honest, I really don't see your usecase for this.

              • 4. Re: Conditional observers
                pmuir

                Gavin King wrote on Oct 28, 2009 20:24:


                Hrm. Interesting. Ordinary beans are not allowed to observe container lifecycle events. It seems like we should make that explicit and validated at startup time...


                This is a bug. We shouldn't be firing lifecycle events to anything that doesn't impl extension.


                Please file a WELD issue with classes to reproduce.

                • 5. Re: Conditional observers
                  william.drai

                  In fact this already works (almost...). This global event handler will select itself which events it needs to process, that's why I want to observe @Any Object, no problem with this, the handler can just ignore lifecycle events.
                  The problem is that Weld tries to trigger this observer during application startup when there is no session context. I thought that IF_EXISTS would be enough to avoid this but this is not the case because Weld still tries to get the bean reference and gets a ContextNotActiveException.


                  Anyway I've found a way to do what I want, hopefully this will be 'legal' in the final release :


                  public class GlobalObserver {
                      @Inject
                      private BeanManager manager;
                  
                      public void processEvent(@Observes(notifyObserver=Notify.ALWAYS) @Any Object event) {
                          try {
                              Bean<GlobalEventHandler> gehBean = (Bean<GlobalEventHandler>)manager.getBeans(GlobalEventHandler.class).iterator().next();
                              GlobalEventHandler eventHandler = (GlobalEventHandler)manager.getReference(gehBean, GlobalEventHandler.class);
                           if (eventHandler != null)
                                eventHandler.processEvent(event);
                           }
                           catch (ContextNotActiveException e) {
                               // Ignore event, no session context
                           }
                      }
                  }
                  
                  @SessionScoped
                  public class GlobalEventHandler {
                  
                      public void processEvent(Object event) {
                          ...
                      }
                  }
                  



                  The use case is relatively specific as I'm working on the integration of Flex and JCDI/Weld in the GraniteDS project. This global handler is meant to send back to the Flex client some events for which the client has registered itself as listener.
                  Maybe there is another way to do this with portable extensions, but I've not seen anything that would allow for intercepting any kind of event, or at least to register dynamically event observers once the application is deployed (that enough would probably fit my needs).

                  • 6. Re: Conditional observers
                    gavin.king

                    This is a bug. We shouldn't be firing lifecycle events to anything that doesn't impl extension.

                    Hrm. I agree that this sounds desirable, and I can see how you would probably read the spec to imply that, but it's not explicit in the spec. I suppose I should make that explicit. Let me think about it.

                    • 7. Re: Conditional observers
                      gavin.king

                      Maybe there is another way to do this with portable extensions

                      Yes, implement ObserverMethod and call AfterBeanDiscovery.addObserverMethod() from an Extension. If that approach doesn't work, it is definitely a bug.

                      • 8. Re: Conditional observers
                        gavin.king

                        Or a completely different solution is to just declare your observer method on an Extension :-)

                        • 9. Re: Conditional observers
                          gavin.king

                          but it's not explicit in the spec

                          I've updated the spec to say very explicitly that container lifecycle events aren't delivered to ordinary beans.

                          • 10. Re: Conditional observers
                            william.drai

                            Thanks, I'll try these solutions