Announcement Announcement Module
No announcement yet.
proxying a proxy Exception Page Title Module
Move Remove Collapse
Conversation Detail Module
  • 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.

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

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
          <!-- 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="*"/>
      <!-- ensure that the above transactional advice runs for any execution
          of an operation defined by the FooService interface -->
        <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>

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

    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(
    	at net.sf.cglib.transform.TransformingClassGenerator.generateClass(
    	at net.sf.cglib.core.DefaultGeneratorStrategy.generate(
    	at net.sf.cglib.core.AbstractClassGenerator.create(
    	at net.sf.cglib.proxy.Enhancer.createHelper(
    	at net.sf.cglib.proxy.Enhancer.create(
    	at org.springframework.aop.framework.Cglib2AopProxy.getProxy(
    	at org.springframework.aop.framework.Cglib2AopProxy.getProxy(
    	at org.springframework.aop.framework.ProxyFactory.getProxy(
    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....

      <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"/>


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

      <bean id="autoProxyCreator" init-method="init" 
      	<property name="interceptorNames">
      	 <property name="proxyTargetClass" value="true"/>
      	<property name="pojoBaseDao" ref="pojoBaseDao"/>
      And the init method:

      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);			
      		String[] names = context.getBeanNamesForType(Class.forName(className));			
      		for(int i=0;i<names.length;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.


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