Results 1 to 10 of 10

Thread: Help with DefaultAdvisorAutoProxyCreator for ThrowsAdvice

  1. #1
    Join Date
    Aug 2004
    Location
    Ankara, Turkey
    Posts
    24

    Default Help with DefaultAdvisorAutoProxyCreator for ThrowsAdvice

    Hi,
    I want to define a DefaultAdvisorAutoProxyCreator, to be able to generate a database entry containing the details of an Exception. I want to define it so that, whenever an Exception is thrown, I want a row to be inserted into a table containing the details...

    Here are my definitions:
    Code:
    	<bean id="exceptionAdvice" class="util.ExceptionAdvice" >
    		<property name="userDAO"><ref local="userDAO"/></property>
    		<property name="systemDAO"><ref local="systemDAO"/></property>
    	</bean>
    
    	<bean id="exceptionAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    		<property name="advice"><ref local="exceptionAdvice"/></property>
    		<property name="patterns">
    			<list>
    				<value>.*</value>
    			</list>			
    		</property>
    	</bean>
    	
    	<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">		
    		<property name="advisorBeanNamePrefix">
    				<value>exceptionAdv</value>			
    		</property>
    		<property name="usePrefix">
    				<value>true</value>			
    		</property>
    	</bean>
    Here is my ExceptionAdvice:
    Code:
    public class ExceptionAdvice implements ThrowsAdvice&#123;
    	private SystemDAO systemDAO = null;
    	private UserDAO userDAO = null;
    
    	public void setUserDAO&#40;UserDAO userDao&#41; &#123;
            this.userDAO = userDao;
        &#125;
    	public void setSystemDAO&#40;SystemDAO systemDao&#41; &#123;
            this.systemDAO = systemDao;
        &#125;
    
    	public void afterThrowing&#40;Method m,Object&#91;&#93; args,Object target,Exception ex&#41;&#123;
    		ApplicationErrorLog ael=new ApplicationErrorLog&#40;&#41;;
    		Timestamp now = new Timestamp&#40;System.currentTimeMillis&#40;&#41;&#41;;
    		ael.setCreatedTime&#40;now&#41;;
    		
    		ael.setCreatedUser&#40;userDAO.retrieveUserByUserName&#40;"admin"&#41;&#41;;
    		ael.setDescription&#40;"Method&#58;"+m+" Exception&#58;"+ex&#41;;
    		ael.setErrorNumber&#40;"111"&#41;;		
    		systemDAO.saveApplicationErrorLog&#40;ael&#41;;
    	&#125;
    &#125;
    I get the following Exception when I try to run this:
    Code:
    Exception in constructor&#58; testCreateAndDeleteUser &#40;org.springframework.beans.factory.BeanCreationException&#58; Error creating bean with name 'userManagerFacade' defined in class path resource &#91;applicationContext.xml&#93;&#58; Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException&#58; Unexpected AOP exception; nested exception is java.lang.IllegalArgumentException&#58; Cannot subclass final class class $Proxy3
    org.springframework.aop.framework.AopConfigException&#58; Unexpected AOP exception; nested exception is java.lang.IllegalArgumentException&#58; Cannot subclass final class class $Proxy3
    java.lang.IllegalArgumentException&#58; Cannot subclass final class class $Proxy3
    	at net.sf.cglib.proxy.Enhancer.generateClass&#40;Enhancer.java&#58;448&#41;
    	at net.sf.cglib.core.DefaultGeneratorStrategy.generate&#40;DefaultGeneratorStrategy.java&#58;63&#41;
    	at net.sf.cglib.core.AbstractClassGenerator.create&#40;AbstractClassGenerator.java&#58;192&#41;
    	at net.sf.cglib.proxy.Enhancer.createHelper&#40;Enhancer.java&#58;406&#41;
    	at net.sf.cglib.proxy.Enhancer.create&#40;Enhancer.java&#58;318&#41;
    	at org.springframework.aop.framework.Cglib2AopProxy.getProxy&#40;Cglib2AopProxy.java&#58;240&#41;
    	at org.springframework.aop.framework.Cglib2AopProxy.getProxy&#40;Cglib2AopProxy.java&#58;213&#41;
    	at org.springframework.aop.framework.ProxyFactoryBean.getSingletonInstance&#40;ProxyFactoryBean.java&#58;210&#41;
    	at org.springframework.aop.framework.ProxyFactoryBean.setBeanFactory&#40;ProxyFactoryBean.java&#58;177&#41;
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean&#40;AbstractAutowireCapableBeanFactory.java&#58;245&#41;
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean&#40;AbstractAutowireCapableBeanFactory.java&#58;177&#41;
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean&#40;AbstractBeanFactory.java&#58;159&#41;
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons&#40;DefaultListableBeanFactory.java&#58;177&#41;
    	at org.springframework.context.support.AbstractApplicationContext.refresh&#40;AbstractApplicationContext.java&#58;268&#41;
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>&#40;ClassPathXmlApplicationContext.java&#58;68&#41;
    	at service.BaseServiceTestCase.<init>&#40;BaseServiceTestCase.java&#58;14&#41;
    	at service.UserManagerFacadeTest.<init>&#40;UserManagerFacadeTest.java&#58;12&#41;
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance0&#40;Native Method&#41;
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance&#40;NativeConstructorAccessorImpl.java&#58;39&#41;
    	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance&#40;DelegatingConstructorAccessorImpl.java&#58;27&#41;
    	at java.lang.reflect.Constructor.newInstance&#40;Constructor.java&#58;274&#41;
    	at service.UserManagerFacadeTest.main&#40;UserManagerFacadeTest.java&#58;69&#41;
    &#41;
    	at service.UserManagerFacadeTest.main&#40;UserManagerFacadeTest.java&#58;69&#41;
    It complains about the bean 'userManagerFacade' , so here is the bean definition:
    Code:
    	<bean id="FacadeTemplate" lazy-init="true" 
    		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager"><ref local="transactionManager"/></property> 
    		<property name="transactionAttributes"> 
    			<props> 
    				<prop key="update_*">PROPAGATION_REQUIRED</prop> 
    				<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop> 
    			</props> 
    		</property>	
    	</bean>
    		
    	<bean id="userManagerFacade" parent="FacadeTemplate" class="org.springframework.aop.framework.ProxyFactoryBean"> 
    		<property name="target"><ref local="userManagerFacadeTarget"/></property>
    		<property name="interceptorNames">
    			<list>
    				<value>securityAdvisor</value>
    			</list>
    		</property> 
    	</bean>	
    	
    	<bean id="userManagerFacadeTarget" class="service.impl.UserManagerFacadeImpl"> 
    		<property name="userDAO"><ref local="userDAO"/></property>
    		<property name="systemDAO"><ref local="systemDAO"/></property>
    	</bean>
    What can be the problem?
    Thanks a lot, regards,
    Turgay Zengin

  2. #2
    Join Date
    Aug 2004
    Location
    San Mateo, CA
    Posts
    1,265

    Default

    It looks like one of the classes you're trying to advise is final. CGLIB generates a subclass at runtime to apply interception: it can't do this if a class is final.
    Rod Johnson - GM, SpringSource Division, VMware
    http://www.springsource.com
    Spring From the Source

  3. #3
    Join Date
    Aug 2004
    Location
    Ankara, Turkey
    Posts
    24

    Default

    Thanks Rod,
    But I have no final classes.

    I suspect that the bean 'userManagerFacadeTarget' is causing the problem. I get the exception after the following:
    Code:
    DEBUG - AbstractAutowireCapableBeanFactory.destroyBean&#40;849&#41; | Applying DestructionAwareBeanPostProcessors to bean with name 'userManagerFacadeTarget'
    Probably there is an error with this bean definition, but I can't figure out how to fix it: (All configuration is in the first post)
    Code:
    <bean id="userManagerFacade" parent="FacadeTemplate" class="org.springframework.aop.framework.ProxyFactoryBean">
    Can I use both "parent" and "class" in the same bean definition?

    Regards,
    Turgay Zengin

  4. #4
    Join Date
    Aug 2004
    Location
    Ankara, Turkey
    Posts
    24

    Default Solved

    While playing with the context definition, I made it work, but don't know why it works now. Looks like the order of definitions are important when using parent="a template" (first I define the TransactionalFacadeTemplate, then the SecureFacadeTemplate and then finally the facade bean).

    Also, there is one difference which may be the reason it works now: There is another template bean for the security advice now. The userManagerFacade bean uses this SecureFacadeTemplate bean to have security advice functionality.

    Here is the changed bean definitions:
    Code:
    	<bean id="TransactionalFacadeTemplate" lazy-init="true"
    		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager"><ref local="transactionManager"/></property> 
    		<property name="transactionAttributes"> 
    			<props> 
    				<prop key="update_*">PROPAGATION_REQUIRED</prop> 
    				<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop> 
    			</props> 
    		</property>	
    
    	</bean>
    
    	<bean id="SecureFacadeTemplate" lazy-init="true" parent="TransactionalFacadeTemplate"
    		class="org.springframework.aop.framework.ProxyFactoryBean">
    		<property name="interceptorNames">
    			<list>
    				<value>securityAdvisor</value>
    			</list>
    		</property>
    
    	</bean>
    
        <bean id="userManagerFacade" parent="SecureFacadeTemplate" >
    		<property name="proxyInterfaces"><value>service.UserManagerFacade</value></property>
    		<property name="target"><ref local="userManagerFacadeTarget"/></property>
        </bean>    
    
    	<bean id="userManagerFacadeTarget" class="service.impl.UserManagerFacadeImpl"> 
    		<property name="userDAO"><ref local="userDAO"/></property>
    		<property name="systemDAO"><ref local="systemDAO"/></property>
    	</bean>
    Now the exception advice works...

    Regards,
    Turgay Zengin

  5. #5

    Default

    It sounds like you had DefaultAdvisorAutoProxyCreator trying to proxy a proxy. The JDK's proxies are final classes, thus they cannot be proxied by CBLIB.

  6. #6
    Join Date
    Aug 2004
    Location
    Ankara, Turkey
    Posts
    24

    Default

    Thank you, that explains the exception java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy3

  7. #7
    Join Date
    Aug 2004
    Location
    San Mateo, CA
    Posts
    1,265

    Default

    It sounds like you had DefaultAdvisorAutoProxyCreator trying to proxy a proxy
    Proxying a proxy is usually a bad idea (although I've seen people doing it successfully, unintentionally) because of the additional performance overhead (not usually a problem, though) and the added depth to stack traces for debugging and analysing production problems.
    Rod Johnson - GM, SpringSource Division, VMware
    http://www.springsource.com
    Spring From the Source

  8. #8
    Join Date
    Aug 2004
    Location
    Ankara, Turkey
    Posts
    24

    Default

    So, what is the recommended way to have the same service object (my userManagerFacade in this example) to have both TransactionProxyFactoryBean functionality, and another AOP functionality (securityAdvisor in this example)?

  9. #9
    Join Date
    Aug 2004
    Location
    Montréal, Canada
    Posts
    845

    Default

    Quote Originally Posted by turgayz
    So, what is the recommended way to have the same service object (my userManagerFacade in this example) to have both TransactionProxyFactoryBean functionality, and another AOP functionality (securityAdvisor in this example)?
    You can use
    Code:
      <bean id="TransactionalFacadeTemplate" lazy-init="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager">
          <ref local="transactionManager"/>
        </property>
        <property name="transactionAttributes">
          <props>
            <prop key="update_*">PROPAGATION_REQUIRED</prop>
            <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
          </props>
        </property>
      </bean>
    
      <bean id="SecureFacadeTemplate" lazy-init="true" parent="TransactionalFacadeTemplate">
        <property name="preInterceptors">
          <list>
            <ref local="securityAdvisor"/>
          </list>
        </property>
      </bean>
    
      <bean id="userManagerFacade" parent="SecureFacadeTemplate" >
        <property name="proxyInterfaces"><value>service.UserManagerFacade</value></property>
        <property name="target">
    		  <bean id="userManagerFacadeTarget" class="service.impl.UserManagerFacadeImpl">
    		    <property name="userDAO"><ref local="userDAO"/></property>
    		    <property name="systemDAO"><ref local="systemDAO"/></property>
    		  </bean>
        </property>
      </bean>
    Omar Irbouh

    Spring Modules Team
    http://irbouh.blogspot.com/

  10. #10
    Join Date
    Aug 2004
    Location
    Ankara, Turkey
    Posts
    24

    Default

    Thank you,
    I used the part that you insert "userManagerFacadeTarget" as a nested bean. But the other part caused problems (where you set the preInterceptors). I got an exception saying:

    Code:
    testCreateAndDeleteUser&#40;service.UserManagerFacadeTest&#41;org.springframework.orm.hibernate.HibernateSystemException&#58; a different object with the same identifier value was already associated with the session&#58; 2, of class&#58; domain.User; nested exception is net.sf.hibernate.NonUniqueObjectException&#58; a different object with the same identifier value was already associated with the session&#58; 2, of class&#58; domain.User
    I understood the pre-post interceptors, thank you. But I couldn't make it work that way. My config works the other way (described in post dated Sep 02, 2004 4:08 am), so I'll use that.

    Regards,
    Turgay Zengin

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •