7 Replies Latest reply on Aug 20, 2009 10:43 AM by acerberus

    Intercept invocation of component's own method

    trossmy

      I would like every invocation of a method of my component to be intercepted, even the ones that the component invokes on itself. Consider something like this:




      @Name("myComponent")
      @LogAllDoSomethings
      public class MyComponent
      {
      
         public void doSomething1()
         {
            doSomething2(); 
         }
      
         public void doSomething2()
         {
      
         }
      }



      Then the @LogAllDoSomethings should output:



      starting doSomething1


      starting doSomething2


      finished doSomething2


      finished doSomething1


      with spring AOP I could achieve this like this:


      @Name("myComponent")
      @LogAllDoSomethings
      public class MyComponent
      {
      
          public void doSomething1()
          {
              ELContext elContext = FacesContext.getCurrentInstance().getELContext();
              ExpressionFactory factory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
              MethodExpression expression = factory.createMethodExpression(elContext, "#{myComponent.doSomething2}", null, new Class[0]);
              expression.invoke(elContext, null);
          }
      
          public void doSomething2()
          {
      
          }
      }



      This approach does not seem to work with seam. Any ideas?


        • 1. Re: Intercept invocation of component's own method
          wrzep

          Inject yourself (@In MyComponent myComponent) and call myComponent.doSomething2()? This way the call will be proxied and your interceptor should be invoked.


          -Pawel

          • 2. Re: Intercept invocation of component's own method
            trossmy

            thanx, but unfortunately it does not seem to work:



            @Name("myComponent")
            @LogAllDoSomethings
            public class MyComponent
            {
                @In
                MyComponent myComponent;
            
                public void doSomething1()
                {
                    myComponent.doSomething2();
                }
            
                public void doSomething2()
                {
            
                }
            
            }



            the method gets executed alright, but is not intercepted.


            • 3. Re: Intercept invocation of component's own method
              wrzep

              Hmm, that's interesting. Does it work correctly if doSomething2() is in the another component (annotated with @LogAllDoSomethings)?


              -Pawel

              • 4. Re: Intercept invocation of component's own method
                trossmy

                yes, if it is in another injected component it works alright:


                @Name("myComponent")
                @Log2Db
                public class MyComponent
                {
                    @In("myComponent2")
                    MyComponent2 myComponent2;
                
                    public void doSomething1()
                    {
                        myComponent2.doSomething2();
                    }
                }





                • 5. Re: Intercept invocation of component's own method
                  wrzep

                  Maybe you should just use JBoss AOP then :)


                  -Pawel

                  • 6. Re: Intercept invocation of component's own method
                    trossmy

                    In the end I could do it quite similar as I did with Spring, only difference is that I had to move the faces methodexpression stuff to it's own component:



                    @Name("componentInvoker")
                    @Scope(ScopeType.SESSION)
                    @AutoCreate
                    public class ComponentInvoker
                    {
                        public Object invoke(String action)
                        {
                            ELContext elContext = FacesContext.getCurrentInstance().getELContext();
                            ExpressionFactory factory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
                            MethodExpression expression = factory.createMethodExpression(elContext, "#{" + action + "}", null, new Class[0]);
                            return expression.invoke(elContext, null);
                        }
                    }



                    and then I can add a method to the baseclass of all my components:



                     protected String invokeOnSelf(String method)
                        {
                            Name service = this.getClass().getAnnotation(Name.class);
                            String componentName = service.value();
                            return (String) componentInvoker.invoke(componentName + "." + method);
                        }
                    



                    so that in the end it will look like this:



                    @Name("myComponent")
                    @LogAllDoSomethings
                    public class MyComponent extends MyBaseClass
                    {
                       @In("componentInvoker")
                       ComponentInvoker componentInvoker;
                    
                        public void doSomething1()
                        {
                            invokeOnSelf("doSomething2");
                        }
                    
                         public void doSomething2()
                        {
                    
                        }
                    }
                    



                    which I can live with;-)


                    Thanx 4 the help








                    • 7. Re: Intercept invocation of component's own method
                      acerberus

                      Nice workaround, but is there really no other way of achieving this. This just looks too complicated for this very simple task.