0

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

kriegaex
  • 63,017
  • 15
  • 111
  • 202
amportugal
  • 124
  • 1
  • 12
  • This is pretty complex. I am an experienced AspectJ user, but never tried combining it with a code coverage tool. In order to see what you are doing and reproduce the problem I will need your [MCVE](http://stackoverflow.com/help/mcve) on GitHub so I can see for myself and play around with it. – kriegaex Jun 10 '18 at 04:42
  • @kriegaex here is the sample code (MCVE) -> https://github.com/amportugal/aspectj-with-clover-instr The `clover-maven-plugin` and `clover-aspectj-compiler` plugins are commented, so feel free to remove the comment and test as you please. Note: as in the `pom.xml` the instrumentation goal of Clover is executed on the veify phase. Thank you. – amportugal Jun 20 '18 at 08:52
  • In your project I see AspectJ Maven plugin, not Clover AspectJ plugin. What the former does I already know because I use it all the time. What is the latter supposed to do and why is it found here in your question but not in your GitHub project? – kriegaex Jun 21 '18 at 11:19
  • It is a wrapper for AspectJ compiler which allows code instrumentation using OpenClover, as I stated. I seem to have forgotten to include it in that project. I'm going to push. Anyway, I think it's necessary, but I'm not sure if it should replace AspectJ Maven plugin or work along with it. There's just not enough documentation about it. – amportugal Jun 21 '18 at 11:24
  • It is not meant to be run from Maven, it is not really a plugin, just contains an AspectJ compiler wrapper. What is your goal? Just to compile your application classes correctly and measure their test coverage? Or also somehow measure aspect code coverage? Because if you just want to get it running, I already got that in cloned project with AspectJ Maven. You only have to configure exclusions for aspect classes in the Clover plugin because it tries to instrument `@Pointcut` methods which should have an empty method body, which the AspectJ compiler does not like. You can also inline pointcuts. – kriegaex Jun 21 '18 at 11:42
  • I want to compile application classes, and then measure their test coverage. Clover first instruments classes (in a fork fashion; notice the tests are run twice) and then generates a report. Also, just for the sake of getting it to run, I tried to exclude the aspect classes on the Clover plugin and it didn't work anyway. – amportugal Jun 21 '18 at 12:21
  • 1
    Have you seen my pull request on GitHub? After your latest change it does not merge cleanly anymore, you can just remove the Clover AspectJ thing you inserted before you merge, or you resolve the merge conflict manually. – kriegaex Jun 21 '18 at 13:27
  • Two things: why `useIncrementalCompilation` flag?And why the `compile`, `test-compile` goals on `process-sources`? – amportugal Jun 21 '18 at 14:35
  • I will explain in answer here after you confirm that it solves your problem. First I would like to know if that solution is what you needed and it was worth while answering the question. – kriegaex Jun 22 '18 at 00:49
  • Yes, it solved my problem! Thank you very much! – amportugal Jun 22 '18 at 07:57
  • Okay, I explained everything in my answer. Please read until the end, I found another solution which I like even better than the one with excluding aspects manually. – kriegaex Jun 23 '18 at 01:36

1 Answers1

1

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.

kriegaex
  • 63,017
  • 15
  • 111
  • 202