5 Replies Latest reply on Dec 9, 2009 10:36 PM by gavin.king

    Intercepting self-invocations

    lehphyro.lehphyro.yahoo.com.br

      I just took weld for a spin and found that it is not possible to intercept self-invocations.
      I think this is a great feature but unfortunately only Google Guice support it, spring doesnt too.


      Specifically, I was hoping this would generate two log messages:


      public class MyService1 {
      
          @Inject
          private MyService2 service;
      
          @LogThis
          public String doSomething(String s) {
              return doInternal(s);
          }
      
          @LogThis
          protected String doInternal(String s) {
              return service.doSome(s);
          }
      }
      



      But only the invocation to doSomething() will be intercepted.
      Do you plan to support it in subsequent releases?

        • 1. Re: Intercepting self-invocations
          gavin.king

          CDI does not define the semantics of interceptors, that stuff comes from the Java Interceptors spec, which was originally part of EJB 3, which in turn inherited its interception semantics from earlier versions of EJB. I don't think there's been an discussion at all around adding interception of self-invocations to the Interceptors spec, and I think this is the first time I've seen a user request for it.


          I agree that interception of self-invocation is (very) occasionally useful, but we don't have any plans to support it right now. Well, so far I've never encountered a usecase where this feature was really needed.


          Are you sure Guice supports this? I thought Guice implemented interception via subclassing? If so, I don't see how they could support self-interception of private methods, which account for the bulk of self-invocations. I suppose you could force the user to redeclare the method protected if they want to add an interceptor binding....

          • 2. Re: Intercepting self-invocations
            lehphyro.lehphyro.yahoo.com.br

            This maven project shows guice interceptor logging two messages but the weld one logs only one.
            Guice supports interception of public, protected and package-private methods.
            I'm sorry for posting this on the wrong forum...


            Thanks

            • 3. Re: Intercepting self-invocations
              gavin.king

              Leandro Aparecido wrote on Dec 09, 2009 13:51:


              This maven project shows guice interceptor logging two messages but the weld one logs only one.
              Guice supports interception of public, protected and package-private methods.
              I'm sorry for posting this on the wrong forum...


              OK, but most self-invocations are invocations of private methods. So is this feature really very useful, given that it's so limited? Like I said, I don't know of a really strong usecase for this feature (log two messages instead of one doesn't count as a usecase).

              • 4. Re: Intercepting self-invocations
                lehphyro.lehphyro.yahoo.com.br

                most self-invocations are invocations of private methods

                I personally prefer protected or package-private methods to private because of visibility issues with test cases and extensibility opportunities. As a project progresses, I usually end up realizing that some logic would be better in a superclass or shared in another way (static utilities, for instance). So I may as well start writing protected methods and think about extensibility upfront so I don't need to change them later and think about all the implications on existing code. I rarely write private methods.
                It seems I'm not the only one who prefers protected methods.



                log two messages instead of one doesn't count as a usecase

                Why not? I can think of some possibilities for this like the following:


                    @Trace(level = DEBUG, onException = "Error calling method1 with [%s], [%s]: [%e]")
                    public void method1(int x, int y) {
                        sum(x, y);
                        // Other method calls logged the same way
                    }
                     
                    @Trace(before = "Sum [%s] with [%s]", after = "Result of sum [%s]", level = DEBUG)
                    protected int sum(int x, int y) {
                        return x + y;
                    }
                



                Calling method1(1,2) could generate the following log messages:


                [DEBUG] Executing method1 with x: 1, y: 2


                [DEBUG] Sum [1] with [2]


                [DEBUG] Result of sum [3]


                Since I usually break large methods in small ones, this could allow me to clean up my code a bit from too many calls to logger.debug().


                There are other possibilites too like transaction demarcation (a friend needed this but couldn't implement this way using spring, so he created another bean and called it...):


                    @Transactional
                    public void method1() {
                        // Do something
                        method2();
                    }
                
                    @Transactional(REQUIRES_NEW)
                    public void method2() {
                        // Do something using a new transaction
                    }
                



                I'm sure there are other possibilities. A quick search for self-invocation on spring framework forums finds 24 posts.

                • 5. Re: Intercepting self-invocations
                  gavin.king

                  As you can probably guess, these usecases don't sound very compelling to me, and have easy workarounds. And 24 posts doesn't sound like a huge number, given the heavy traffic on the Spring forum.