Reputation: 2233
I have a question regarding how maven calculates the classpath during building. Specifically, what controls when the "target/classes" is used and when the "jar" from a repository (local/remote) is used.
I have a project on version 1.0.0-SNAPSHOT where the artifacts have NOT been installed/deployed so there is no "jar" in some repository (remote or local) to resolve them. I want to run "generate-sources" WITHOUT installing locally (no 'mvn install
' run).
The structure looks like this:
parent-prj
parent-prj/sub-prj
parent-prj/gen-src-prj <--- This depends on 'sub-prj'
When I run "mvn -am -pl parent-prj/gen-src-prj generate-sources
" in order to just generate some java files, it does not work:
[ERROR] Failed to execute goal on project gen-src-prj: Could
not resolve dependencies for project
mygrp:gen-src-prj:jar:1.0.0-SNAPSHOT:
Could not find artifact
mygrp:sub-prj:jar:1.0.0-SNAPSHOT -> [Help 1]
Using debug output and adding "dependency:build-classpath" I can confirm that maven ignores the presence of "sub-prj" in the reactor and looks for a "jar" somewhere which it can't find. Yet the project is printed in the reactor summary:
[INFO] Reactor Summary:
[INFO]
[INFO] parent-prj ..................................... SUCCESS [ 0.625 s]
[INFO] sub-prj ........................................ SUCCESS [ 0.018 s]
[INFO] gen-src-prj .................................... FAILURE [ 0.040 s]
The interesting thing I noticed is that running the compile goal works fine! This uses sub-prj/target/classes
(as shown by dependency:build-classpath) and has no trouble generating the sources and even compiling them: "mvn -am -pl parent-prj/gen-src-prj compile
"
So here are the points I want to understand:
Regarding (3) my generation tool is a utility invoked by:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
The tool reads some XML in src/main/resources and generates Java files and does NOT need anything in its class-path (so there is no need for maven to resolve it).
Also note that I would be interested to understand (1) and (2) even if a solution for (3) is provided.
EDIT: Per comment request, adding full example
parent-prj/pom.xml
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mygrp</groupId>
<artifactId>parent-prj</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>sub-prj</module>
<module>gen-src-prj</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.9</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
parent-prj/sub-prj/pom.xml
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mygrp</groupId>
<artifactId>parent-prj</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>sub-prj</artifactId>
</project>
parent-prj/gen-src-prj/pom.xml
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mygrp</groupId>
<artifactId>parent-prj</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>gen-src-prj</artifactId>
<dependencies>
<dependency>
<groupId>mygrp</groupId>
<artifactId>sub-prj</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>uk.co.real_logic.sbe.SbeTool</mainClass>
<systemProperties>
<systemProperty>
<key>sbe.output.dir</key>
<value>${project.build.directory}/generated-sources/java</value>
</systemProperty>
<systemProperty>
<key>sbe.validation.warnings.fatal</key>
<value>true</value>
</systemProperty>
</systemProperties>
<arguments>
<argument>${project.build.resources[0].directory}/Examples.xml</argument>
</arguments>
<workingDirectory>${project.build.directory}/generated-sources/java</workingDirectory>
</configuration>
<dependencies>
<dependency>
<groupId>uk.co.real-logic</groupId>
<artifactId>sbe-tool</artifactId>
<version>1.7.10</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated-sources/java/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
EDIT: Armed with the knowledge from the answers I have come up with this workaround that allows one to achieve the desired behaviour. I list the dependencies in a profile that is active by default, then use another profile to run generate-sources with no dependencies active, like follows:
parent-prj/gen-src-prj/pom.xml
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>mygrp</groupId>
<artifactId>sub-prj</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>excludeDependency</id>
<dependencies>
</dependencies>
</profile>
</profiles>
To generate sources with above, use: mvn -PexcludeDependency generate-sources
Upvotes: 9
Views: 11170
Reputation: 15308
Maven can reference only output generated in current Session (during currently executing shell command). It uses the most "mature" place to look for the "output":
compile
is run - the classes end up in the target/classes
dir, thus other modules can reference thatpackage
is run - then target/*.jar
is created and this jar file ends up in the classpath insteadinstall
is run - then jar file ends up in the local repository - which is what ends up on the classpathSo there are 3 factors that impede your task:
generate-sources
is run before the compilation. Thus module2 is not yet prepared to be used as a dependency.So if you want to do it your way - you'll have to run at least compile
phase each time you use anything from the Default Lifecycle. Or you could write your own plugin that doesn't require dependency resolution.
Upvotes: 5
Reputation: 374
This problem is related to an open maven bug:
https://issues.apache.org/jira/browse/MNG-3283
The issue says: "The problem only occurs when a plugin binds itself to the generate-sources phase and has @requiresDependencyResolution".
I have checked that exec-maven-plugin Mojo have indeed requiresDependencyResolution = ResolutionScope.TEST
. You can see that on https://github.com/mojohaus/exec-maven-plugin/blob/master/src/main/java/org/codehaus/mojo/exec/ExecJavaMojo.java
Then, your only option is to use compile or process-classes phases. This is a Major open bug from 2007...
Upvotes: 3