6 Replies Latest reply on May 13, 2005 2:29 AM by twundke

    CacheInterceptor not intercepting

    iapetus999

      I may cross-post this on the JBoss Cache forum too...

      I have a class which is "prepared" in the aop.xml file.

      The TreeCacheAop implementation then calls this:

      
      InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
       advisor.appendInterceptor(new CacheInterceptor(this, fqn, type));


      where obj is the prepared object.
      Then I call
      fieldX = val
      inside my class where fieldX is a member of my class.
      The interceptor's "invoke" never gets called, so the change never gets committed to the cache.

      Could someone help me try to figure this out?
      There is another class that extends this class, and field accesses on that class are intercepted. Could this be a problem with intercepting field accesses in a superclass?

      Let me know what more info I can provide.
      This is completely preventing me from using the jboss cache since many of my field updates are not being committed.

      Jboss AS 4.0.1.sp1
      jboss-aop_1.1.1 (jboss-aop-jdk50.deployer)
      jbossCache-1.2.1
      java (build 1.5.0_02-b09)
      -andy



        • 1. Re: CacheInterceptor not intercepting
          bill.burke

          * Are you precompiling using AOPC?
          * Are you using Loadtime transformation?

          • 2. Re: CacheInterceptor not intercepting
            iapetus999

            I'm deploying the jboss-aop-jdk50.deployer package to my server's deploy directory and then using loadtime transformation:

            <attribute name="EnableTransformer">true</attribute>
            

            I'm not using AOPC.
            I have a .aop package in my .ear file which contains a meta-inf/jboss-aop.xml file.
            In the xml file I have

            <prepare expr="field(* $instanceof{com.memeticsystems.item.common.IItem}->*)"/>

            where my class implements IItem




            • 3. Re: CacheInterceptor not intercepting
              bill.burke

              you have to add a jboss-app.xml to your EAR's META-INF directory (it is the jboss specific application.xml DD).

              <jboss-app>
               <module>
               <service>foo.aop</service>
               </module>
              </jboss-aop>
              



              • 4. Re: CacheInterceptor not intercepting
                iapetus999

                I have that.
                AOP is generally working fine. It's just this one specific instance that is not working.

                • 5. Re: CacheInterceptor not intercepting

                  Can you open a Jira issue in JBossCache and attach the sample file so I can take a look?

                  -Ben

                  • 6. Re: CacheInterceptor not intercepting
                    twundke

                    I have the same problem, and have found out what's going on through much trial and error!

                    The basic problem occurs when you're attempting to instrument a class and its superclass.

                    public abstract class Base {
                     private int attribute;
                    
                     getAttribute()...
                     setAttribute()...
                    }
                    
                    
                    public class Extender extends Base {
                     private int other;
                    
                     getOther()...
                     setOther()...
                    }
                    
                    
                    <aop>
                     <prepare expr="field(* $instanceof{Base}->*)" />
                    </aop>
                    

                    Now, if you attempt to use the class Extender, the JVM will automatically load in Base for you. However, Extender goes through the instumentation phase before Base! This is the root of the problem.

                    org.jboss.aop.instrument.Instrumentor has the following code:
                     public void setupBasics(CtClass clazz) throws CannotCompileException, NotFoundException
                     {
                     if (basicsSet) return;
                     basicsSet = true;
                     // add serialVersionUID.
                     SerialVersionUID.setSerialVersionUID(clazz);
                    
                     // add marker interface.
                     clazz.addInterface(forName(AOP_PACKAGE + ".Advised"));
                    
                     // add aop helper class.
                     addHelperClass(clazz);
                    
                     if (isBaseClass(clazz))
                     {
                     addBaseElements(clazz);
                     }
                     }
                    
                    
                     private boolean isBaseClass(CtClass clazz)
                     throws NotFoundException
                     {
                     if (clazz.getSuperclass() != null)
                     {
                     return !isAdvised(clazz.getSuperclass());
                     }
                     return true;
                     }
                    

                    So, when Extender gets instrumented, its superclass, Base, is not yet Advised. Extender therefore get an _instanceAdvisor attribute. Base then gets instrumented, and also receives an _instanceAdvisor attribute.

                    Obviously, any call to _setInstanceAdvisor will only update Extender's _instanceAdvisor attribute, as Base's has been overridden.

                    Now TreeCacheAOP comes along and appends an interceptor to Extender, but Base misses out.

                    The upshot of all of this is that calling getAttribute() on Base will not result in the interceptor being called as the local _instanceAdvisor is null. However, calling getOther() will work as its _instanceAdvisor is correct.

                    The problem really occurs because the optimized field wrappers use _instanceAdvisor directly, rather than calling _getInstanceAdvisor(). I assume this is for speed reasons (hence being called optimized!).

                    Using aopc will work this out (at least I assume so). Certainly using aopc on the Base class, but using runtime transformation for the rest solves the problem.

                    This is a significant issue, and I think the only general solution seems to be using _getInstanceAdvisor() in the field wrappers, unless of course the JVM changes its semantics to transform superclasses before subclasses. I don't have full knowledge of the infrastructure though, so perhaps there's a nice neat solution out there.

                    Tim.