3 Replies Latest reply on Jul 3, 2007 11:04 PM by jahlborn

    A better IsLocalInterceptor?

    jahlborn

      Jboss has always had the behavior where calls to remote beans are made locally if the same service exists on the local server. This may or not be desired behavior. We've had this problem in the past, where we really do want to call the remote server, even if the same service exists locally. In the ejb3 world, this optimization is done by the IsLocalInterceptor, which makes it fairly easy to factor out of the picture (in the ejb 2 world the behavior is embedded within the interceptor which actually makes the remote call). So, we've written a new interceptor for ejb3 which uses the jboss partition name to determine if the local call optimization should really be done or not. This seems to be correct behavior and seems to work. I'd appreciate feedback from jboss people indicating whether or not this is really a valid test. If so, it would be great if this code could be included in jboss for others to use (even if it is not used by default).

      To use this you would replace the relevant references to IsLocalInterceptor in the deploy/ejb3-interceptors-aop.xml with references to this class instead.

      package com.hmsonline.jbossbootstrap.remoting;
      
      import java.io.Serializable;
      
      import org.jboss.aop.advice.Interceptor;
      import org.jboss.aop.joinpoint.Invocation;
      import org.jboss.ejb3.remoting.IsLocalInterceptor;
      import org.jboss.system.server.ServerConfigUtil;
      
      
      /**
       * This interceptor fixes the IsLocalInterceptor, which makes local calls
       * regardless of whether that's what is intended by the user. This
       * Interceptor instead stores the PartitionName of the partition on which the
       * interceptor was created and compares that to the partition name of the
       * invoking partition. If the names differ, the call is treated as a remote
       * call. Assuming that the partition names are setup correctly (which they
       * must be, or other bad things happen), then this test should be
       * sufficient for both clustered and non-clustered remote proxies.
       *
       * @author James Ahlborn
       */
      public class IsReallyLocalInterceptor implements Interceptor, Serializable
      {
       private static final long serialVersionUID = -2472756311741041575L;
      
       /** interceptor which handles actual local invocations */
       private IsLocalInterceptor _delegate = new IsLocalInterceptor();
       /** the name of the partition on which this interceptor was created, filled
       in at construction */
       private String _creationPartitionName;
       /** the name of the partition on which the interceptor is being utilized,
       re-filled in on deserialization */
       private transient String _invocationPartitionName;
      
      
       public IsReallyLocalInterceptor() {
       // store the partition name on which this interceptor is created
       _creationPartitionName = getInternedPartitionName();
       _invocationPartitionName = _creationPartitionName;
       }
      
       public String getName()
       {
       return getClass().getName();
       }
      
       public Object invoke(Invocation invocation) throws Throwable
       {
       // if we got the interceptor locally, let IsLocalInterceptor handle the
       // call, otherwise continue down the interceptor chain. Note, we intern
       // the partition names so we can use object equality.
       if(_creationPartitionName == _invocationPartitionName) {
       return _delegate.invoke(invocation);
       }
      
       return invocation.invokeNext();
       }
      
       private void readObject(java.io.ObjectInputStream in)
       throws java.io.IOException, ClassNotFoundException
       {
       // handle serialized fields
       in.defaultReadObject();
      
       // make sure creation partition is interned
       _creationPartitionName = _creationPartitionName.intern();
      
       // grab the invocation partition
       _invocationPartitionName = getInternedPartitionName();
       }
      
       /**
       * Returns the partition name of the current environment, interned.
       */
       private static String getInternedPartitionName() {
       return ServerConfigUtil.getDefaultPartitionName().intern();
       }
      
      }
      



        • 1. Re: A better IsLocalInterceptor?
          jahlborn

          The class went through a variety of iterations, and i realized the version above could be simplified a bit more:

          package com.hmsonline.jbossbootstrap.remoting;
          
          import java.io.Serializable;
          
          import org.jboss.aop.advice.Interceptor;
          import org.jboss.aop.joinpoint.Invocation;
          import org.jboss.ejb3.remoting.IsLocalInterceptor;
          import org.jboss.system.server.ServerConfigUtil;
          
          
          /**
           * This interceptor fixes the IsLocalInterceptor, which makes local calls
           * regardless of whether that's what is intended by the user. This
           * Interceptor instead stores the PartitionName of the partition on which the
           * interceptor was created and compares that to the partition name of the
           * invoking partition. If the names differ, the call is treated as a remote
           * call. Assuming that the partition names are setup correctly (which they
           * must be, or other bad things happen), then this test should be
           * sufficient for both clustered and non-clustered remote proxies.
           *
           * @author James Ahlborn
           */
          public class IsReallyLocalInterceptor implements Interceptor, Serializable
          {
          
           /** interceptor which handles actual local invocations */
           private final IsLocalInterceptor _delegate = new IsLocalInterceptor();
           /** the name of the partition on which this interceptor was created, filled
           in at construction */
           private final String _creationPartitionName;
           /** whether or not this object is on a box in the same cluster in which the
           object was originally created */
           private transient boolean _isCreationCluster;
          
          
           public IsReallyLocalInterceptor() {
           // store the partition name on which this interceptor is created
           _creationPartitionName = getPartitionName();
           _isCreationCluster = true;
           }
          
           public String getName()
           {
           return getClass().getName();
           }
          
           public Object invoke(Invocation invocation) throws Throwable
           {
           // if we got the interceptor on this cluster, let IsLocalInterceptor
           // handle the call, otherwise continue down the interceptor chain.
           if(_isCreationCluster) {
           return _delegate.invoke(invocation);
           }
          
           return invocation.invokeNext();
           }
          
           private void readObject(java.io.ObjectInputStream in)
           throws java.io.IOException, ClassNotFoundException
           {
           // handle serialized fields
           in.defaultReadObject();
          
           // grab the invocation partition and determine if we are still on the same
           // cluster
           String invocationPartitionName = getPartitionName();
           _isCreationCluster =
           _creationPartitionName.equals(invocationPartitionName);
           }
          
           /**
           * Returns the partition name of the current environment.
           */
           private static String getPartitionName() {
           return ServerConfigUtil.getDefaultPartitionName();
           }
          
          }
          


          • 2. Re: A better IsLocalInterceptor?

            Hi James, first of all, thanks for your contribution...

            I've tried to use it in our EJB3 application (two independent -non clustered- servers, both containing the same SLSB, and trying to invoke the SB remotely from one server to the other one) without success...

            We tried placing a jar with the class in \lib, in \deploy and in both at the same time, but we get a ClassNotFoundException for IsReallyLocalInterceptor when we try to lookup the remote bean.

            Could you please explain a little bit more what references in ejb3-interceptors-aop.xml should be changed, and where to place your class?

            Kind Regards,
            Guido Scalise

            • 3. Re: A better IsLocalInterceptor?
              jahlborn

              we have the compiled class in a jar in the server/[profile]/lib directory. the interceptors file has:

              <!-- near the top -->
              <interceptor class="com.hmsonline.jbossbootstrap.remoting.IsReallyLocalInterceptor" scope="PRE_VM"/>
              
              <!-- in each stack -->
               <stack>
               <interceptor-ref name="com.hmsonline.jbossbootstrap.remoting.IsReallyLocalInterceptor"/>
               ...
               </stack>