Maven2 compiler custom execution source directory and target directory - java

I want to run the maven compiler plugin in a different phase and with different sourceDirectories and destinationDirectories such that code from directories other than src/main/java and src/test/java can be used.
I thought the solution would look something like the below, where the phase I was linking it to was pre-integration-test. However the properties for testSourceDirectory and testOutputDirectory don't seem to be specified in this way as they are in the section of the POM.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile mytests</id>
<goals>
<goal>testCompile</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<testSourceDirectory>${basedir}/src/inttest/java</testSourceDirectory>
<testOutputDirectory>${basedir}/target/inttest-classes</testOutputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Is there a way to get this plug-in to compile different directories in different phases without affecting its default operation?

The source directories are set outside the compiler-plugin inside the <build> element, so this won't work.
You can use the build-helper-maven-plugin's add-source and add-test-source to specify additional source directories for your integration tests, but this will not remove the existing source dirs.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>add-it-source</id>
<phase>pre-integration-test</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/src/inttest/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
If you bind the add-test-source goal to run just before the testCompile goal, your integration tests will be included. Note you want them to be output to target/test-classes so the surefire plugin will find them.
To handle removal of the standard test sources, I wrote a small plugin to modify the model to remove existing testSource locations before adding the ones for integration tests.

After more research it is apparent this is not actually possible in Maven 2 in the way I want, a hack of some form is necessary to introduce integration tests. While you can add additional directories (as suggested by Rich Seller) there is no plugin to remove the other sources or to compile a directory separately from the main compilation.
The best solution I have found for adding integration tests is to first use the build helper plugin to add the directory inttest directory to be compiled as tests.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/inttest/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Now in order to get the integration tests to execute on the integration-test phase you need to use excludes and includes to manipulate when they get run as below. This allow any custom parameters you might want (in my case an agent being added via argline).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/itest/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>inttests</id>
<goals>
<goal>test</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<excludes><exclude>none</exclude></excludes>
<includes>
<include>**/itest/**/*Test.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>

Related

Maven - How to include single java files as sources/depedencies

I have created a multi-module project in maven which is as follows:
root/pom.xml
|________client/pom.xml
|________/src/main/java
|________/src/main/resources
|________common/pom.xml
|________/src/main/java
|________tools/pom.xml
|________/src/main/java
|________server/pom.xml
|________/src/main/java
|________/src/main/resources
I would like to compile the "client" module code which depends on ALL java classes in "common" module but on SOME java classes in the "tools" module.
Using the build-helper-maven-plugin as below, I was able to add all java source files under common/ path, but I need a way to define individual java files as sources which are under tools/.
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../common/src/main/java</source>
<!-- Adding single java files as below does not work -->
<source>../tools/log/Log.java</source>
<source>../tools/socket/SocketClient.java</source>
<!----------------------------------------------------->
</sources>
</configuration>
</execution>
</executions>
You should include module "common" and "tools" as dependency in "client"
Then you can run build in the root of project: mvn clean install - it will build all modules.
Don't try to use parts of a module as dependency. Maven does not support this and it results in brittle and hard to maintain constructions.
If you only need parts of tools, then this is a clear signal that tools is too large and you need to split it up into two modules.
Ok, based on the comments received it seems that the ideal solution is to break the modules into sub-modules and use those as dependencies. However, as this is currently a time consuming task, I am posting a quick and dirty solution on how you can include one or more java files into your build by copying the files under a new source directory, src/main/external, and then add this directory as part of your sources.
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>copy-source-java-files</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/external</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<!-- External source directory -->
<directory>../tools/src/main/java/</directory>
<includes>
<!-- Files to be copied along with their directory paths -->
<include>tools/log/Log.java</include>
<include>tools/socket/SocketClient.java</include>
<include>tools/client/reader/**</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
<source>src/main/resources</source>
<source>../common/src/main/java</source>
<!-- Here we add the source with the files copied -->
<source>src/main/external</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The output after compilation would be as follows:
root/pom.xml
|________client/pom.xml
|________/src/main/java
|________/src/main/resources
|________/src/main/external <----- This contains all external java files.

Maven calling maven plugin goal from command line

Can you tell me how to call maven surefire in command line with the following configuration ?
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<id>Custom tests</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<classesDirectory>target/generated/classes/normalCase/</classesDirectory>
<reportsDirectory>target/generated/reports/normalCase/</reportsDirectory>
</configuration>
</execution>
</executions>
</plugin>
When surefire is defined like this in my pom.xml and I execute the phase test, it work exactly how i want it to work : it tries to run my tests on the classes located in target/generated/classes/normalCase.
So I tried this command line:
mvn surefire:test -DclassesDirectory="target/generated/classes/normalCase/"
But no, it keep checking the classes in the default value directory which is "target/classes".
So how can I achieve this in command line ?
To recap the situation you have. You are generating multiple version of your source code during the build, each of those version ends up in a separate folder under target. For each of those versions, you would like to execute your unit tests with the maven-surefire-plugin. Let's consider the base directory to be target/generated/classes. That means you have multiple subdirectories target/generated/classes/version1, target/generated/classes/version2... for each version.
A possible solution would be to use the iterator-maven-plugin to iterate over all subdirectories of a folder and invoke the maven-surefire-plugin from all those subdirectories. The variable #item# holds the current item.
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>iterator-maven-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<id>iterate</id>
<phase>test</phase>
<goals>
<goal>iterator</goal>
</goals>
<configuration>
<folder>target/generated/classes</folder>
<pluginExecutors>
<pluginExecutor>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
</plugin>
<goal>test</goal>
<configuration>
<classesDirectory>target/generated/classes/#item#</classesDirectory>
<reportsDirectory>target/generated/reports/#item#</reportsDirectory>
</configuration>
</pluginExecutor>
</pluginExecutors>
</configuration>
</execution>
</executions>
</plugin>

using antlr4-maven-plugin for both main and test code

I'm working on a project in which I've got an antlr4 grammar in main code, and I'd like to add a "mini-grammar" for some tests. I'd like the generated .java files for that mini-grammar to only be available to test code. Can the antlr4-maven-plugin support this?
After some experimentation, I settled on this less-than-ideal setup:
both my main-targeted and test-targeted grammars are in src/main/resources (I realize this isn't the standard place; I set sourceDirectory to account for this)
the antrun plugin copies ${project.build.directory}/generated-sources/antlr4/**/MyTestGrammar*.java to ${project.build.directory}/generated-test-resources/antlr4
the build-helper-maven-plugin plugin adds ${project.build.directory}/generated-test-resources/antlr4 as a test source dir
This requires three plugin configurations, and that I explicitly specify which of the generated grammars are meant for tests and which are meant for main code. Is there a better way?
Save your test grammar in a subfolder of ${baseDir}/src/test/antlr4.
Then you can try and put something like this inside the build-plugins element of your POM:
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>${antlr4.plugin.version}</version>
<configuration>
<arguments>
<argument>-visitor</argument>
</arguments>
</configuration>
<executions>
<execution>
<id>antlr-4</id>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
<execution>
<id>antlr-test</id>
<configuration>
<sourceDirectory>${baseDir}/src/test/antlr4</sourceDirectory>
<outputDirectory>${baseDir}/target/generated-test-sources-antlr/antlr4</outputDirectory>
</configuration>
<phase>generate-test-sources</phase>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
</plugin>
and then add the generate sources while compiling the test classes:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${baseDir}/target/generated-test-sources-antlr/antlr4</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
You may want to adjust directories and packages names according to your needs

