6

I have configured Spring 3.0.6 with AspectJ LTW using spring-instrument.jar and:

<context:load-time-weaver aspectj-weaving="on" weaver-class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />

When removing CGLIB from dependencies, I'm getting the following exception even after MyBean is created (and its @PostConstruct is run):

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'crawlItemService' defined in file [/path/to/project/foo/bar/MyBean.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:435)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:409)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:541)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:147)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:297)
    ... 72 more
Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
    at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67)
    at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:476)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1426)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    ... 83 more

Does it mean that I should have CGLIB even in existence of a load time weaver?

Mohsen
  • 3,512
  • 3
  • 38
  • 66

3 Answers3

11

After over 3 hours of investigations of the code and changing Spring bean definition XMLs, I finally found the problem. This could be found from this part of stacktrace, which I noticed after finding the solution:

at org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor.postProcessAfterInitialization(AsyncAnnotationBeanPostProcessor.java:126)

Based on the note here, I changed all proxy-target-class attributes to false in <aop:config>, <aop:aspectj-autoproxy>, and <tx:annotation-driven>, but to no success.

Then I started removing parts of my XML definition to find which one fixes this problem. Commenting <task:annotation-driven> helped and the problem resolved. I then saw that this element has a mode attribute which I didn't specified, so its default value, proxy, is used, and so CGLIB is required. As I changed mode="aspectj" the problem resolved:

<task:annotation-driven scheduler="dataProviderScheduler" executor="dataProviderExecutor" mode="aspectj" />
Mohsen
  • 3,512
  • 3
  • 38
  • 66
  • Great discovery, +1! So have you been using `@Async` annotation somewhere? The CGLIB proxy should not be generated for classes that do not have such methods. – Tomasz Nurkiewicz Nov 18 '11 at 08:59
  • Thanks, yes I had `@Async`. CGLIB works with `@Async` if your async method is not called from another method in the same bean. (this is a known problem with CGLIB) But it works when you call your async method from another bean into which the source bean is injected. – Mohsen Nov 21 '11 at 07:51
3

No, but it is required to create AOP proxies (Cannot proxy target class). Does your class have one of:

  • @Transactional
  • @Cacheable
  • @Async
  • ...

annotations? Or maybe there is some external aspect around methods of this class? Nevertheless, AspectJ compiler should take care of weaving, AFAIR CGLIB should not be used. Can you show us your code?

In my case to correctly enable load time weaving for transaction support I had to add:

 <context:load-time-weaver/>
 <tx:annotation-driven mode="aspectj"/>
 <aop:config proxy-target-class="true"/>

Have a look at a working example.

DwB
  • 37,124
  • 11
  • 56
  • 82
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • I have @Transactional on MyBean. and also: . Is this still required to have CGLIB? – Mohsen Nov 17 '11 at 16:47
  • 1
    See my edit. Also have a quick read of my [article](http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html) about proyxing and transactions. – Tomasz Nurkiewicz Nov 17 '11 at 16:57
  • Are you sure about: . Documentation says: Attribute : proxy-target-class Are class-based (CGLIB) proxies to be created? By default, standard Java interface-based proxies are created. – Mohsen Nov 17 '11 at 17:15
  • No, I am not sure, I just copied it from a working code. Give it a try and play with a debugger. – Tomasz Nurkiewicz Nov 17 '11 at 17:39
  • This should be false for sure. See "Note" [here](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-proxying) – Mohsen Nov 17 '11 at 18:15
2

If you are using Spring APO you need to include CGLIB. There are two ways to add this to your project

  1. Download CGLIB library file and add it to your library files. http://www.java2s.com/Code/Jar/c/Downloadcglib22jar.htm
  2. Add the Maven dependency in your pom.xml file

    https://mvnrepository.com/artifact/cglib/cglib/2.2.2


<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
</dependency>
Gani
  • 422
  • 1
  • 8
  • 16