9 Replies Latest reply on Oct 11, 2010 3:37 AM by verydapeng

    Interceptor is not invoked within same bean

    verydapeng

      i have implemented a very simple LogAccess interceptor, which i want to record the method invocations.


      codes below. when i call the m1(), i only got the m1 logged, not m2 ...


      so is this the limitation of the CDI interceptor impl ?


      glassfish 3.0.1 opensource edition


      @Stateless
      public class MyBean {
      
          @LogAccess
          public String m1() {
              return m2();
          }
      
          @LogAccess
          public String m2() {
              return "hello world";
          }
      }
      
      @LogAccess
      @Interceptor
      public class LogAccessInterceptor {
          Logger logger = Logger.getLogger("LogAccess");
          @AroundInvoke
          public Object logAccess(InvocationContext ic) throws Exception {
              logger.info(ic.getMethod().toString());
              return ic.proceed();
          }
      }
      
      @InterceptorBinding
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.METHOD, ElementType.TYPE})
      public @interface LogAccess {
      }
      
      
      
      
      



        • 1. Re: Interceptor is not invoked within same bean
          cjalmeida

          This is the correct behavior as in the CDI spec. Only methods called by client classes are considered business methods and, thus, are intercepted.

          • 2. Re: Interceptor is not invoked within same bean
            nimo22

            when i call the m1(), i only got the m1 logged, not m2 ...

            If you want to call m2 when calling m1, then you can use a CDI-Event.


            If you want to trigger more than one interceptors within one method invocation, then you can use standard ejb annotation:


            @Interceptors(A.class, B.class)
            public Customer m1()

            • 3. Re: Interceptor is not invoked within same bean
              asiandub

              Cloves Almeida wrote on Oct 04, 2010 19:17:


              This is the correct behavior as in the CDI spec. Only methods called by client classes are considered business methods and, thus, are intercepted.


              I don't get this. What does that imply for the above snippet? That this code does not contain any business-methods? Certainly a client (whatever that is in the sense of the spec) can call both methods, can't it?


              • 4. Re: Interceptor is not invoked within same bean
                asiandub

                nimo mayr wrote on Oct 05, 2010 05:45:


                when i call the m1(), i only got the m1 logged, not m2 ...

                If you want to call m2 when calling m1, then you can use a CDI-Event.

                If you want to trigger more than one interceptors within one method invocation, then you can use standard ejb annotation:

                @Interceptors(A.class, B.class)
                public Customer m1()


                I'd recommend to raise the interceptor to class level, and check each method invocation. You'll find a very helpful class AnnotationUtils in SEAM-FACES, which provides an isAnnotationPresent(class clazz) method.

                • 5. Re: Interceptor is not invoked within same bean
                  verydapeng

                  could you please elaborate more ?



                  i change to




                  @LogAccess
                  @Stateless
                  public class MyBean {
                  
                      public String m1() {
                          return m2();
                      }
                  
                      public String m2() {
                          return "hello world";
                      }
                  }




                  but i getitng the same result as only m1 is logged, m2 is not





                  • 6. Re: Interceptor is not invoked within same bean
                    asiandub

                    Dapeng,


                    my idea is to raise the interceptor-binding to class level, and make the interceptor intercept each method call. in the interceptor itself you then have to check for the presence of a certain annotation, just like this:


                    
                    @LogAccess
                    @Interceptor
                    public class TaskInterceptor implements Serializable {
                    
                    @AroundInvoke
                         public Object around(final InvocationContext ctx) throws Exception {
                    
                              if (Annotations.isAnnotationPresent(ctx.getMethod(), LogAccess.class)) {
                                        ...
                              }
                              return ctx.proceed();
                         }
                    



                    I would expect this to work, but as I stated earlier: I'm not sure about the intention of the spec in this case.

                    • 7. Re: Interceptor is not invoked within same bean
                      asiandub

                      btw, just to doublecheck: can you confirm that you are call both methods from outside of your bean? the interceptor is not expected to work for internal calls....

                      • 8. Re: Interceptor is not invoked within same bean
                        asiandub

                        good morning to myself


                        ;-)



                        i overlooked the fact that you are calling m2 from within m1.


                        what cloves almeida posts is absolutely correct - only external calls are intercepted, no internal calls.



                        • 9. Re: Interceptor is not invoked within same bean
                          verydapeng

                          thank you guys for your help