Announcement Announcement Module
Collapse
No announcement yet.
proxying a proxy Exception Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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.

  • #2
    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>

    Comment


    • #3
      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.

      Comment


      • #4
        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....

        Comment

        Working...
        X