Dependency injection and Tests - java

I have a project that contains some tests, all it does is create a test-jar to be run by other projects. And it depends on a another artifact, let's call it artifact X
then there are multiple other projects that run the test-jar, using the maven-surefire-plugin
I have multiple implementations of artifact X and what I want to do is to be able to run those tests using the implementation that I want, not X
so for example:
in project A I want to run the tests using implementation A
in project B I want to run the tests using implementation B
this does not seems to be possible, because once the test-jar generated, it has the artifact X hard-coded in it
so I'm open to any other solutions
Edit :
extra information:
the pom file of the project generating the tests :
the part for generating the test-jar
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
the Artifact X dependency :
<dependency>
<groupId>com.conztanz</groupId>
<artifactId>X</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
the pom file of one of the projects running the tests (project A):
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<dependenciesToScan>
<dependency>testJar</dependency>
</dependenciesToScan>
</configuration>
</plugin>
</plugins>
</build>
Ideally what I want is do some thing that tells project A to Override artifact X with it's own implementation
I hope this makes more sense now

I think you're looking for the scope called provided.
The dependency would look like this:
<dependency>
<groupId>com.conztanz</groupId>
<artifactId>X</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
This tells Maven: "Hey, I need this to compile, but don't include it in the target output, because a container (or something) will provide the jar itself."

Related

How to force maven to download a artifact from a specific repo in plugin

