Translate

miércoles, 11 de septiembre de 2013

Error usando Junit combinado con AspectJ: AspectJAdviceParameterNameDiscoverer$AmbiguousBindingException

En nuestro proyecto J2EE hemos utilizado AspectJ para capturas las excepciones que se producen en la parte servidora en JAVA.

Es muy cómodo porque no tienes que poner bloques try....catch en todos los servicios de la aplicación para aplicar la gestión que quieras a las excepciones, de este modo tienes toda la gestión de las excepciones en un solo punto.

El problema lo tenemos a la hora de hacer los test unitarios y de integración con JUNIT ya que no se lleva nada bien el tema de que los servicios sobre los que hacemos los test. Los casos de uso que tenemos son los siguientes:

1 - Creación y ejecución de los test en Eclipse. En este caso los test pasan correctamente



2 - Ejecución de los test en Jenkins a través de un scripts (maven o ant) de compilación y ejecución de los test.

En este caso es donde nos encontramos con el problema de que la solución de la utilización de Aspecj para la gestión de excepciones no funciona porque nos devuelve el siguiente error.


--

java.lang.IllegalStateException: Failed to load ApplicationContext
 at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
 at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#0': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer$AmbiguousBindingException: Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:452)
 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
 at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:740)
 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:449)
 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
 at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
 at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
 at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
Caused by: org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer$AmbiguousBindingException: Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them
 at org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.maybeBindThisOrTargetOrArgsFromPointcutExpression(AspectJAdviceParameterNameDiscoverer.java:519)
 at org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.getParameterNames(AspectJAdviceParameterNameDiscoverer.java:264)
 at org.springframework.core.PrioritizedParameterNameDiscoverer.getParameterNames(PrioritizedParameterNameDiscoverer.java:54)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.bindArgumentsByName(AbstractAspectJAdvice.java:420)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.calculateArgumentBindings(AbstractAspectJAdvice.java:375)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvice(ReflectiveAspectJAdvisorFactory.java:218)
 at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice(InstantiationModelAwarePointcutAdvisorImpl.java:140)
 at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.<init>(InstantiationModelAwarePointcutAdvisorImpl.java:89)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisor(ReflectiveAspectJAdvisorFactory.java:134)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory$1.doWith(ReflectiveAspectJAdvisorFactory.java:74)
 at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:473)
 at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:451)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisors(ReflectiveAspectJAdvisorFactory.java:70)
 at org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors(BeanFactoryAspectJAdvisorsBuilder.java:109)
 at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:86)
 at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:107)
 at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:278)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:880)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:852)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:446)


--

La solución a este problema consiste en añadir un parámetro en la compilación de las clases en el script que se encarga de compilar las clases. El parámetro añadir es el siguiente: -g:vars

Os pongo el ejemplo de como lo añado en mi script donde todas mis clases están en las carpetas src y javatest

--
<path id="lib.path.ref">
      <fileset dir="../WebContent/WEB-INF/lib" includes="*.jar"/>
   <fileset dir="./libs" includes="*.jar"/>
</path>
<javac srcdir="../src:../javatest"
          destdir="${DirectorioBase}/WEB-INF/classes"
          classpathref="lib.path.ref"
          debug="off"
          source="1.7"
          optimize="true"
          target="1.7"
          fork="true"
   encoding="UTF8"
          includeantruntime="true">
    
                 <compilerarg value="-g:vars"/>  <!--Argumento especial para la compilación de AspectJ -->
</javac>
--

Con esto el error desaparece completamente.

Referencias:

Referencia 1 - SpringSource

Referencia 2 - epubbud