Results 1 to 3 of 3

Thread: upgrade from 2.0-M5 to 2.0: cannot subclass final proxy

  1. #1
    Join Date
    Oct 2006
    Location
    London
    Posts
    19

    Default upgrade from 2.0-M5 to 2.0: cannot subclass final proxy

    I upgraded from 2.0-M5 to 2.0 and now have some problems deploying my application on the webserver. It's a webapp using acegi security and transactions which seem to be co-operating badly now.

    The way it is configured now, all the service beans are proxied twice and CGLib is complaining that the first proxy is final and is not allowing it to create the second proxy. (See the stacktrace below.)

    It seems in the previous Spring release M5, BeanNameAutoProxyCreator for Acegi and aspectj-autoproxy were co-existing fine. The transactionality is catered for first using annotations and aspectj, and acegi is implemented using BeanNameAutoProxyCreator.

    My first question is, can you confirm that this change is expected? Do you know about this and is there an immediate work-around? If you could confirm that for the sake of my sanity and to reassure me that I haven't just mangled my Jar dependencies, I'd be grateful.

    Secondly, what course to take? I want to change the config anyway to avoid proxying the service beans twice, and I want to get rid of the annotations that are putting undesired dependencies in the service classes. I am using interfaces but the stacktrace shows CGLib is active - is there a simple, elegant approach that doesn't involve CGLib?

    Here's the stack trace:

    Code:
    ERROR web.context.ContextLoader.initWebApplicationContext() <Context initialization failed>
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityServices' defined in class path resource [applicationContext.xml]: 
    Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: 
    Couldn't generate CGLIB subclass of class [class $Proxy8]: 
    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 $Proxy8
    Caused by:
    org.springframework.aop.framework.AopConfigException: 
    Couldn't generate CGLIB subclass of class [class $Proxy8]: 
    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 $Proxy8
    Caused by:
    java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy8
            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:216)
            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:202)
            at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:147)
            at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:72)
            at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:392)
            at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:249)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBea
    nFactory.java:311)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1038)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:420)
            at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
            at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
            at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
            at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
            at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:290)
            at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:348)
            at org.springframework.web.context.support.AbstractRefreshableWebApplicationContext.refresh(AbstractRefreshableWebApplicationContext.java:156)
            at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:246)
            at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:184)
            at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49)
            at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3729)
            at org.apache.catalina.core.StandardContext.start(StandardContext.java:4187)

  2. #2
    Join Date
    Jun 2005
    Posts
    4,230

    Default

    There was a bug in 2.0 to do with auto-proxying, where double proxying was the result. You may be affected by that. I'm not sure how much of auto-proxying was involved, but I know that BeanNameAutoProxyCreator was definitely part of the problem.

    If this is the bug that has caused your problem then it is possible that Spring is trying to use Cglib to proxy a JDK Proxy, which itself was already created for your interface, as you wanted.

    I understand that the bug is fixed in the latest builds (and in 2.0.1). A workaround if you can't wait is to extend BeanNameAutoProxyCreator and override postProcessBeforeInstantiation, checking for an existing proxy with AopUtils.isAopProxy() and only calling the superclass method if it is false.
    Last edited by Dave Syer; Oct 25th, 2006 at 04:07 AM.

  3. #3
    Join Date
    Oct 2006
    Location
    London
    Posts
    19

    Default

    Thanks for the info. I think your assumption is right. I have reconfigured my transactions to use BeanNameAutoProxyCreator, instead of using the annotations method with AspectJ, and then listing the different interceptors so that I only have one proxy. (That does mean only one is created, right?)

Posting Permissions

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