Results 1 to 4 of 4

Thread: proxying a proxy Exception

  1. #1

    Default proxying a proxy Exception

    Hi all, I posted this in the acegi forum some time ago and I didnt get any answer, so I'm gonna try here.

    This is my question, is there a way of applaying Acegi MethodSecurityInterceptor and hibernateTransactionManger to the same class?
    In both cases the creation of a proxy is needed.

    ------------------------------------------------------------------------------------

    This is my scenario:

    I am using acegi to secure the calls to my methods, so I create I proxy for those classes with methods that I want to secure.

    Code:
    <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
      <property name="interceptorNames">
        <list><value>methodSecurityInterceptor</value></list>
      </property>
      <property name="beanNames">
        <list><value>targetObjectName</value></list>
      </property>
      <property name="proxyTargetClass" value="true"/>
    </bean>
    Now I want to apply a hibernateTransaciontionManager to those methods, so I also need another definition that creates a new proxy for those classes.

    Code:
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
          <!-- all methods starting with 'get' are read-only -->
          <tx:method name="get*" read-only="true"/>
          <!-- other methods use the default transaction settings (see below) -->
          <tx:method name="*"/>
        </tx:attributes>
      </tx:advice>
      
      <!-- ensure that the above transactional advice runs for any execution
          of an operation defined by the FooService interface -->
      <aop:config>
        <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
      </aop:config>

    The problem is that the second time , Spring is trying to create a proxy of a proxy, so I get the following exception.

    Code:
    org.springframework.aop.framework.AopConfigException: Couldn't generate CGLIB subclass of class [class $Proxy2]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy2
    Caused by: 
    java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy2
    	at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
    	at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    	at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    	at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:215)
    	at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    	at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
    	at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:200)
    	at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:145)
    	at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:72)
    Does anyone know any workaround for this? Thanks.
    We all learn best the things that we have discovered ourselves

    http://javier-rivas.blogspot.com/

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    CGLIB proxies are final, so cannot be proxied again.

    Next to that WHY have a BeanNameAutoProxyCreator and a AOP config block. If you remove the BeanNameAutoProxyCreator and replace it with another line in your AOP config it works....

    Code:
    <aop:config>
      <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
      <aop:advisor advice-ref="methodSecurityInterceptor" pointcut-ref="fooServiceOperation" id="security"/>
      <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation" id="transactions"/>
    </aop:config>
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3

    Default

    First of all thank you very much, I think you have given me a nice idea. I'll try to give it a try on monday.

    -------

    Sorry, the code I wrote for the acegi example isn't quite right.

    The idea here, is that I first query the database, read the classes (services) with methods that have been set as secure, and for those classes I create proxies using an extension of "BeanNameAutoProxyCreator"

    Acegi configuration:

    Code:
    <bean id="autoProxyCreator" init-method="init" 
              class="com.polarlake.pl4edm.acegi.SecurityBeanNameAutoProxyCreator">
    	<property name="interceptorNames">
    		<list><value>securityInterceptor</value></list>
    	</property>
    	 <property name="proxyTargetClass" value="true"/>
    	<property name="pojoBaseDao" ref="pojoBaseDao"/>
    </bean>
    And the init method:

    Code:
    public void init() throws ClassNotFoundException {
    		
    	HibernateTemplate hb = (HibernateTemplate)pojoBaseDao.getTemplate();		
    	List list =  hb.find("select distinct method.className from SecureMethodBean method");
    	List beanNames = new ArrayList();
    	Iterator it= list.iterator();
    		
    	while(it.hasNext() ){
    		String className = (String)it.next();			
    		String[] names = context.getBeanNamesForType(Class.forName(className));			
    		for(int i=0;i<names.length;i++)	
    			beanNames.add(names[i]);			
    	}		
    		
    	if (list.size() > 0) {
    		setBeanNames((String[]) beanNames.toArray(new String[list.size()]));
    	}
    }
    The reason for that was that I only wanted to create proxies when needed, but maybe I can create proxies for all of them, and the same proxy can be shared by acegi and the transaction manager.
    We all learn best the things that we have discovered ourselves

    http://javier-rivas.blogspot.com/

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    Assuming you have security configured also on your service level I don't see the use of your setup. Proxies for all services are already created (due to the transcation setup), so adding another (optional) proxy layer is imho more overkill then adding a second (optional due to the pointcut) advisor....
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Posting Permissions

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