I am trying solve an issue related with download of my own checktyle from the plugin section in my pom.xml.
At the moment the pom.xml contains all necessary configurations that allows me to download the dependencies from my own artifactory. The problem occurs when I am trying to download a specific artifact of my jar file, every time I try, the code tries to download from the maven central instead of going to my configurations of repos added into the pom.
How can I "force" the plugin to check in my artifactory first instead of going all the time to the maven central repository? There is any specific configurations for the plugins?
The code that I have to download my own artifact in the plugins is the one below.
I am pointing already the repository via DistributionManagement and repositories.
<build>
<plugins>
....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version>
<dependencies>
<dependency>
<groupId>com.test.checkstyle</groupId>
<artifactId>checkstle-tools</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.31</version>
</dependency>
</dependencies>
<configuration>
<consoleOutput>true</consoleOutput>
<configLocation>build/checkstyle-test.xml</configLocation>
<sourceDirectories>
<sourceDirectory>${project.build.sourceDirectory</sourceDirectory>
<sourceDirectory>${project.build.testSourceDirectory</sourceDirectory>
</sourceDirectories>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
Note:
I am to have a clean settings.xml with all necessary configurations, I won't be able to manage the settings.xml after I deploy the application.

Failed to bypass maven checkstyle plugin

My project is consisted of two modules, one is common, the other let's call it X.
When using maven to "clean install" module X, it complained:
You have 50 Checkstyle violations.
Looking into the pom.xml I didn't see any checkstyle maven plugin, but in the "common" module I did find it in "common"'s pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.9.1</version>
</plugin>
Since module X depends on module "common", I updated common's checkstyle plugin in pom.xml like this:
<configuration>
<skip>true</skip>
</configuration>
and rebuilt the common module before I ran the "clean install" on X module.
To play safe, I added one more setting on the mvn command when running X module:
mvn clean install -DskipTests -Dcheckstyle.skip
However, it looks that neitherthe change in "common"'s pom.xml w.r.t checkstyle plugin nor the additional setting on mvn command had any effect on the running - it still complained the same.
I tried with, pluginManagment and it works fine. You need to add this in your parent pom file.
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
It turned out that there are two places in the pom.xml that involve checkstyle plugin: one is under the tag
<pluginManagement>
, in which I added:
<skip>true</skip>
However it's not sufficient (at least in my case), I found the checkstyle was also registered under:
<build><plugins>
it looks like:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>6.1.1</version>
</dependency>
</dependencies>
<configuration>
<skip>true</skip>
....
</configuration>
<plugin>
Now after I added skip being true to both places and rebuilt the project modules, the errors were gone.

Create a simple JAR instead of an executable JAR with Spring-Boot

I have a problem with a Multi-Module Spring-Boot Application.
I have one Module that I use for Services, the core-Module. And one module for View-Related Classes, the web-Module.
The are both in a parent-Module, where I add the dependencies, like the "spring-boot-starter" and that can be used by both modules.
Now to the problem:
I want to run the web-Module with the embedded Tomcat and have the core-Module as a dependency in the web-module.
In other Spring projects I would just include the maven-jar-plugin and create a jar of the core-Module.
The problem in this Spring-Boot project is that the maven-jar-plugin is already configured, in the "spring-boot-starter". And it needs a mainClass, which only the web-module has.
Small excerpt from the "spring-boot-starter"-POM
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>${start-class}</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
Is there a way to package the core-Module as a JAR without needing a "start-class" in that module?
It seem like you can disable the fat-JAR from replacing the original and getting installed into the repo by configuring the spring-boot-maven-plugin.
Taken from http://docs.spring.io/spring-boot/docs/1.5.1.RELEASE/maven-plugin/examples/repackage-disable-attach.html:
By default, the repackage goal will replace the original artifact with
the executable one. If you need to only deploy the original jar and
yet be able to run your app with the regular file name, configure the
plugin as follows:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<attach>false</attach>
</configuration>
</execution>
</executions>
...
</plugin>
...
</plugins>
...
</build>
...
</project>
This configuration will generate two artifacts: the original one and the executable counter part produced by the repackage goal. Only the original one will be installed/deployed.
You can just disable the spring-boot-maven plugin this way.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
I have found the answer.
I configured my application just like #judgingnotjudging explained. The difference was that I had put this, in the parent-POM:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
It was preventing the default creation of JARs in the children-modules. I could resolve this problem by including this only in the web-Module.
That way Spring-Boot builds a fat-JAR from the web-Module and a simple JAR from the core-Module.
To create simple jar update
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
To
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
For more details please visit below Spring URL:-
https://docs.spring.io/spring-boot/docs/1.1.2.RELEASE/reference/html/howto-build.html
You can simply change
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
to
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
I don't know whether it's still relevant or not, however, a simple classifier needs to be configured for the spring-boot-maven-plugin -
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
This would generate two jars - one a normal one which can be included as a dependency, another as an exe jar with the "exec" word appended as a suffix - like test-0.0.1-SNAPSHOT-exec.jar and test-0.0.1-SNAPSHOT.jar
If you're using the embedded tomcat to run your app, don't you just want a standard Spring Boot fat jar for your web app? If so, just mark your web module as dependent on your core module in the pom, and build your project.
It's there a different use case that you need the jars separated?
Are you building your modules as completely separate modules or as modules as part of a single multi-module project? The difference is in the latter, you will have a pom at the root specifying the modules. I forget the Maven syntax specifically, so my example is Gradle (Maven docs for multi-module builds are here). Sorry about that.
baseProject
|----web-module
|----core-module
baseProject's build.gradle:
project(':web-module') {
dependencies {
compile project(':core-module')
}
evaluationDependsOn(':core-module')
}
Maven has a similar structure. You should review the docs, but I believe all you need to do is specify the module order correctly in your parent pom as below and include the dependency in your web-module pom.
Parent pom:
...
<modules>
<module>core-module</module>
<module>web-module</module>
</modules>
web-pom:
<project ...>
<parent>
<groupId>com.example</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>web-module</artifactId>
<packaging>war</packaging>
<name>My web-module</name>
<dependencies>
...
<dependency>
<groupId>com.example</groupId>
<artifactId>core-module</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
...
core pom should only need to include the parent section as in the web-module above, and otherwise be the same.

Conventional workflow to build deployable maven code from repo

I am setting up a Maven repository with the goal of automating much of my build and deploy process. My current workflow begins with bringing up a server, doing a git clone, and running a bunch of mvn install commands to complete the top level application.
To my understanding, Maven is not a tool for deploying applications, and at this point I do not see a need for a continuous integration or continuous deployment server or formal process.
However, thus far I have not been able to find a canonical way to put together the complete, runnable program together with Maven.
This script goes so far as to get the top level jar and install it into the local maven repo:
mvn -DgroupId=me.company -DartifactId=Top-Level-Application -Dversion=1.0-SNAPSHOT -DrepoUrl='http://theserver:8081/nexus/' dependency:get
If I installed everything manually, this application would find all of its dependent jars in a lib/ directory, as Maven ought to do. However this jar as pulled is not deployable - while the dependent jars are installed to a local repo they are not compiled where the classpath expects it.
I imagine if I could rig the above script to pull the pom.xml instead of just the jar and run a mvn install on that, everything would go smoothly (although weirdly that seems to be duplicating the last step of the build process). Another option is for applications to contain all dependent jars rolled up into one giant jar and have no external dependencies.
Which of these (or other) options is the proper way to complete the Maven build process?
Here is our top-level pom narrowed down to as much as I can think would be relevant:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>me.company</groupId>
<artifactId>Top-Level-Application</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Top Level Application</name>
<url>http://company.me</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<distributionManagement>
<repository>
<id>releases</id>
<url>http://host:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>Internal Snapshots</name>
<url>http://host:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>me.company.application.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>copy</id>
<phase>compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>me.company</groupId>
<artifactId>First-Library</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- more in-house libraries -->
<!-- third party libraries - Apache Commons, javamail, etc. -->
</dependencies>
</project>
Correct me if I'm wrong -- you want to transform your source code into a compiled JAR, with appropriately-set classpath for its dependencies? That's not what dependency:get is for at all. You should look into the Maven JAR plugin and/or the Maven AppAssembler plugin.

Lifecycle phases in maven multi module build

I have defined a maven multi modul build where one module is only used to generate sources. It will not compile, test or package and won't create any artifacts apart from the generate source files.
I haven't found a way yet to only execute the phases up to generate-sources on the generator module, regardless of the phase I specify when I start the multi module build. There are some solutions for skipping unwanted phases, but this is not a real option as there are just to many of them.
For those wondering, why I would want it: The build uses tycho and the fornax oaw plugin and so I had to split the build into two separate pom files and use a multi module build file to execute them "together".
After seeing your latest question I think I might have a solution for you.
I guess that all your ../projectN/generate/pom.xml has the top pom as its parent but I suggest that you create a special generate-parent pom with a special plugin management that will skip all the phases for you.
Create an extra folder called generate-parent at the top level:
<modules>
<module>../generate-parent/pom.xml</module> <!-- NEW FOLDER WITH POM -->
<module>../project1/generate/pom.xml</module>
<module>../project1/pom.xml</module>
<module>../project2/generate/pom.xml</module>
<module>../project2/pom.xml</module>
<!-- and many more projects with or without generate sub modules -->
</modules>
This new pom will inherit from the parent pom as usual but add only some extra plugin management:
<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>
<parent>
<groupId>your-group</groupId>
<artifactId>your-parent-pom-artifact-id</artifactId>
<version>your-parent-version</version>
</parent>
<artifactId>generate-parent</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}-${project.version}</name>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>default-resources</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testResources</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<executions>
<execution>
<id>default-test</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-install</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Now with this pom all the default phases are disabled.
Now use this pom in all the generate projekcts. The above pom inherits all of the good stuff you have in your parent pom but just adds these special plugin management parts that disables the phases after the generate-sources.
project1/generate/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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>your-group</groupId>
<artifactId>generate-parent</artifactId>
<version>your-parent-version</version>
<relativePath>../../generate-parent</relativePath>
</parent>
...
The rest of your pom
...
</project>
This will effectively do what you want, the generate-parent is the middle-man that adds all the plugin management you want for just these generate projects.
So far as I understand, this is about using Xtext to create a code generator that is invoked in a maven build. I think you need to split up your project a bit more. You only need the generator to be built, when you change your grammar. So it would be a good idea to have a independent project (not a module) that contains the generator. You build and deploy your generator to a maven repository. In your normal build you use the fornax-oaw-m2 plugin to generate your sources in the generate-sources phase as you are doing now. You just need to include the generator as a dependency for the fornax-oaw-m2 plugin.
EDIT:
So to come back to your multi module project you want to build: I suggest that there is a module that only contains the resources from which you generate the sources and nothing else. The other java sourcec should be contained in their own module. Then I can suggest two alternatives for using the generator:
Run the generator in the module that contains the resources from which you generate the sources and set relative paths appropriately
Run the generator in the module that should contain the generated sources and include the module with the resources as a dependency (you may need to unpack that dependency before generating resources)
You still always generate in the generate-sources phase. In the 2nd alternative, the configuration of the fornax-oaw-m2 plugin will be duplicated, if you need generate sources to a set of different modules. But I think that this is more the maven way, as you only change the project you are currently building. In the first alternative, you would have to declare the dependencies from the modules, where source is generated into to the module that does the source generation. This seems a bit awkward.

Categories

Resources