Maven vs. AspectJ - Example? - java

MY aspect works great from Eclipse with AspectJ plugin, however if I try to use it with Maven I get .... nothing.
I tried this http://mojo.codehaus.org/aspectj-maven-plugin/includeExclude.html
I add loggin in my aspect and I try to test it with junit test, but when I run
mvn clean
mvn test
I get...
[INFO] [aspectj:compile {execution: default}]
But i dont see logging in test
If I do compiling in Eclipse it works find, but Id like it to be IDE Independent(so I could use it with Hudson)
P.S. I use .aj file for Aspect
I tried to Google it, but I cant find any working example.

Without seeing your POM it's hard to say, one thing to check is that Maven expects your aspects to be under src/main/aspect rather than src/main/java by default.
You also need to ensure the aspectj runtime library is on your classpath (in Eclipse it is included by the AJDT classpath container.
For example (from the plugin documentation):
<project>
...
<dependencies>
...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.2</version>
</dependency>
...
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
<goal>test-compile</goal> <!-- use this goal to weave all your test classes -->
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
<build>
...
</project>
If neither of these work, can you post your pom contents? It might help to identify the problem.

Related

Java: Can't find symbol: class name, when the class name in one of two packages with the same name [duplicate]

I use maven to build a multi module project. My module 2 depends on Module 1 src at compile scope and module 1 tests in test scope.
Module 2 -
<dependency>
<groupId>blah</groupId>
<artifactId>MODULE1</artifactId>
<version>blah</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
This works fine. Say my module 3 depends on Module1 src and tests at compile time.
Module 3 -
<dependency>
<groupId>blah</groupId>
<artifactId>MODULE1</artifactId>
<version>blah</version>
<classifier>tests</classifier>
<scope>compile</scope>
</dependency>
When I run mvn clean install, my build runs till module 3, fails at module 3 as it couldn't resolve the module 1 test dependency. Then I do a mvn install on module 3 alone, go back and run mvn install on my parent pom to make it build. How can I fix this?
I have a doubt about what you are trying to do but but I'll assume you want to reuse the tests that you have created for a project (module1) in another. As explained in the note at the bottom of the Guide to using attached tests:
Note that previous editions of this guide suggested to use <classifier>tests</classifier> instead of <type>test-jar</type>. While this currently works for some cases, it does not properly work during a reactor build of the test JAR module and any consumer if a lifecycle phase prior to install is invoked. In such a scenario, Maven will not resolve the test JAR from the output of the reactor build but from the local/remote repository. Apparently, the JAR from the repositories could be outdated or completely missing, causing a build failure (cf. MNG-2045).
So, first, to package up compiled tests in a JAR and deploy them for general reuse, configure the maven-jar-plugin as follows:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Then, install/deploy the test JAR artifact as usual (using mvn install or mvn deploy).
Finally, to use the test JAR, you should specify a dependency with a specified type of test-jar:
<project>
...
<dependencies>
<dependency>
<groupId>com.myco.app</groupId>
<artifactId>foo</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>
Regarding to my comment to Pascals question i think i have found a stuitable answer :
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
<phase>test-compile</phase>
</execution>
</executions>
<configuration>
<outputDirectory>${basedir}\target</outputDirectory>
</configuration>
</plugin>
</plugins>
The main difference here as you see here is the <phase> tag.
I will create the test-jar and it will be available in the compile phase of the tests and not only after the package phase.
Works for me.

How to read depedency version from properties file [duplicate]

This question already has answers here:
Reading Properties file from POM file in Maven
(2 answers)
Closed 6 years ago.
I have one maven project. I want to externalise maven dependancy version to external property file.
I tried with property file plugin I is not reading property file.
config.properties
springframework.version=4.2.5.RELEASE
POm.xml file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.estuate.test</groupId>
<artifactId>testPom</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>pre-clean</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>config.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
still I am gettting error message as
build.plugins.plugin[org.codehaus.mojo:properties-maven-plugin].dependencies.dependency.version' for org.springframework:spring-core:jar must be a valid version but is '${springframework.version}'
Please help me out.
When you add a plugin with a custom execution, like you do, then you must realise that it only executes in the phases you specify. You specify pre-clean phase, which is part of the clean lifecycle, and not part of the build lifecycle.
Maven is composed of lifecycles, which execute up to a given phase. A command of mvn compile actually means run the build lifecycle all phases up to and including the compile phase.
Two of the standard lifecycles are (not complete list):
clean :: pre-clean -> clean -> post-clean
build :: validate -> compile -> test -> package -> verify -> install -> deploy
The dependencies specified are probably used by the standard plugins for the compile phase, so the properties needs to be available at that time.
When you state the pre-clean phase, the properties are available when you execute mvn clean.
For the properties to be available at compile phase, you should probably bind to the validate phase instead.
Although very verbose, there is actually quite a few hints running in debug mode with mvn -X, but it may be too much to comprehend at first.
Some more information about maven lifecycles here : https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
you can use maven properties plugin which is one of the suggested way to read property files in maven projects. below is the plugin details
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>Versions.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
Version.properties file looks like
springframework.version=4.2.5.RELEASE
I think .
You should assign a Spring version to the springframework.version statement.
For example
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.1-REALESE</version>
</dependency>
then the other dependencies
<dependency>
<groupId>...framework...</groupId>
<artifactId>spring-...</artifactId>
<version>${springframework.version}</version>
</dependency>

Running spock unit tests with Maven

On a previous project I used the Spock testing framework to unit test my Java code. I found this really productive so I am trying to add Spock tests to my current project which uses Maven as its build tool (The previous project used Gradle). While I can get Maven to compile my Spock tests (using groovy-eclipse-compiler), I am unable to get Maven to run the tests.
I've made a simple example to demonstrate my problem with 2 files:
pom.xml
src/test/java/ASpec.groovy
Contents of pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.group</groupId>
<artifactId>my-artifact</artifactId>
<version>0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.0.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>0.7-groovy-2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.8.0-01</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-batch</artifactId>
<version>2.1.8-01</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
Contents of ASpec.groovy:
import spock.lang.Specification
class ASpec extends Specification {
def "Test A"(){
// Always fail
expect: false
}
}
When I execute mvn clean test (or mvn clean install) I would expect my single unit test to be run and fail. While it is compiled, Maven does not run it. Does any one know how to run a Spock unit test from Maven (or if it is possible?)
(I have not put my test in a package to keep the example simple. Also I have put my groovy code in src/test/java to avoid configuring the example to pick up source files from an additional directory, again to keep the example as simple as possible.)
This answer is purely supplemental to #PeterNiederwieser's answer. In it he mentions that you can configure the name pattern used by Surefire. Here is an example of what worked for me:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18</version>
<configuration>
<includes>
<!-- By default only files ending in 'Test' will be included, so also include support for Spock style naming convention -->
<!-- Oddly enough for Groovy files, *Spec.groovy does not work, but *Spec.java does -->
<include>**/*Test.java</include>
<include>**/*Spec.java</include>
</includes>
</configuration>
</plugin>
Source
As I mention in the comments, I'm not sure why **/*Spec.groovy didn't work, but I'm happy to be able to use the normal Spock convention here.
Maven Surefire finds test classes by their name. Either change the class name to ATest, or reconfigure the name pattern used by Surefire. The POM for the spock-example project demonstrates how to do the latter.
I had the same requirement to add Spock to my existing java web app.
I tried Peters but it did not work for me.
gmavenplus-plugin somehow (no idea) replaced my guava dependency with a very old google lib and my Spring application broke complaining about a non-existent method.
After literally maybe 2 or 3 dozen attempts, I finally was able to integrate my Spock Unit tests, and Integration tests and more importantly to isolate the compilation of the Spock groovy classes from my existing Java/Junit Spring/Hibernate application.
Of course if I had gradle it would have solved the issue...but this is a legacy project and therefore I had not the choice.
Below are the plugins I added.
Please note the Spock unit tests end with Spec.
The Spock integration tests end with IT (but most probably should be SpecIT).
I put my Spock tests under src/test/groovy.
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<!-- Without joint compilation - no dependencies between Java and Groovy (inheritance)-->
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>
<directory>${project.basedir}/src/main/java/groovy</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</source>
</sources>
<testSources>
<testSource>
<directory>${project.basedir}/src/test/groovy</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
</testSources>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<testSourceDirectory>src/test/groovy</testSourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<includes>
<include>**/*Spec.java</include>
<!-- Yes, .java extension -->
<include>**/*Test.java</include>
<!-- Just in case having "normal" JUnit tests -->
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.20</version>
<configuration>
<useFile>false</useFile>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
And here are my dependencies:
<!--Spock -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>2.4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.1-groovy-2.4</version>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.1-groovy-2.4</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy.modules.http-builder</groupId>
<artifactId>http-builder</artifactId>
<version>0.7.1</version>
</dependency>
<!--Spock mocking dependencies -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>2.6</version>
</dependency>
And just to let you know, my original POM had absolutely no explicit plugins AT ALL. So I had a very simply POM for my project. So, it should work for you.
It is a Java 1.7 project.
...and finally, just to give you some confidence that this is not a rubbish post, I did multiple tests in order to ensure the above worked:
Just build the WAR without the tests and deploy and smoke test it locally
mvn clean install -DskipTests -Dmaven.test.skip=true
Do a test compile and see if the Groovy Unit tests get compiled as well
mvn -X clean test-compile
Do a clean install without the Integration test (i made sure it was failing for this test) and see if the Groovy unit tests are run
mvn clean install -DskipITs
Just run the integration test
mvn failsafe:integration-test
I would have liked to include screenshots of the above as proof but it would have had to be censored...So, I sincerely hope this helps you, as I was going mental trying to get this working...Maven is a huge subject area. Good luck :=)
A problem I encountered is incompatible dependencies.
The spock-core dependency of course pulls in a dependency on the version of groovy it needs. But it is possible that other dependencies or plugins (I think thegmaven-plus plugin in my case) pull in a different, incompatible, version of groovy.
I fixed the problem by explicitly giving a dependency on the groovy package I wanted to use.

