Where should I put interface class for Junit #Category? - maven

I'd like to define project-wide interfaces, to be used in #Category annotations, and configure Maven to exclude their annotated tests when building the whole project.
In the application project there's a test I'd like to categorize:
#Category(Integration.class)
#Test
public void testExternalResource() { ... }
The setting:
I've set up a multi-module maven project:
/container (has a pom with <modules> element)
/parent (all other modules inherit from its pom. has no source, only pom)
/util (other modules are depending on it)
/infra
/application (depending on infra and util, inherits from parent)
Being an infrastructure freak :), I'd like to configure my whole project to exclude groups in any module. So, in parent module I've defined:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<excludedGroups>com.mycompany.test.Integration</excludedGroups>
</configuration>
</plugin>
And I've put the Integration interface in the util module (in the util/src/test/java), for all modules to see:
package com.mycompany.test;
public interface Integration {}
And because it's a test-jar, I've made the right configuration for both util and application .
The error:
When running mvn clean install, I'm getting
[ERROR] Failed to execute goal org.apache.maven.plugins:
maven-surefire-plugin:2.16:test
(default-test) on project util: Execution default-test of goal
org.apache.maven.plugins:maven-surefire-plugin:2.16:test
failed: There was an error in the forked process
[ERROR] java.lang.RuntimeException:
Unable to load category: com.mycompany.test.Integration
Well, of course the class isn't available - I've crammed it in a test-jar in the first module of the project. :(
Where should I put my Integration interface so it will be available to my mvn configuration and my source code?

Create a new Maven module and put the interface under src/main/java/. Make sure junit is available as a compile time dependency (<scope>compile</scope>) - you're basically building a dependency that other tests can use. So your code that helps other tests must go into main while the tests for this go in the src/test/java, as usual.
This step feels a bit weird but think about how you would package junit itself. From the point of view of junit, it's just a normal Java library, so all its code goes into main.
When you need this module, use it as a test dependency with <scope>test</scope>

Related

Preventing non-src code module from running maven build cycle when a source file from another JVM module is run

I made a maven module that I use only to copy some files around and process them a bit. There is no java or kotlin in it, however it is a JVM-type module. For some reason though, after I did that now, the maven lifecycle runs (I think up to and including phase: package) when I try to jvm projects from other modules. Why is this happening? I just want to be able to run the MVN phases on that module manually. anyone know how to disable it for this module?
All phases are run against all modules. When you run mvn package in your root directory, it runs all the phases from Default lifecycle [1] up to package against every module that's described in your <modules>.
But phases don't do anything. They are just labels - and plugins are bound to these labels[2]. So what's done in a phase is determined by the list of plugins that are bound to that phase.
Things that you may try out:
Change packaging of your module to non-jar. Packaging determines the list of default plugins bindings. This seems to be the best option for you.
Remove the module from <modules> and run whichever plugins you need separately. Thus this module will be excluded completely from your root module.
Unbind the plugin from your module (if the plugin is inherited from the parent POM) by setting a non-existing phase to it (and all other plugins):
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>

Invoking maven plugin as a part of build lifecycle

I’m new to maven. I’m trying to integrate a plugin into my build so that it would execute automatically as part of phase execution.
Say I want to plug into clean lifecycle phase.
The mojo I’m using was annotated specifying that it should be injected into clean phase:
/**
*
* #goal clean
* #phase clean
* #requiresProject
*/
public class CleanMojo extends AbstractSCAMojo {
This mojo was installed following instructions in Using Plugin Tools Java5 Annotations.
I added plugin to my pom.xml:
<build>
<plugins>
<plugin>
<groupId>myclean.plugin</groupId>
<artifactId>myclean-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<logfile>C:/temp/clean.log</logfile>
</configuration>
</plugin>
</plugins>
</build>
In my understanding having lifecycle binding in Mojo java code eliminates the need to provide executions in build-plugins-plugin. Is that correct?
I was expecting that after invoking mvn clean configured above myclean.plugin:myclean-maven-plugin will be executed as part of the clean goal, but nothing happens besides regular maven clean procedure.
When pom is changed to specify executions myclean.plugin:myclean-maven-plugin is invoked so I’m certain mojo code doesn’t contain blocking errors – this is just a question of configuration.
There is probably something more I need to specify to make plugin executed automatically (i.e. without specifying executions), but what?
As per the documentation, you should be adding the following annotation before the class definition:
#Mojo(name = "clean", defaultPhase = LifecyclePhase.clean)
#goal and #phase are for javadocs.

How to configure Sonar and Maven multilevel modules?

I encounter issue to configure a multilevel maven modules for Sonar Analysis.
It is working fine with the following structure:
parent module
|- level 1
|- module with code to analyze
But if I add a depth to the module with code to analyze, I'm not able to configure it.
parent module
|- level 1
|- level 2
|- module with code to analyze
I tried several configurations:
with no special configuration:
I get an Can not execute SonarQube analysis: The project 'level 2' is already defined in SonarQube but not as a module of project 'level 1'. If you really want to stop directly analysing project 'level 2', please first delete it from SonarQube and then relaunch the analysis of project 'level 1'. error. I don't want to launch on level 1 because I have my integration tests at the same level, directly in parent module.
using skippedModules property on level 1 and level 2: Only the parent module is analyzed.
using includedModules by specifying "module with code to analyze": Only the parent module is analyzed.
Does someone has an idea on how to handle it? (I mean without to modifying the hierarchy folder which is really helpful for some other requirements)
Thanks by advance
I found a workaround:
- I launch mvn clean install on parent project
- then I launch sonar:sonar at 'level 2' module, I can do it because all the code source to be analyzed is under the same module.
At least it is working on my sample project but currently I didn't handle yet to make it working on my real project.
Building my Maven multi-module project is consistently working for me. I'm using SonarQube v4.3.
I placed a sonar-project.properties file at the root level of the parent Maven project.
Here's the contents:
# Root project information
sonar.projectKey=<I used the project pom's groupId + artifactId>
sonar.projectName=<can be anything>
sonar.projectVersion=<I used the project pom's version>
# Some properties that will be inherited by the modules
sonar.sources=src
In my parent project's pom, I declared this property:
<sonar.language>java</sonar.language>
Within the same pom, I declared the following:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
I'm building only the parent project, which results in the parent and all of its children getting analyzed by SonarQube. I'm using:
mvn clean install sonar:sonar
or
mvn sonar:sonar
I think that you have one module in SonarQube as a project. First, you need to remove it and then execute the new analysis.
This happen when a project already exist but in different level (project, module and so on)
This behaviour is related to this JIRA : http://jira.codehaus.org/browse/SONAR-4245
The only solution is using old version of Sonar..

What is the difference in Maven between dependency and plugin tags in pom.xml?

Created project with Spring, Hibernate & Maven. My question is what is the logic behind plugin versus dependency ?
Both plugins and dependencies are Jar files.
But the difference between them is, most of the work in maven is done using plugins; whereas dependency is just a Jar file which will be added to the classpath while executing the tasks.
For example, you use a compiler-plugin to compile the java files. You can't use compiler-plugin as a dependency since that will only add the plugin to the classpath, and will not trigger any compilation. The Jar files to be added to the classpath while compiling the file, will be specified as a dependency.
Same goes with your scenario. You have to use spring-plugin to execute some spring executables [ I'm not sure what spring-plugins are used for. I'm just taking a guess here ]. But you need dependencies to execute those executables. And Junit is tagged under dependency since it is used by surefire-plugin for executing unit-tests.
So, we can say, plugin is a Jar file which executes the task, and dependency is a Jar which provides the class files to execute the task.
Hope that answers your question!
Maven itself can be described as food processor which has many different units that can be used to accomplish different tasks. Those units are called plugins. For example, to compile your project maven uses maven-compiler-plugin, to run tests - maven-surefire-plugin and so on.
Dependency in terms of maven is a packaged piece of classes that your project depends on. It can be jar, war etc. For example, if you want to be able to write JUnit test, you'll have to use JUnit annotations and classes thus you have to declare that your project depends on JUnit.
Plugins and dependencies are very different things and these are complementary.
What plugins are ?
Plugins perform tasks for a Maven build. These are not packaged in the application.
These are the heart of Maven.
Any task executed by Maven is performed by plugins.
There are two categories of plugins : the build and the reporting plugins :
Build plugins will be executed during the build and they should be configured in the <build/> element from the POM.
Reporting plugins will be executed during the site generation and they should be configured in the <reporting/> element from the POM.
According to the maven goal specified in the command line (for example mvn clean, mvn clean package or mvn site) , a specific lifecyle will be used and a specific set of plugins goals will be executed.
There are three built-in build lifecycles: default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project's site documentation.
A plugin goal may be bound to a specific phase of a specific lifecyle.
For example the maven-compiler-plugin binds by default the compile goal to the lifecycle phase: compile.
Most of maven plugins (both core plugins and third party plugins) favor convention over configuration. So these generally bound a plugin goal to a specific phase to make their usage simpler.
That is neater and less error prone :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
than :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
What dependencies are ?
Dependencies are Maven artifacts/components required for the project.
Concretely most of dependencies are jar (that is libraries) but these may also be other kinds of archives : war, ear, test-jar, ejb-client ... or still POM or BOM.
In a pom.xml, dependencies may be specified at multiple places : the <build><dependencies> part , the dependencies management part or still in a plugin declaration ! Indeed some plugins may need to have some dependencies in the classpath during their execution. That is not common but that may happen.
Here is an example from the documentation that shows that plugin and dependency may work together :
For instance, the Maven Antrun Plugin version 1.2 uses Ant version
1.6.5, if you want to use the latest Ant version when running this plugin, you need to add <dependencies> element like the following:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
...
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
</project>
In Maven, dependencies are referenced in a specific format :
groupId:artifactId:packaging:classifier:version.
The classifier (that is optional) and the packaging (JAR by default) are not commonly specified. So the common format in the dependency declaration is rather : groupId:artifactId:version.
Here is an example of dependency declared in the <build><dependencies> part :
<build>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.14.Final</version>
</dependency>
<dependencies>
</build>
Dependency doesn't have a phase binding as plugins to address the "when" question.
But it has a counterpart : the scope.
Indeed declared dependencies are usable by the application at a specific time according to the scope we defined for these.
The scope is a central concept about how a dependency will be visible for the project.
The default scope is compile. That is the most commonly needed scope (convention over configuration again).
The compile scope means that the dependency is available in all classpaths of a project.
The scope defines in which classpaths the dependency should be added.
For example do we need it at compile and runtime, or only for tests compilation and execution ?
For example we previously defined Hibernate as a compile dependency as we need it everywhere : source compilation, test compilation, runtime and so for....
But we don't want that testing libraries may be packaged in the application or referenced in the source code. So we specify the test scope for them :
<build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
<dependencies>
</build>
One line answer - basic understanding
Plugin is a tool you use at the execution of your maven build
Dependency means kind of any library which you will use in your code
If you're coming from a front-end background like me, and are familiar with Grunt and npm, think of it like this:
First you would run, say, npm install grunt-contrib-copy --save-dev. This is like maven's <dependency></dependency>. It downloads the files needed to execute a build task.
Then you would configure the task in Gruntfile.js
copy: {
main: {
src: 'src/*',
dest: 'dest/',
},
}
This is like maven's <plugin>/<plugin>. You are telling the build tool what to do with the code downloaded by npm/<dependency></dependency>.
Of course this is not an exact analogy, but close enough to help wrap your head around it.
Plug-ins are used for adding functionalities to Maven itself (like adding eclipse support or SpringBoot support to Maven etc.). Dependencies are needed by your source code to pass any Maven phase (compile or test for example). In case of JUnit since the test code is basically part of your code base and you call JUnit specific commands inside test suites and those commands are not provided by Java SDK therefore JUnit must be present at the time Maven is in the test phase and this is handled by mentioning JUnit as a dependency in your pom.xml file.
In simple words:
Plugins are used to add some additonal features to the software/tools(like Maven). Maven will use the added plugins at the time of building when we use the build command.
Dependecies are used to add some addtional code to your source code, so a dependency will make some extra code (like Classes in Java) in the form of library available for your source code.
Maven at its heart is a plugin execution framework -- as per formal and standard compact definition. To make it more clear, the commands you use like maven-install/clean/compile/build etc for creating/executing jars, which we sometimes manually run too. So, the things which you want to run (or configure or execute) you basically put them in dependency tag of mavens pom and the answer so as to who will run these dependencies (required for environment setup) be the plugins.
javac (compiler) dependency.java (dependency)
A plugin is an extension to Maven, something used to produce your artifact (maven-jar-plugin for an example, is used to, you guess it, make a jar out of your compiled classes and resources).
A dependency is a library that is needed by the application you are building, at compile and/or test and/or runtime time.

How to distribute a binary dependency in maven?

I'm trying to convert a project from ant to maven.
The unit tests depend on a third party binary jar, which is not available in any public maven repositories.
How do I make maven handle this situation? I have found two solutions, neither of which are acceptable. First is to use a system dependency; this doesn't work because a) the dependency should only be for the tests, and b) the dependency is not found by eclipse after generating an eclipse project.
Second is to manually install the dependency in a local repository. This seems to be the recommended way. I don't want to do this because I want users to be able to build and test with a simple 'mvn test'. If users have to read a document and copy/paste some shell commands to be able to build and test, then something's wrong.
I suppose it would be OK if maven itself installed the dependency in the local repository as part of the build - is this possible, and if so, how?
Aled.
You may want to look at install:install-file. You can make it execute in the early phase of your project (validate or initialize) via standard means.
On the second thought, if it fails because of missing dependency in the same project, there are couple more options. One is to call ant script via antrun plugin to install artifact.
Or create additional module not dependent on your artifact to be executed prior to main module and have that module install artifact as described earlier.
First of all my way would be using a repository manager such as nexus and installing this dependency to there.
However there is another solution. You can include this 3rd party jar to your project and with test plugin you can configure to include it in classpath such this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.10</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>path/to/additional/resources</additionalClasspathElement>
<additionalClasspathElement>path/to/additional/jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
By the way, I hope that you are aware of that maven is executing surefire plugin in order to run tests by default lifecycle.

Resources