title: AOP problem running Spring unit tests
body: <p>I have a Spring web application which is configured to use JDK proxying for AOP. The AOP annotations (such as @Transactional) are declared on the interfaces, rather than the implementation classes.</p>
  
  <p>The application itself works fine, but when I run the unit tests, it seems to be attempting to use CGLIB for the AOP functionality (instead of JDK proxying). This causes the tests to fail - I've appended the stack trace below.</p>
  
  <p>I don't understand why CGLIB is being used when I run the tests, because the Spring configuration is largely the same as when the application is running. One possibly significant difference is that the test configuration uses a <a href="http://static.springframework.org/spring/docs/2.5.0/api/org/springframework/jdbc/datasource/DataSourceTransactionManager.html" rel="noreferrer">DataSourceTransactionManager</a> instead of a JTA transaction manager. The test classes themselves all extend <a href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/test/context/junit4/AbstractJUnit4SpringContextTests.html" rel="noreferrer">AbstractJUnit4SpringContextTests</a>, could it be that this class is somehow hard-wired to use CGLIB?</p>
  
  <pre><code>Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy25]: 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 $Proxy25
      at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
      at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:488)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:363)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:324)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:361)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1343)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
      ... 79 more
  Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy25
      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:201)
      ... 86 more
  </code></pre>
  
  <p><strong>EDIT: One of the commentators requested that I post the Spring configuration</strong>. I've included it below in abbreviated form (i.e. irrelevant beans and XML namespaces omitted).</p>
  
  <p><strong>spring-servlet.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans&gt;                 
      &lt;!-- ANNOTATION SUPPORT --&gt;
      &lt;!-- Include basic annotation support --&gt;
      &lt;context:annotation-config/&gt;        
  
      &lt;!-- CONTROLLERS --&gt;
      &lt;!-- Controllers, force scanning --&gt;
      &lt;context:component-scan base-package="com.onebigplanet.web.controller,com.onebigplanet.web.ws.*"/&gt;  
  
      &lt;!-- Post-processor for @Aspect annotated beans, which converts them into AOP advice --&gt;
      &lt;bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"&gt;
          &lt;property name="proxyTargetClass" value="true"/&gt;
      &lt;/bean&gt;
  
      &lt;!-- An @Aspect bean that converts exceptions thrown in POJO service implementation classes to runtime exceptions  --&gt;
      &lt;bean id="permissionAdvisor" class="com.onebigplanet.web.advisor.PermissionAdvisor"/&gt;
      &lt;bean id="businessIntelligenceAdvisor" class="com.onebigplanet.web.advisor.bi.BusinessIntelligenceAdvisor"/&gt;        
  
      &lt;!-- Finds the controllers and sets an interceptor on each one --&gt;
      &lt;bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"&gt;
          &lt;property name="interceptors"&gt;
              &lt;list&gt;
                  &lt;bean class="com.onebigplanet.web.interceptor.PortalInterceptor"/&gt;              
              &lt;/list&gt;
          &lt;/property&gt;
      &lt;/bean&gt; 
  
      &lt;!-- METHOD HANDLER ADAPTER --&gt; 
      &lt;!-- Finds mapping of url through annotation on methods of Controller --&gt;
      &lt;bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"&gt;
          &lt;property name="cacheSeconds" value="0"/&gt;
          &lt;property name="webBindingInitializer"&gt;
              &lt;bean class="com.onebigplanet.web.binder.WebBindingInitializer"/&gt;
          &lt;/property&gt;
      &lt;/bean&gt; 
  &lt;/beans&gt;
  </code></pre>
  
  <p><strong>applicationContext-service.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans&gt; 
      &lt;!-- Declares a bunch of bean post-processors --&gt;
      &lt;context:annotation-config/&gt;
  
      &lt;context:component-scan base-package="com.onebigplanet.service.impl,com.onebigplanet.dao.impl.mysql" annotation-config="false"/&gt;    
  
      &lt;!-- Property configurer --&gt;
      &lt;bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
          &lt;property name="location" value="/WEB-INF/obp-service.properties" /&gt;
      &lt;/bean&gt; 
  
      &lt;!-- Post-processor for @Aspect annotated beans, which converts them into AOP advice --&gt;
      &lt;bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/&gt;
  
      &lt;!-- An @Aspect bean that converts exceptions thrown in service implementation classes to runtime exceptions  --&gt;
      &lt;bean id="exceptionAdvisor" class="com.onebigplanet.service.advisor.ExceptionAdvisor"/&gt;
      &lt;bean id="cachingAdvisor" class="com.onebigplanet.service.advisor.CacheAdvisor"/&gt;   
      &lt;bean id="businessIntelligenceAffiliateAdvisor" class="com.onebigplanet.service.advisor.BusinessIntelligenceAffiliateAdvisor"/&gt;
  
      &lt;!-- Writable datasource --&gt;
      &lt;jee:jndi-lookup id="dataSource" jndi-name="java:/ObpDS"/&gt;
  
      &lt;!-- ReadOnly datasource --&gt;
      &lt;jee:jndi-lookup id="readOnlyDataSource" jndi-name="java:/ObpReadOnlyDS"/&gt;  
  
      &lt;!-- Map the transaction manager to allow easy lookup of a UserTransaction --&gt;
      &lt;bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/&gt;
  
      &lt;!-- Annotation driven transaction management --&gt;
      &lt;tx:annotation-driven transaction-manager="transactionManager"/&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p><strong>applicationContext-test.xml</strong> This is only included when running the unit tests. It's purpose is to overwrite some of the beans declared in the other config files.</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans&gt;         
      &lt;!-- Overwrite the property configurer bean such that it reads the test properties file instead --&gt;
      &lt;bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
          &lt;property name="location" value="/obp-test.properties"/&gt;
      &lt;/bean&gt; 
  
      &lt;!-- All DAOs should use the test datasource --&gt;
      &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"&gt;
          &lt;property name="driverClassName" value="${testDataSource.driverClassName}"/&gt;
          &lt;property name="url" value="${testDataSource.url}"/&gt;
          &lt;property name="username" value="${testDataSource.username}"/&gt;
          &lt;property name="password" value="${testDataSource.password}"/&gt;
      &lt;/bean&gt;
  
      &lt;bean id="readOnlyDataSource" class="org.apache.commons.dbcp.BasicDataSource"&gt;
          &lt;property name="driverClassName" value="${testDataSource.driverClassName}"/&gt;
          &lt;property name="url" value="${testDataSource.url}"/&gt;
          &lt;property name="username" value="${testDataSource.username}"/&gt;
          &lt;property name="password" value="${testDataSource.password}"/&gt;
      &lt;/bean&gt;
  
      &lt;!-- 
          Overwrite the JTA transaction manager bean defined in applicationContent-service.xml with this one because
          the implementation of the former is provided by JBoss
      --&gt;
      &lt;bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
          &lt;property name="dataSource" ref="dataSource" /&gt;
      &lt;/bean&gt;
  &lt;beans&gt;
  </code></pre>