0 Replies Latest reply on Jul 12, 2009 7:58 AM by Arbi Sookazian

    Understanding Seam interceptors and when to bypass them

    Arbi Sookazian Master

      The following discussion is based on the excellent Seam performance tuning articles by DAllen on jsfcentral.com:


      http://jsfcentral.com/articles/speed_up_your_jsf_app_1.html


      http://jsfcentral.com/articles/speed_up_your_jsf_app_2.html


      Let's assume you have the situation he describes which is multiple rendered attributes in a <rich:dataTable> or equivalent component which are causing the getter methods to be executed multiple times per tag using rendered per row due to the different phases in the JSF life cycle.  In his case, In total, there are 16 uses of the rendered attribute appearing in each row.


      For performance optimization purposes, my idea regarding bypassing interceptors is twofold:


      1) disable interceptors by default for all Seam components' getter/setter methods (why are the interceptors necessary for getter/setter methods?)


      2) refactor @BypassInterceptors to allow user to specify which interceptors to bypass (default ALL)


      According to SiA:



      if you disable interceptors, you end up stripping away all the other interceptor-
      based functionality, not only bijection. Such features include declarative conversation
      controls, transaction management, and event handling, to name a few.

      So we typically start/end conversations via action handler methods (not getter/setter methods).  We are typically not doing any CRUD operations in getter/setter methods (at least we should not be!).  And event handling in getter/setter methods is an atypical use case (those should typically occur in action handler methods).


      What are the other interceptor-based functionalities?


      I have yet to see a thorough treatment of all of Seam's interceptors, only cursory coverage.


      In the org.jboss.seam.core package, we have the following classes:


      BijectionInterceptor
      ConversationalInterceptor
      ConversationInterceptor
      EventInterceptor
      MethodContextInterceptor
      SynchronizationInterceptor


      I am not familiar with all of these classes and their functionalities, but it seems to me that turning off interceptors by default for all getter/setter methods would not have any negative consequences in most cases and would boost performance.


      So are there JIRA issues open for items 1 and 2?  Will these items be addressed in Seam 3?


      Perhaps this is the roadblock, so to speak:



      Seam 2.0 uses an interceptor that aids with maintaining the object identity of persistent objects (managed entities) across passivation of a SFSB, or when components jump nodes in a cluster. This interceptor has good intentions, but can have bad consequences. At the end of a method call on a conversation-scoped component, the interceptor transfers the values of all fields holding references to entity instances directly into the conversation context, and then nullifies the values of those fields. It reverses the process at the beginning of the next call. The consequence is that without interceptors, your conversation-scoped object is missing state. Eeek! What's worse is that the performance of the interceptor is naturally challenged if your component happens to be storing large data sets, because it takes time for the interceptor to perform its work. It's an unfortunate sacrifice in order to achieve transparent replication.

      source: http://jsfcentral.com/articles/speed_up_your_jsf_app_1-3.html


      So exactly which interceptor is DAllen referring to here?  And what is the difference b/n 2.0 and 2.1 apps in this regard?  Can someone shed some more light on this?



      In Seam 2.1, this behavior is disabled by default, so you could just add @BypassInterceptors to the method. However, if you plan to use stateful session beans (SFSBs) in your application or run the application in a cluster, you will need to enable the behavior I am about to describe, so it's important to understand why interceptors on conversation-scoped components are important.

      So does that mean that if we have a JavaBean or SFSB which is conversation-scoped in a Seam 2.0 app, and we use @BypassInterceptors on our getter method and the value that the getter method returns is injected by the Seam container, the value will be null?


      For example:


      public class FooAction implements FooLocal
      
      @In String bar;
      
      public void setBar(String bar){
         this.bar = bar;
      }
      
      @BypassInterceptors
      public String getBar(){
         return bar;
      }
      
      @Remove
      public void destroy(){}



      And what is the probability that this is even a valid scenario?  i.e. if you are not injecting the instance variable, then this will not be a concern...