Exclude maven dependency for one specific unit test

I'd like to remove a dependency for a unit test. I found how to do it in this answer.
But I'd like to remove a dependency for only one specific test, not for all my tests. Is there a way to do that?
Not by using one Surefire execution.
You will have to define two executions of the Surefire plugin: one containing the full Classpath for most of the tests, and one containing the specialized Classpath for the single test that requires it.
Follow the Surefire plugin's documentation: http://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html
You'll have to create two executions, and bind them both to the test phase. Use the following example as a skeleton (you'll have to adjust the include and exclude patterns, as well as the excluded Classpath artifact):
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>full-cp</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>**/Test*.java</include>
</includes>
<excludes>
<exclude>MyFancyTest.java</exclude>
</excludes>
</configuration>
</execution>
<execution>
<id>special-cp</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>MyFancyTest.java</include>
</includes>
<classpathDependencyExcludes>
<classpathDependencyExcludes>excluded-artifact</classpathDependencyExcludes>
</classpathDependencyExcludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

Problems running JBehave with Maven

I am trying to get a JBehave story to execute in Maven it is completely ignoring the JBehave plugin. I've spent several hours using different configurations but it looks like the plugin isn't being executed at all. Any recommendations/tips would be appreciated!
All my JBehave classes live in:
src/at/java
Relevant parts of my pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/at/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<executions>
<execution>
<id>run-stories-as-embeddables</id>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/*.java</include>
</includes>
</configuration>
<goals>
<goal>run-stories-as-embeddables</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<executions>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<includes>
<include>**/*.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Best is to change the location of your test classes to src/test/java and change the name of the stories based on the documentation of JBehave.
JBehave running with maven follow the Maven rules for location of code and text artifacts.
For test scope you must put them in src/test/java and src/test/resources. For compile scopes is src/main/java and src/main/resources.
With JBehave with maven you could use two scopes (test or compile), you just need to set which one you want in the plugin configuration, so you choose where to put your artifacts. it defaults to compile.
In your case you are adding a new test source so you must set the scope to test:
see detail here.
Maybe the jbehave-maven-plugin could not find the compiled test classes (scenarios) because it looks in the wrong classpath.
Please look at your target directory and search the embeddable classes -> target/classes or target/test-classes?
To solve the problem i must set the scope of jbehave-maven-plugin to test in the configuration of my project pom.xml.
here is a example
<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<executions>
<execution>
<id>run-stories-as-embeddables</id>
<phase>integration-test</phase>
<goals>
<goal>run-stories-as-embeddables</goal>
</goals>
<configuration>
<scope>test</scope>
<includes>
<include>**/*Scenarios.java</include>
</includes>
<ignoreFailureInStories>true</ignoreFailureInStories>
<ignoreFailureInView>false</ignoreFailureInView>
</configuration>
</execution>

Categories

Resources