OpenClover - Getting to work with AspectJ - java

I'm trying to use Openclover with a project that uses AspectJ and that instruments aspects into its code.
The pom.xml has these dependencies with relation to AspectJ:
...
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
And these plugins:
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.openclover</groupId>
<artifactId>clover-aspectj-compiler</artifactId>
<version>1.0.0</version>
</plugin>
<plugin>
<groupId>org.openclover</groupId>
<artifactId>clover-maven-plugin</artifactId>
<version>4.2.0</version>
<executions>
<execution>
<id>clover</id>
<phase>verify</phase>
<goals>
<goal>instrument</goal>
<goal>clover</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
I'm using two plugins to do this: clover-maven-plugin which is a code coverage tool and clover-aspectj-compiler, a wrapper for AspectJ compiler which allows code instrumentation using OpenClover.
The errors I get are the following:
[ERROR] QueryAspect.java:48:0::0 The type QueryAspect is already defined
[ERROR] LogAspect.java:35:0::0 The type LogAspect is already defined
The documentation about this is just too little (or better, none) and I can't seem to make AspectJ work with OpenClover, and there isn't much help on the web.
Thank you

As discussed in our comments, you can just use AspectJ Maven instead of Clover AspectJ. You just need to take a few precautions in order to get it to work:
I like to put AspectJ Maven executions into the process-sources phase in order to make sure the AspectJ compiler kicks in before the normal Java compiler kicked off by Maven Compiler plugin. You could also deactivate Maven Compiler instead as Ajc is a full replacement for Javac. Actually that phase used to be the default in older plugin versions, but it has been changed long ago, which is also mentioned in an answer on SO. See also MASPECTJ-13 for why it was changed and MASPECTJ-92 for why the change was a bad idea.
There is a problem in Maven Compiler, namely the switch useIncrementalCompilation seems to have reversed logic. This is why you need to set it to false in order to make it work. Otherwise it tries to recompile stuff already compiled by AspectJ, breaking aspect weaving. See MCOMPILER-209 and MCOMPILER-194, I explained the problem and its solution there in my posts.
Now the only issue actually related to OpenClover (OC): AspectJ (AJ) does not know anything about OC adding source code to each method in order to enable code coverage. Unfortunately OC also does not know about AJ and also adds code to annotation-style pointcuts defined as empty methods with a #Pointcut annotation. As OC needs to do its magic before AJ compiles, the AJ compiler complains about unexpected code found in the pointcut and stops compilation with an error. There are at least two ways to avoid that:
You can either inline all pointcuts into the respective #Before, #After, #Around etc. advices using them, which usually works, but is not always an option in cases where you need argument binding in pointcuts in order to implement a wormhole pattern like execution(pointcutA()) && cflow(execution(pointcutB(myArgument))).
Or you can exclude all aspects from OC instrumentation, which is easiest if they reside in one package where there are no other Java classes which need to be instrumented. Then you can use a simple exclusion like in your case <exclude>codeaspects/**</exclude>. This is what I was doing in my pull request when fixing your project.
The easiest way is to just rename all aspects from *.java to *.aj, which is the canonical way of naming them anyway. I just tried in your project, and it works beautifully. AspectJ Maven looks for those files anyway, but OC will ignore them, not even calculating their lines of code for missing coverage. You can also get rid of the <exclude> mentioned above, see this commit.
Maybe all of this is automatically taken care of by Clover AspectJ, I never tried. Maybe the author of that compiler wrapper should actually explain what it does and how it works in the documentation, especially how to use it with Maven. Otherwise it does not make much sense to use it.

Related

Cannot remove java annotation processor from maven project

I'm about to refactor my dirty annotation processor. Therefore I wanted to create a new one to extract some responsibilities from the old one.
old: com.company.coma.shared.annotation.ComaToolAnnotationProcessor
new: com.company.coma.shared.annotation.ToolProcessor
Now I have removed the old one from the Configuration in my pom.xml
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<generatedSourcesDirectory>
${project.build.directory}/generated-sources/
</generatedSourcesDirectory>
<annotationProcessors>
<annotationProcessor>
com.company.coma.shared.annotation.ToolProcessor
</annotationProcessor>
<!--<annotationProcessor>-->
<!--com.company.coma.shared.annotation.ComaToolAnnotationProcessor-->
<!--</annotationProcessor>-->
</annotationProcessors>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
I also removed the ComaToolAnnotationProcessor.java file completely and rebuild the whole project afterwards.
Still this is what my clean install
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile (default-compile) on project module-foo: Compilation failure
[ERROR] Annotation processor 'com.company.coma.shared.annotation.ComaToolAnnotationProcessor' not found
What is going on here? How can it still look for this even when I removed any namings of it from the whole project?
EDIT#1: Deactivating the whole annotation processing plugin (maven-compiler) did not help either. I don't understand what is going on. It seems like I have not influence to the dependencies or configurations anymore.
Probably you have (manually or not) added the processor to your META-INF/services file. Therefore it will try to run it, and fail upon not finding the class specified. I believe removing the reference might fix the problem :)
I found the problem. I renamed one of my parent modules lately. But the submodules which actually contained the files to be processed still referred to the old parent artifact. That way all of my configuration of the thought to be new parent did not affected anything. Pretty weird since the the old parent module disappeared completely from my project structure but it surely was still available in my maven repo for sure.
I relied to much on the module-name refactoring feature of my IDE.

Maven un-ban a dependency (in order to use a library)?

We have a bill of material for all our projects that banned a certain dependency in the parent pom.xml. Now we need to use another library that uses that dependency. I can make an exclusion to exclude that banned dependency to compile. However, that makes the library throw a java.lang.NoClassDefFoundError. Given that we do not want to remove the ban in the parent pom, is there a way that I can bring it in for just the library?
Accordind to the documentation you could use includes for that:
includes - a list of artifacts to include. These are exceptions to the excludes. It is meant to allow wide exclusion rules with wildcards and fine tune using includes. If nothing has been excluded, then the includes have no effect. In otherwords, includes only subtract from artifacts that matched an exclude rule.
For example, to ban all xerces except xerces-api you would exclude "xerces" (groupId) and include "xerces:xerces-api"
You can skip execution of the enforcer plugin via the pom.xml in 2 ways:
Through a property:
<properties>
<enforcer.skip>true</enforcer.skip>
</properties>
Through plugin configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>

How can I tell what phase a plugin will run in?

I'm using a plugin in my pom that looks like this:
<plugin>
<groupId>org.codehaus.enunciate</groupId>
<artifactId>maven-enunciate-plugin</artifactId>
<!-- check for the latest version -->
<version>1.27</version>
<executions>
<execution>
<goals>
<goal>docs</goal>
</goals>
<configuration>
<docsDir>${project.build.directory}/docs</docsDir>
</configuration>
</execution>
</executions>
</plugin>
And I'm wondering, if I run package will this plugin run or is it during site or something else? Is there an easy way to tell by looking at this, or do I have to either
Read the plugin documentation
Experiment through trial and error
I'm hoping there's an easier way. I'm using intellij-idea, if that provides a means I'd be happy with that. Assuming I can't tell without one of these two methods, is it a best practice to always define the phase in the pom so that I can save myself and others time in the future?
You can let maven print out informations regarding the plugin using mavens help plugin - for enunciate simply use the following command:
mvn help:describe -Dplugin=org.codehaus.enunciate:maven-enunciate-plugin -Ddetail
It has actually 6 goals bound to different phases - goal docs will be bound to process-sources-phase
To only extract the goal you are interested in you can furthermore use the following command:
mvn help:describe -Dmojo=docs -DgroupId=org.codehaus.enunciate -DartifactId=maven-enunciate-plugin -Ddetail
You could also omit the -Ddetail part, but it won't give you then any information on the phase it is running.

Maven and code metrics: check for existence of a test case for each class

Is there something that can be used in Maven to automate this kind of check? I'm seeing checkstyle and PMD but I'm not finding this feature.
Basically I'd like the build to fail if there's a class A and there's not an ATestCase. I know, it is not a strict check and can be easily bypassed by creating just the class, but at the moment that would be enough.
What ou are looking for
As Jens Piegsa pointed id out, what you are looking for is a tool that show you the test coverage, in other words the percentage of code which is used by you tests.
It allow you to see how much you code is tested, in a really more reliable way than (at least test by class).
You can use Cobertura, which well integrated in Maven: http://mojo.codehaus.org/cobertura-maven-plugin/
The way to achieve that
POM Configuration
Just put this code snippet in your pom.xml
<project>
...
<reporting>
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
</plugin>
</plugins>
</reporting>
</project>
Running coverage
And run
mvn cobertura:cobertura
Or run the report phase (binded with site generation)
mvn site:site
Adding quality Threshold
You can even add failing threshold if you want to invalidate low coverage builds
<plugin>
[...]
<configuration>
<check>
<!-- Fail if code coverage does not respects the goals -->
<haltOnFailure>true</haltOnFailure>
<!-- Per-class thresholds -->
<lineRate>80</lineRate>
<!-- Per-branch thresholds (in a if verify that if and else are covered-->
<branchRate>80</branchRate>
<!-- Project-wide thresholds -->
<totalLineRate>90</totalLineRate>
<totalBranchRate>90</totalBranchRate>
</check>
</configuration>
</plugin>
Short answer: No.
Longer answer: I once wrote a unit test to assert that all VO's had a no-args constructor, and I would think that you could use the same approach here.
Basically, iterate through Package.getPackages() (you'll need to filter out JRE packages, but assuming you're using a sensible namespace, this should be no problem). For each package gather all classes not starting or ending with Test and assert that each one has a matching test.
It's not failsafe, but close enough perhaps?
Cheers,

Ant: Weave aspects both from library and user aspects

I have a library created by myself with simple logging annotations and logger aspect.
I have several AspectJ projects where I want to reuse this library compiled into the jar.
Library is very similar to http://www.jcabi.com/ library with it's #Loggable annotation, but has some differences, main difference is that my library aspect tries to retrieve a Username if class of method marked as #Loggable implements HasUser interface (my own interface). Other differences are not so important.
I want an example of Ant script to compile both from library and project aspects.
AspectJ Ant Documentation is too complex for me because I have little experience with Ant.
Partially similar questions are hear:
aspectj: How to weave aspects from a library into user code?
iajc fails to weave aspects from a jar but succeedes from class files
I would recommend to use jcabi-maven-plugin, which weaves your .class files using AspectJ aspects from your current Maven module (in src/main/aspect) and from all its dependencies:
<plugin>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-maven-plugin</artifactId>
<version>0.7.19</version>
<executions>
<execution>
<goals>
<goal>ajc</goal>
</goals>
</execution>
</executions>
</plugin>

Categories

Resources