Question
Cobertura instrumentation is breaking springs autowiring in a specific case. Does anyone know how to resolve this?
Scenario
- I am running MVN 3.0.4 with the cobertura-maven-plugin version 2.5.1.
- mvn test runs without issues
- mvn compile, package etc also runs without issues.
- mvn cobertura:cobertura also ran without any issues up until the addition of 2 new features which introduced a number of new classes, including two new com.mycompany.executor executor classes. (Example: MyHappyExecutor and MySadExecutor was added in addition to the existing MyExecutor)
- Excluding MyExecutor from the cobertura instrumentation process seems to fix autowiring
- Checking the spring autowiring output confirms that the correct beans are getting autowired.
Point of failure
Autowiring fails when attempting to autowire the instrumented version of myExecutor in myService. This worked fine before adding MyHappyExecutor and MySadExecutor. MyHappyExecutor and MySadExecutor are autowired and used in MyExecutor exclusively.
I have attached the exception output below. Please not that class and package names have been edited.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myService': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.mycompany.executor.MyExecutor com.mycompany.service.impl.MyServiceImpl.myExecutor;
nested exception is java.lang.IllegalArgumentException: Can not set com.mycompany.executor.MyExecutor field com.mycompany.service.impl.MyServiceImpl.myExecutor to $Proxy20
Conclusion
Something in the Cobertura instrumentation process messes up Springs autowiring.
Update 1
Forcing CGLIB class proxies changes the error type to a "java.lang.NoClassDefFoundError" error. This is affects the standard test goal as well as the Cobertura goal.
<aop:config proxy-target-class="true"/>
Update 2
Here is the output from springs startup process for the 3 classes in question.
2012-11-01 16:21:51 INFO [main] Overriding bean definition for bean 'myExecutor': replacing [Generic bean: class [com.mycompany.executor.MyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] with [Generic bean: class [com.mycompany.executor.MyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] - (DefaultListableBeanFactory.java:623)
2012-11-01 16:21:51 INFO [main] Overriding bean definition for bean 'happyExecutor': replacing [Generic bean: class [com.mycompany.executor.HappyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] with [Generic bean: class [com.mycompany.executor.HappyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] - (DefaultListableBeanFactory.java:623)
2012-11-01 16:21:51 INFO [main] Overriding bean definition for bean 'sadExecutor': replacing [Generic bean: class [com.mycompany.executor.SadExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] with [Generic bean: class [com.mycompany.executor.SadExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] - (DefaultListableBeanFactory.java:623)