Compile-time aspects throwing NoSuchMethodError in Spring Boot - spring

I am getting an error when running my "compile-time-weaver" classes from Maven on a JAR file that is included in my Spring Boot 1.2.2 WAR.
So, I have a jar, ctms-components.jar, that I run my aspect (e.g., a method timing profiler) on using MAVEN. Then, Spring Boot puts it all in an embedded WAR (I'm using Tomcat). I see both the aspectj woven classes like AJC Closures(), etc. and I see the logs from Maven are weaving my classes as per my pointcuts.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<source>${compiler.version}</source>
<target>${compiler.version}</target>
<Xlint>ignore</Xlint>
<complianceLevel>${compiler.version}</complianceLevel>
<encoding>UTF-8</encoding>
<verbose>false</verbose>
<aspectLibraries>
<aspectLibrary>
<groupId>cdot.ctms</groupId>
<artifactId>ctms-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<weaveDependencies>
<weaveDependency>
<groupId>cdot.ctms</groupId>
<artifactId>ctms-components</artifactId>
</weaveDependency>
</weaveDependencies>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
Here is an excerpt from my maven log.
[INFO] Join point 'method-execution(cdot.base.DataAccessObject cdot.ctms.layer.services.comm.device.doppler.facade.DopplerFacade.getDopplerExchange())' in Type 'cdot.ctms.layer.services.comm.device.doppler.facade.DopplerFacade' (DopplerFacade.java:78) advised by around advice from 'cdot.aop.profiler.MethodTimerAspect' (ctms-aspects-2.0.0-SNAPSHOT.jar!MethodTimerAspect.class(from MethodTimerAspect.java))
[INFO] Join point 'method-execution(cdot.base.DataAccessObject cdot.ctms.layer.services.comm.device.doppler.facade.DopplerFacade.getDopplerRawDataExchange())' in Type 'cdot.ctms.layer.services.comm.device.doppler.facade.DopplerFacade' (DopplerFacade.java:84) advised by around advice from 'cdot.aop.profiler.MethodTimerAspect' (ctms-aspects-2.0.0-SNAPSHOT.jar!MethodTimerAspect.class(from MethodTimerAspect.java))
My Spring Boot WAR shows the AJC Closures are bundled in the WAR:
The ERROR I get when running the application is:
java.lang.NoSuchMethodError: cdot.aop.profiler.MethodTimerAspect.aspectOf()Lcdot/aop/profiler/MethodTimerAspect
nested exception is java.lang.NoSuchMethodError: cdot.aop.profiler.MethodTimerAspect.aspectOf()Lcdot/aop/profiler/MethodTimerAspect;
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:121)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1502)
... 87 more
I don't understand why it does compile time weaving, adds it to my Spring Boot WAR just fine, and also includes the ctms-aspects.jar, but cannot find the method on my Aspect?

The AspectJ runtime library aspectjrt.jar must be on your classpath, so it should be a Maven <dependency> not just for the AspectJ Maven Plugin but also for the Maven module as such.

Related

Jacoco + Surefire Maven plugins always show 0% coverage

