Note that there are some explanatory texts on larger screens.

plurals
  1. POAOP problem running Spring unit tests
    primarykey
    data
    text
    <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>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload