Announcement Announcement Module
Collapse
No announcement yet.
advice code never entered when using cglib Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • advice code never entered when using cglib

    I have an integration test in which I attempt to add advice to a bean in the ApplicationContext. The body of the advice is never entered if I'm running with cglib proxies, but everything works fine if I'm using JDKProxies.

    Here's how I add the advice:
    Code:
    		  ActivityDAO activityDAO = (ActivityDAO) 
    		     (new BeanLocatorImpl()).getBean(BeanNames.ACTIVITY_DAO);	
         	Advised proxy = (Advised) activityDAO;
         	System.out.println("Old advised count = " + proxy.getAdvisors().length);
         	NameMatchMethodPointcutAdvisor advisor = 
         		new NameMatchMethodPointcutAdvisor(new CauseNullPointerException());
         	advisor.setMappedName("insert");
         	proxy.addAdvisor(advisor);
         	System.out.println("New advised count = " + proxy.getAdvisors().length);
    Whether I'm running with cglib or jdkproxies, the printlns indicate that the advice has been successfully added.

    Here's the part of my applicationContext that controlls default values for my application's FactoryBeans:
    Code:
    <bean id="baseProxy"  abstract="true" 
             class="org.springframework.beans.factory.FactoryBean"> 
    		<property name="frozen"><value>$&#123;spring.aop.advice.frozen&#125;</value></property> 
          <property name="optimize"><value>$&#123;spring.aop.doCGLibProxies&#125;</value></property> 	
          <property name="opaque"><value>$&#123;spring.aop.opaqueProxies&#125;</value></property>    
     </bean>
    Here's the relevant snippet from the properties file that sets the above values:
    Code:
    spring.aop.advice.frozen=false
    spring.aop.doCGLibProxies=true
    spring.aop.opaqueProxies=false
    All I have to do to get things to work is to change
    Code:
    spring.aop.doCGLibProxies=true
    to
    Code:
    spring.aop.doCGLibProxies=false
    I'm having this trouble in I'm using spring 1.1.3.

    Any help would be appreciated.

    -Chuck

  • #2
    Chuck,

    Can you raise a bug report on JIRA and asked for it to be assigned to me. If you can attach a simple test case that shows this failing it would be great.

    Rob

    Comment


    • #3
      advice code never entered when using cglib

      Thanks Rob. By the way, I love your book.

      I registered as a JIRA member, but for some reason can't get past the "Create Issue" page, even though I think I've entered every field.

      Anyway, here's the information I attempted to submit to JIRA.

      Summary: Can't add advisor to cglib proxies at runtime
      Priority: Critical
      Component/s: 1.1.3
      Assign to: You do not have permission to assign this issue, this issue will be assigned automatically
      Environment: java

      Description:
      The before() method of a MethodBeforeAdvice instance is never entered if the advice has been added to a cglib proxy at runtime. The bug may well exist for other advice types, but I haven't tested that. I've marked the affected version as 1.1.3, because that's the version I currently use, but other versions may also be affected.

      I've been told to assign this bug to Rob Harrop, but do not have the neccessary permisions to do so.

      Here are a few files, including a test case, that illustrate this problem.
      ****applicationContext.xml************************
      Code:
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
      <beans>
      
      	<bean id="simpleBean" 
      	class="org.springframework.aop.framework.ProxyFactoryBean"> 
      		<property name="frozen"><value>false</value></property> 
            	<property name="optimize"><value>true</value></property> 	
           	<property name="opaque"><value>false</value></property>   
      	    <property name="proxyInterfaces">
      			<value>bugexample.SimpleBean</value>
      		</property> 
      		<property name="target">
      			<bean class="bugexample.SimpleBeanImpl">
      			</bean>	
      		</property>	
        	</bean>    
      </beans>
      ****bugexample.SimpleBean**********************
      Code:
      package bugexample;
      
      /**
       * @author ctassoni
       */
      public interface SimpleBean &#123;
      	public void doNothing&#40;&#41;;
      &#125;
      ****bugexample.SimpleBeanImpl********************* *
      Code:
      package bugexample;
      
      /**
       * @author ctassoni
       */
      public class SimpleBeanImpl implements SimpleBean &#123;
      
      	public SimpleBeanImpl&#40;&#41;&#123;
      	&#125;
      
      	public void doNothing&#40;&#41;&#123;
      	&#125;
      &#125;
      ****bugexample.AddAdvisorTest********************* *
      Code:
      package bugexample;
      
      import java.lang.reflect.Method;
      
      import junit.framework.Assert;
      import junit.framework.TestCase;
      
      import org.springframework.aop.MethodBeforeAdvice;
      import org.springframework.aop.framework.Advised;
      import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      /**
       * @author ctassoni
       */
      public class AddAdvisorTest extends TestCase &#123;
      
      	public void testAddAdvisor&#40;&#41;&#123;
      		ApplicationContext ctx = new ClassPathXmlApplicationContext&#40;"applicationContext.xml"&#41;;
      		SimpleBean simpleBean = &#40;SimpleBean&#41; ctx.getBean&#40;"simpleBean"&#41;;
      		Advised proxy = &#40;Advised&#41; simpleBean;
      		
      	  	NameMatchMethodPointcutAdvisor advisor = 
           		new NameMatchMethodPointcutAdvisor&#40;new MakeRuntimeExceptionBefore&#40;&#41;&#41;;
           	advisor.setMappedName&#40;"doNothing"&#41;;
           	proxy.addAdvisor&#40;advisor&#41;;
           	try&#123;
           		simpleBean.doNothing&#40;&#41;;
           		Assert.fail&#40;"Advice body was not entered or else" +
           				" \ncalling simpleBean.doNothing would cause an exception.  This test fails when" +
           				" \napplicationContext.xml uses cglib proxy like so&#58; " +
           				" \n<property name=\"optimize\"><value>true</value></property>" +
           				" \nbut succeeds when applicationContext.xml uses jdkProxy&#58;" +
           				" \n<property name=\"optimize\"><value>false</value></property>" &#41;;
           	&#125;catch&#40;RuntimeException e&#41;&#123;
           	&#125;
      	&#125;
      	
      	class MakeRuntimeExceptionBefore implements MethodBeforeAdvice&#123;
      		public void before&#40;Method method, Object&#91;&#93; args, Object target&#41; throws Throwable &#123;
      			throw new RuntimeException&#40;"Advice body has been entered"&#41;;
      		&#125;
      		
      	&#125;
      &#125;

      Comment


      • #4
        I tried out the test code shown below and it passed fine, showing that the dynamically added advice was invoked. I ran this test using Spring 1.1.3. Can you try it out on your machine?

        Code:
        package org.springframework.aop;
        
        import junit.framework.TestCase;
        import org.springframework.aop.framework.Advised;
        import org.springframework.aop.framework.ProxyFactory;
        import org.springframework.aop.support.AopUtils;
        import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
        
        import java.lang.reflect.Method;
        
        /**
         * @author robh
         */
        public class FrozenTest extends TestCase &#123;
        
            public void testFrozenProxy&#40;&#41; &#123;
                FrozenTestBean tb = new FrozenTestBean&#40;&#41;;
        
                CountingAdvice before = new CountingAdvice&#40;&#41;;
                CountingAdvice after = new CountingAdvice&#40;&#41;;
        
                NameMatchMethodPointcutAdvisor beforeAdvisor = new NameMatchMethodPointcutAdvisor&#40;before&#41;;
                beforeAdvisor.setMappedName&#40;"getAge"&#41;;
        
                NameMatchMethodPointcutAdvisor afterAdvisor = new NameMatchMethodPointcutAdvisor&#40;after&#41;;
                afterAdvisor.setMappedName&#40;"getAge"&#41;;
        
                ProxyFactory pf = new ProxyFactory&#40;&#41;;
                pf.setTarget&#40;tb&#41;;
                pf.addAdvisor&#40;beforeAdvisor&#41;;
                pf.setFrozen&#40;false&#41;;
                pf.setOpaque&#40;false&#41;;
        
                FrozenTestBean proxy = &#40;FrozenTestBean&#41; pf.getProxy&#40;&#41;;
                assertTrue&#40;"Not a CGLIB proxy", AopUtils.isCglibProxy&#40;proxy&#41;&#41;;
        
                Advised advised = &#40;Advised&#41; proxy;
        
                assertEquals&#40;0, before.count&#41;;
                proxy.getAge&#40;&#41;;
                assertEquals&#40;1, before.count&#41;;
        
                advised.addAdvisor&#40;afterAdvisor&#41;;
        
                assertEquals&#40;0, after.count&#41;;
                proxy.getAge&#40;&#41;;
                assertEquals&#40;"Dynamic advise not invoked", 1, after.count&#41;;
                assertEquals&#40;2, before.count&#41;;
        
            &#125;
        
            public static class CountingAdvice implements MethodBeforeAdvice &#123;
        
                private int count = 0;
        
                public void before&#40;Method method, Object&#91;&#93; objects, Object o&#41; throws Throwable &#123;
                    count++;
                &#125;
            &#125;
        
            public static class FrozenTestBean &#123;
        
                public int getAge&#40;&#41; &#123;
                    return 100;
                &#125;
            &#125;
        &#125;
        Regards,

        Rob

        Comment


        • #5
          advice code never entered when using cglib

          Your test runs fine on my machine. Just speculating, but one difference between the two tests is that my test gets a bean from the ApplicationContext.

          Does my test fail on your machine?

          It might be a bit of a bother for you to create a directory structure and paste in all four files that my test requires. If you'd like, you can email me at [email protected], and I'll send you a zip.

          -Chuck

          Comment


          • #6
            advice code never entered when using cglib

            Your test runs fine on my machine. Just speculating, but one difference between the two tests is that my test gets a bean from the ApplicationContext.

            Does my test fail on your machine?

            It might be a bit of a bother for you to create a directory structure and paste in all four files that my test requires. If you'd like, you can email me at [email protected], and I'll send you a zip.

            -Chuck

            Comment

            Working...
            X