I got a multi-module maven project on which i want to generate a jacoco report with the unit coverage. Currently i am using arqullian surefire and jacoco maven plugins, which both are defined in only one module. The tests run on a JBoss EAP 7.2
Although the jacoco report is generated, i always get a 0% coverage on all my test classes which are deployed as an archive org.jboss.shrinkwrap.api.spec.WebArchive on my JBoss server even though there are several methods covered by the Unit tests.
Important: Other unit tests performed without a deployment, do show some coverage on the report
Below is my maven configuration
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<skip>${skipTests}</skip>
<argLine>${surefireArgLine}</argLine>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Below my dependencies used:
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-api-maven</artifactId>
<version>3.1.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-impl-maven</artifactId>
<version>3.1.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-spi</artifactId>
<version>3.1.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.core</artifactId>
<version>0.8.5</version>
<scope>test</scope>
</dependency>
Arqulian XML
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<!-- Force the use of the Servlet 3.0 protocol with all containers, as it is the most mature -->
<defaultProtocol type="Servlet 3.0" />
<!-- Example configuration for a remote JBoss EAP 7 instance -->
<container qualifier="jboss" default="true">
<!-- If you want to use the JBOSS_HOME environment variable, just delete the jbossHome property -->
<configuration>
<!-- <property name="javaVmArguments">${jacoco.agent}</property> -->
</configuration>
</container>
</arquillian>
On one of my configurations (not the above), i remember seeing a warning that the ${jacoco.agent} was not used. So i did comment it out again.
When running the mvn clean install goal, in my console logs i see following variables set to the surefireArgLine
[INFO] --- jacoco-maven-plugin:0.8.5:prepare-agent (pre-unit-test) # alis-ejb ---
[INFO] surefireArgLine set to -javaagent:C:\\Users\\user\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.8.5\\org.jacoco.agent-0.8.5-runtime.jar=destfile=c:\\Projects\\Projectname\\ejb-module\\target\\coverage-reports\\jacoco-ut.exec
All my tests are executed normaly and i am able to generate a surefire report command with surefire-report that lists all the unit test executions. I am thinking if am missing a mvn goal for jacoco that calculates the coverage, but it looks that i am still missing something
Update 1: I start to believe that the issue is created due to the usage of Arquilian, and i should use the pre-integration-test phases instead. But not sure yet.
Update 2: I just noticed that for one of my Unit tests i see some coverage. The difference between this unit test and the rest is the one Class containing the tests of which a coverage as shown, are simple Unit tests, whereas for the rest of my Test classes on which i do not get a coverage report from Jacoco a org.jboss.shrinkwrap.api.spec.WebArchive deployment is created. Some more details on this. 90% of my tests, are of this structure. A webarchive is created and deployed on JBoss EAP 7.

How to build a project with AspectJ plugin which also has dependencies on querydsl plugin

I have Aspects defined in project A which can be referred from project B without any compilations issues because project A has project B as dependency. However project B needs AspectJ plugin so that aspects can be weaved via compilation/build.
Issue : My project B is using com.mysema.querydsl plugin to generate Q files for database entities. When I compile using AspectJ in eclipse (command clean aspectj:compile install) it does NOT auto generate these Q files and thus the compilation fails and weaving is not processed, overall build fails.
I have tried so many combinations of adding this dependency in AspectJ plugin but nothing works.
Please refer the pom part below:
<!-- AspectJ Maven Plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<dependencies>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>3.6.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<complianceLevel>1.7</complianceLevel>
<!-- <aspectLibraries>
<aspectLibrary>
<groupId>projectA.groupId</groupId>
<artifactId>projectA.artifactId</artifactId>
</aspectLibrary>
</aspectLibraries> -->
</configuration>
<executions>
<execution>
<!-- <phase>generate-sources</phase> -->
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- AspectJ Maven Plugin -->
What should be done here? I really dont want to create individual aspects in each project. All in all how to build projects with aspectj plugins which have querydsl plugin code references?

Spring #Configurable annotation with AspectJ

Can't make my project compile with Aspectj. There's an issue with Apache CXF that ResourceContext.getResource(SomeClass.class) creates a simple object not a Spring-managed one. So I would like to use weaving and #Configurable to come over this hardship. I got it to work in my test Spring Boot application (I could provide a link on the Github if needed) with the following set up using #Configurable itself and #EnableSpringConfigured:
Here is a snapshot of my pom.xml (Spring version is 4.3.3.RELEASE):
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
and the aspectj-maven-plugin plugin configuration:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<complianceLevel>1.8</complianceLevel>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
However, when I try to apply the configuration above in the real project in my company I get this weird error:
[ERROR] *path to the java file being weaving* can't determine annotations of missing type javax.transaction.Transactional
[ERROR] when weaving type *the full java class name*
[ERROR] when weaving classes
[ERROR] when weaving
[ERROR] when batch building BuildConfig[null] #Files=27 AopXmls=#0
[ERROR] [Xlint:cantFindType]
[ERROR] error at (no source information available)
My test project doesn't use #Transactional but the real one does. So I've tried to add spring-tx and persistence-api dependencies but nothing works. And the last note: the project is built successful the second time I run mvn install and unsuccessful every time I run mvn clean install.
Any help is much appreciated as I'm really stuck with this error.
Adding the following dependency to the classpath should solve the issue:
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>

