5 Replies Latest reply on Jun 5, 2008 8:26 PM by stephen

    Why can't I @BypassInterecptors for simple getters?

    stephen

      I noticed that a lot of time is spent in my applications for calls to simple getters of Seam JavaBean components.


      Naively, I tried to add @BypassInterceptors:



      @Name("foo")
      @Scope(ScopeType.CONVERSATION)
      public class Foo {
          private Bar bar;
          
          @BypassInterceptors
          public Bar getBar() {
              return bar;
          }
      }
      



      However this does not work - the value comes back empty in my facelets pages.


      I can probably use the more complicated way described here, creating separate beans as value holders:
      Seam performance problem - rewarding workaround...


      But I really would like to understand why it does not work.
      What magic does Seam provide around a call to a getter of a non-bijected field?

        • 1. Re: Why can't I @BypassInterecptors for simple getters?
          pmuir

          Stephen Friedrich wrote on Jun 04, 2008 17:22:


          But I really would like to understand why it does not work.
          What magic does Seam provide around a call to a getter of a non-bijected field?


          It does. I've sat with developers and seen it working. You must have some way the field gets initialized by Seam.

          • 2. Re: Why can't I @BypassInterecptors for simple getters?
            stephen

            Thanks for the answer.
            That puts my mind at rest somewhat: 5 calls to that getter cost me 400ms if intercepted by Seam and less than 1ms without interception.


            Hm, the value gets initialized in a @Factory method for another context variable, something like this:



            @Factory 
            public Foo getSelectedFoo() {
               ...
               bar = ...;
               ...
               return foo;
            }



            That shouldn't make a difference, should it?
            After all only the bar-getter is bypassed, not the factory method.


            I'll try to create a stripped down example and hopefully while doing that I'll find out what's going on.

            • 3. Re: Why can't I @BypassInterecptors for simple getters?
              stephen

              Weeeeeeell. Two hours of debugging later - I am not so used to Seam internals :-(


              My bar is an entity in a seam managed persistence context.
              It seems that for this entity the swizzlelization provided by the ManagedEntityIdentityInterceptor is missing.
              It is only that interceptor that restores the field value from null to its correct value (in entityIdsToRefs()).


              Is that by design? Or maybe I am doing something wrong, that is just compensated for by the interceptor?


              The javadoc of ManagedEntityIdentityInterceptor reads quite innocently:



              /**
               * Swizzles entity references around each invocation, maintaining
               * referential integrity even across passivation of the stateful 
               * bean or Seam-managed extended persistence context, and allowing 
               * for more efficient replication.
              



              AFAICS there is neither passication nor replication going on here.


              BTW: Seam 2.0.2SP1, Sun JSF 1.2_08-b06-FCS, Facelets 1.1.14 on Tomcat 5.5.17.

              • 4. Re: Why can't I @BypassInterecptors for simple getters?
                stephen

                So, now I finally understand the issue a little better.


                The problem is that the ManagedEntityIdentityInterceptor clears entity field values after the invocation (after saving their ids to conversation context).
                That happens when any other method of my bean (not annotated with @BypassInterceptors) is called.


                Usually the field gets re-initialized in the next invocation using the saved id and the persistence context.


                However that simply does not happen when the interceptor is disabled for the method that gets called next.


                Hm, I don't use replication and session passivation is disabled on Tomcat by default, right?
                So I just have to find a way to disable the ManagedEntityIdentityInterceptor completely.
                Any idea?


                BTW: I just learned that debugger field watchpoints do not trigger if the field's value is changed by reflection. What good is that? I had to set a conditional breakpoint on field.set().


                • 5. Re: Why can't I @BypassInterecptors for simple getters?
                  stephen

                  To sum up: I set the field correctly and seam nulls it behind my back.



                  - In a conversation scoped component



                  - if any method is intercepted


                  - then any other method that accesses any field that holds an entity must be intercepted also.



                  IMHO that is a strange side effect of the implementation that should be corrected.


                  Also the ManagedEntityIdentityInterceptor causes a huge performance hit.
                  I'll post another thread for that topic.