I have a maven project project A that has a dependency on a different maven project project B. I publish Project B as two jars, one with the regular class files and one for its tests (I need to re-use some componenents). Maven has a plug-in for this.
The pom.xml for project A looks like this:
<properties>
<project-B.version>abcd123</project-B.version>
</properties>
<dependencies>
<dependency>
<groupId>group-id-project-B</groupId>
<artifactId>project-B</artifactId>
<version>${project-B.version}</version>
</dependency>
<dependency>
<groupId>group-id-project-B</groupId>
<artifactId>project-B</artifactId>
<classifier>tests</classifier>
<type>test-jar</type>
<version>${project-B.version}</version> <!-- Doesn't work! -->
<scope>test</scope>
</dependency>
</dependencies>
Somehow, both my IDE (IntelliJ) and mvn CLI are unable to compile this and both give an unresolved reference in my test classes (where I re-use test files from project B).
If, however, I replace ${project-B.version} with abcd123 in the test-jar dependency everything loads fine. I can't make any sense of this as to why mvn doesn't like me to use a variable in properties? This behaviour is consistent between my IDE and mvn cli.
For what it's worth, this is the output for project B when I use mvn dependency:list
group-id-project-B:project-B:test-jar:tests:abcd123:test
group-id-project-B:project-B:jar:tests:abcd123:compile
And the rest of my pom:
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
is there a bug in maven or am I missing something?
Edit:
I use mvn clean install and the truncated output is:
[INFO] --- kotlin-maven-plugin:1.3.72:test-compile (test-compile) # optimization-engine-service ---
[ERROR] MyClass.kt: (16, 19) Unresolved reference: functionName
[ERROR] MyClass.kt: (19, 28) Unresolved reference: SOME_FIELD
... etc.
Maven cannot resolve artifact that were installed/deployed with a version from parameter.
In order for your artifacts to be resolvable after build, you will have to use flatten-maven-plugin so you get an effective pom which will be resolvable by maven.
You can see an example on how to do this in maven-ci-friendly
Related
I have a framework where I have multiple classes and one of my class is a mojo class which gets some data from a different class and then pass that data to some other class for execution.
The first time when I use command mvn clean install I would get error - Could not find artifact com.io:MyDataProject:0.0.1-SNAPSHOT. Then I have to comment out the second plugin section inside build tag as shown below and again use command mvn clean install which would then install my plugin and once installed I would then uncomment the commented code again so that I can use my installed plugin which executes the mojo and then everything runs fine.
Issue is if I would share my project with other team members they have to do the same steps which I don't want. I need something like using mvn clean install would install my plugin and can execute my mojo at the same time.
#Mojo(name = "dependency-counter", defaultPhase = LifecyclePhase.COMPILE)
public class DependencyCounterMojo extends AbstractMojo {
public void execute() throws MojoExecutionException, MojoFailureException {
System.out.println("$$$$$$$$$$$$$$ ....Mojo execution begins.... $$$$$$$$$$$$$$");
GenerateFeature ob=new GenerateFeature();
ob.getData();
}
}
Pom.xml:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
</plugin>
<plugin>
<groupId>com.io</groupId>
<artifactId>MyDataProject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>dependency-counter</goal>
</goals>
</execution>
</executions>
<configuration>
<scope>test</scope>
</configuration>
</plugin>
</plugins>
</build>
You need two separate projects or modules:
One for the plugin, containing the mojo and the POM for the plugin.
One for your framework, where the POM lists the plugin under <plugins>.
You cannot list the plugin in the same POM that produces the plugin.
You might also consider not putting the plugin into the POM at all, but run it on command line.
I have multi-module maven project. The acceptance-tests module has dependency from api module in pom.xml (Replacing real company name by xxx to keep confidentiality). I am trying to import some classes from api module in my acceptance-tests.
Here is my pom.xml dependency of acceptance-tests module:
<dependency>
<artifactId>xxx-api</artifactId>
<groupId>com.xxx</groupId>
<version>${xxx.api.version}</version>
</dependency>
The api module separately is being installed and packaged (mvn install, mvn package) by maven without any issue. The jar file is being created in my local .m2.
However, when I try to compile the acceptance-tests module, I get a compilation error saying that the the classes cannot be imported because the package is not found.
Here is the actual error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project xxx-acceptance-tests: Compilation failure: Compilation failure:
[ERROR] /Users/andranik_chorokhyan/mydisk/Projects/XXX/automation/xxx-project-test-automation/xxx-acceptance-tests/src/main/java/com/xxx/xxx/utilities/api/ApiPayloadUtils.java:[17,38] package com.xxx.domain.dto does not exist
[ERROR] /Users/andranik_chorokhyan/mydisk/Projects/XXX/automation/xxx-project-test-automation/xxx-acceptance-tests/src/main/java/com/xxx/xxx/utilities/api/ApiPayloadUtils.java:[18,38] package com.xxx.domain.dto does not exist
[ERROR] symbol: class MappingData
[ERROR] location: class com.xxx.utilities.api.ApiPayloadUtils
One more interesting fact is that there is no error visible in Intellij IDEA. No red underline, no compilation error, no problem with navigating to the appropriate imported file.
And in reality, the com.xxx.domain.dto package does exist and the MappingData class as well.
I removed whole xxx directory from my local .m2 repository and executed mvn clean dependency:resolve command. It succeeded as well.
Does anybody know what's the problem here and how it can be solved?
Thanks in advance!
Finally I have found the solution. Thanks JF Meier and khmarbaise for hints.
It appeared Maven doesn't allow dependency from executable jar. This was my case. My api module was an executable Spring Boot application and not reusable library.
So, the solution was the following:
It was necessary to find the Application.java file in api module.
Add maven-jar-plugin with exclusion of the Application.java file and specification of some classifier
Making dependency in acceptance-tests module from the above specified classifier instead of standard jar
Plugin specification in api module below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>qa</classifier>
<excludes>
<exclude>**/Application*</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
Dependency in acceptance-tests module below:
<dependency>
<artifactId>xxx-api</artifactId>
<groupId>com.xxx</groupId>
<version>${api.version}</version>
<classifier>qa</classifier>
</dependency>
I was also getting symbol not found errors while compiling with maven, and the solution is for spring boot 2 you need to configure plugin as below, classifier exec
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
If you are working with spring boot 1
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
I've got a plugin that I need to use in my build. This plugin, however, has a build-time dependency on another plugin and that dependency does not work post-Java-8.
Specifically, the plugin that I want to use has this in its pom.xml file
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>${javaVersion}</version>
<scope>system</scope>
<systemPath>${tools.jar}</systemPath>
</dependency>
</dependencies>
<executions>
<execution>
<phase>test-compile</phase>
......
</execution>
</executions>
</plugin>
It's set to the test-compile phase, so it's only ever run when the plugin itself is being built, and not when it's being used.
The problem is that it's got the systemPath as part of the dependency, and this is set to something that is not resolvable using Java 9+. That in turn causes the build for the project using the plugin to fail with:
[ERROR] 'dependencies.dependency.systemPath' for com.sun:tools:jar must specify an absolute path but is ${tools.jar} #
So either I need to completely ignore the maven-antrun-plugin as part of my using this plugin, or I need to at least make the dependencies for it work.
Any thoughts?
Cheers
I'm using IntelliJ IDE with maven. I have a project (main module) with a parent pom, that includes 2 sub modules, each with their own pom.
<!-- main pom module part -->
<packaging>pom</packaging>
<modules>
<module>ModuleA</module>
<module>ModuleB</module>
</modules>
<!-- example for sub module pom -->
<parent>
<artifactId>main-module</artifactId>
<groupId>my.main.module</groupId>
<version>0.5.0</version>
</parent>
Image ModuleA includes the OpenCV Java wrapper and ModuleB is an executable java program (having the main class) using ModuleA.
The compiling works fine, but when I run ModuleB with having set the library path in the launcher, I'll get the following error for ModuleA:
java.lang.NoClassDefFoundError: org/opencv/core/Core
Any suggestions how to fix this?
Ok, I found a solution my self. The problem was, that the opencv java wrapper was included with a system path. Now I use the maven install plugin within the validate live cycle step instead.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>3.3.0</version>
<packaging>jar</packaging>
<file>${project.basedir}/../lib/opencv/opencv-330.jar</file>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Works fine for me, but was not the way I wanted it to be... The system-path type dependency seems to be buggy in maven.
Try to add the following dependency to your ModuleA:
<dependency>
<groupId>nu.pattern</groupId>
<artifactId>opencv</artifactId>
<version>2.4.9-7</version>
</dependency>
I have a project called "commons" that contains common includes for both runtime and test.
In the main project I added a dependency for commons:
<dependency>
<groupId>com.alexb</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
However the test common files are not included. So I added :
<dependency>
<groupId>com.alexb</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
</dependency>
However when type is test-jar, the runtime is not included.
Unfortunatelly, it seems I cannot include both:
<type>jar,test-jar</type>
What can I do to include both?
As #khmarbaise mentioned in the comments you should separate your test-jar part project.
I presume you have in the commons pom.xml something like this which generates common test-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
The problem with this approach is that you don't get the transitive test-scoped dependencies automatically.
Check this link for more details:
https://maven.apache.org/plugins/maven-jar-plugin/examples/create-test-jar.html