How to disable Spring's JpaExceptionTranslatorAspect

I'm migrating from Spring 2.5.6 to 3.2.5. The jar spring-aspects-3.2.5 contains the new aspect JpaExceptionTranslatorAspect which translates standard JPA exceptions into Spring exceptions. It seems to be a Roo-specific aspect. This aspect gets automatically weaved into repositories (annotated with #Repository). Consequently, standard JPA exceptions are not caught anymore and the application is broken.
How can I exclude JpaExceptionTranslatorAspect from being weaved? If it can't be done, is there any other workaround? Or am I missing some piece of configuration?
I'm using AspectJ 1.7.4 and AspectJ Maven Plugin 1.4.
What I have already gathered:
Spring rejected the issue because it's a build issue
AspectJ Maven Plugin rejected the issue because the AspectJ compiler doesn't support excluding specific aspects from a library
However, I wonder if those pieces of information are up to date.
First, upgrade aspectj-maven-plugin to 1.5 and add the complianceLevel tag in the configuration of the plugin (otherwise it will try to compile with java 1.4 compliance by default).
Then you can specify the exclusion through the xmlConfigured property of the aspectj-maven-plugin. This property references a file from your local directory (i.e. where your pom.xml is)
pom.xml exemple :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<complianceLevel>${maven.compiler.target}</complianceLevel>
<xmlConfigured>myCtAspects.xml</xmlConfigured>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<showWeaveInfo>true</showWeaveInfo>
<weaveMainSourceFolder>true</weaveMainSourceFolder>
<proceedOnError>${maven.aspectj.failOnError}</proceedOnError>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<phase>process-resources</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
Then in myCtAspects.xml file, you just have to specify all the wanted aspects explicitly, including Spring Aspects. In your case:
<?xml version="1.0"?>
<aspectj>
<aspects>
<!-- Spring Aspects -->
<aspect name="org.springframework.beans.factory.aspectj.AbstractInterfaceDrivenDependencyInjectionAspect"/>
<aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
<aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect"/>
<!-- Your Application Aspects -->
</aspects>
</aspectj>
Please try to use aop-autoproxy's include proprety with some invert regexp (something like ^((?! JpaExceptionTranslatorAspect).)*$).

How do you configure aspectj maven plugin to use Java 7?

What are the appropriate configuration/versions/plugin versions for the aspectj plugin to use Java 7?
I am trying to upgrade from Java 6 to Java 7, and the aspectj compiler seems to not be compiling Java 7. I'm specifying the java source and target version as 1.7 in the plugin configuration for aspectj plugin and for the maven compiler plugin. I introduced Java7-specific syntax to my code, adding several language features such as string in switch and the diamond operator. During the build, I get errors from aspectj about the Java7 syntax. The first sign that things are going wrong is:
[INFO] --- aspectj-maven-plugin:1.4:compile (default) # site ---
[ERROR] Cannot switch on a value of type String. Only int values or enum constants are permitted
[ERROR] Cannot instantiate the type HashSet<?>
[ERROR] Syntax error on token "<", ? expected after this token
If I remove the executions section from the aspectj maven plugin so it doesn't run, and use mvn clean install, the new code compiles fine. So I think it's something misconfigured with aspectj. Here is my plugin configuration:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java-version>1.7</java-version>
<org.aspectj-version>1.6.11</org.aspectj-version>
</properties>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<complianceLevel>${java-version}</complianceLevel>
<encoding>${project.build.sourceEncoding}</encoding>
<outxml>true</outxml>
<source>${java-version}</source>
<target>${java-version}</target>
</configuration>
</plugin>
Also aspectjrt is defined as a dependency outside of the plugins section
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependencies>
I updated from 1.6.11 to 1.7.0, which has been released since I asked this question. I no longer have any aspectj/Java1.7 issues, so that resolves this question.

Resources