Error while compiling when using AspectJ compiler instead of Javac

I have a multi module project. The aspect is currently added to the "core" project. When doing a mvn clean install here it works. However trying to do a mvn clean install on parent project it fails with this error when compiling one of the other projects:
The type org.hibernate.annotations.CacheConcurrencyStrategy cannot be resolved. It is indirectly referenced from required .class files
If I add the Hibernate core dependency in that project too it works, but adding dependencies to projects that shouldn't have the dependency does not make sense - so it is not a solution. When compiling with javac it works fine.
What is the reason? And how can I fix it so I can use the AspectJ compiler without leaking dependencies to projects that shouldn't have that?
I have this configuration in the parent POM:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<complianceLevel>1.6</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Update
I just found out. Running mvn clean install fails every time. However, running mvn [clean] install one time fails. Then running mvn install without clean works. I see that the builddef.lst in the target folder is the reason why it works and fails based on whether or not you run clean. So now my question is: How do you automatically generate this file?
Parent POM-file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>core-lib</artifactId>
<name>core-lib</name>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<complianceLevel>1.6</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
</dependency>
</dependencies>
<modules>
<module>core-xyz</module>
<module>core-xyz2</module>
</modules>
</project>
Enable debug on the maven invocation to dig deeper. You should observe that the aspectj compile is only being invoked during the first maven invocation with the clean. Since the builddef.lst already exists after the first invocation, invoking without clean skips the aspectj compile.
This aspectj compile plugin behavior has been observed previously and was described here:
http://out-println.blogspot.com/2007/08/compile-time-checks-with-aspectj-part-2.html?m=1
You will need to look deeper to address the underlying issue, but as one commenter has already suggested, the aspectj compiler should only be enabled in modules that require it.
Otherwise, the additional dependencies are required for the aspectj compile, as you have already observed. I have incorporated aspectj compile into my own work without issue by restricting it to only the modules that require it.
According to the AspectJ compiler Maven plugin you could set up the argumentFileName to locate an existing builddef.lst.
So you can generate the builddef.lst and copy it to your resources folder, and instruct the AspectJ Maven plugin to use that file.

Publish test utils from maven project

I created a library in maven that can be extended by implementing some interfaces. To test the default implementation I have written some hamcrest matchers that currently live in src/test/java.
However, I think they might be useful for users of the library if they want to test their customization.
So how can I make them available? Moving them to src/main would require to make hamcrest a runtime dependency and I don't want that.
There is a way to create a test jar and install it into the repository using the command 'mvn jar:test-jar'. This jar can then be referenced by other projects using the test-jar modifier in the dependency block.
If you want to have this jar built and installed as part of your your normal 'mvn install' build add the following plugin config to your pom:
From http://maven.apache.org/guides/mini/guide-attached-tests.html
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Then other projects can reference the test jar as follows:
<dependency>
<groupId>com.myco.app</groupId>
<artifactId>foo</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
As you said, move it to src/main in a new project. Let that project only be used in a test dependency and you don't pollute your module's classpath.
It sounds like you need to move them to their own project and release it. From there you can determine in the original project what scope you'd like.

Categories