How to configure a subproject dependency in Maven without deploying jars? - maven-2

I googled this and it seems that no one has an answer, yet it seems like such an elementary thing that it should be possible.
I have the following project structure:
parent
---sub-project1
---sub-project2
sub-project2 needs to have sub-project1 as a dependency.
So I have this in sub-project2's pom:
<dependencies>
<dependency>
<artifactId>sub-project1</artifactId>
<groupId>mygroup</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
....
When I do this, Maven tries to dowload the sub-project1.jar file, which does not exist because it's not ready for the repo yet.
I tried to put a <scope>import</scope> in the dependency, but that didn't work either -- same result.
So what do I have to do to get Maven to look at sub-project1 when building sub-project2?
EDIT Here are some pom snippets:
Parent:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<prerequisites>
<maven>2.0.9</maven>
</prerequisites>
<modules>
<module>sub-project1</module>
<module>sub-project2</module>
</modules>
....
sub-project1:
<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">
<parent>
<artifactId>parent</artifactId>
<groupId>mygroup</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sub-project1</artifactId>
....
sub-project2:
<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">
<parent>
<artifactId>parent</artifactId>
<groupId>mygroup</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sub-project1</artifactId>
<dependencies>
....
<dependency>
<artifactId>sub-project2</artifactId>
<groupId>mygroup</groupId>
<version>1.0-SNAPSHOT</version>
<scope>import</scope>
</dependency>
</dependencies>
The error I'm getting when I got mvn clean install on the parent is:
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure
With a lot of classes/package not found errors

You should have a master pom at parent's level, in which you will list the modules of your project.
<modules>
<module>sub-project1</module>
<module>sub-project2</module>>
</modules>
In each subproject you have to reference your parent:
<parent>
<artifactId>parent</artifactId>
<groupId>mygroup</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
And you specify the dependencies between the project just as you did. I think you've missed some of the steps I've described.
Edit: you should issue your mvn clean install at the parent level.

When I do this, Maven tries to dowload the sub-project1.jar file, which does not exist because it's not ready for the repo yet.
That's the normal behavior, Maven resolves dependencies through the local repository so you need to install sub-project1 first. Actually, the common way to deal with this kind of situation is to launch a reactor build (a multi-modules build) from the parent.
Assuming you are aggregating modules in the parent i.e. you have something like this declared in the "parent" pom.xml:
<modules>
<module>sub-project1</module>
<module>sub-project2</module>>
</modules>
Just cd into the parent directory and launch a reactor build:
$ cd parent
$ mvn install
Maven will then calculate the build order (deducted from the oriented graph made of modules and their dependencies) and run install on all modules in the calculated order (parent first, then sub-project1 and finally sub-project2 for your particular example).
But don't use a scope of type import, you are misusing it here. Remove it.
Update: The question has been updated while I was answering and the POMs shown do no illustrate the situation given in the original question (reversed dependency, probable mistake in the artifact id). But the suggested approach still applies. Remove the <scope>import</scope> on the dependency and start a reactor build from the parent.

Related

IntelliJ 12 - maven multimodule cannot resolve transitive dependencies

I've imported maven multimodule project and some transitive dependencies are not resolved. This same project builds in Jenkins/Eclipse/Console.
I've tried two import each project separately, and also to import only parent pom - both are not working.
I have following structure: Project A and Project B have common parent and both are defined as modules in this parent. Project A contains as dependency jackon-jar, Project B does not have it. Project A contains jackson-jar in default scope - jar is visible during compilation and tests are running. Now Project B imports Project A and also uses jackson-jar - and here is the problem - jackson-jar in not visible in Project B :( When I specify it explicitly in Project B all works fine, but it should come automatically as transitive dependency from Project A ......
Is this common problem? Is there workaround?
Here are POM examples:
Parent:
<project ....>
<modelVersion>4.0.0</modelVersion>
<version>1.0-SNAPSHOT</version>
<groupId>miklas.test</groupId>
<artifactId>my-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>my-project-a</module>
<module>my-project-b</module>
<module>my-project-c</module>
</modules>
</project>
Project-A
<project ....>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>miklas.test</groupId>
<artifactId>my-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>my-project-a</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>2.3.4.Final</version>
</dependency>
</dependencies>
</project>
Project-B
<project >
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>miklas.test</groupId>
<artifactId>my-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>my-project-b</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>miklas.test</groupId>
<artifactId>my-project-a</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Below is also the screenshot from my real project - this would be Project B from simplified example above. On the left side we can see, that resteasy-jackoson-provider has 4 dependent jars, and on the right side there are only two. Both views are showing the same project:
Now the same screenshot from Project A
This appears to be a bug in IntelliJ 12. See http://youtrack.jetbrains.com/issue/IDEA-98425 and please vote for the issue if it's important to you.
Workaround mentioned at http://youtrack.jetbrains.com/issue/IDEA-98425 that worked for me and others is to go to "settings - Maven - Multiproject build fail policy". Set it to "Fail At End".

ivy - why is trying to download yyyy.bundle and can I avoid that?

We recently transformed a maven pom to ivy but are getting this error for many things(not all things):
[NOT FOUND ] org.apache.geronimo.specs#geronimo-javamail_1.4_spec;1.7.1!geronimo-javamail_1.4_spec.bundle (11649ms)
The only difference between the pom files that work and don't is there a package element with the value "bundle".
Maven is working fine. How can we get ivy working as it gets the pom and just really needed to download the jar artifact.
More info, I changed my ivysettings so it ends in .jar instead of [ext] like so
This workardoun worked but I am worried now source downloads won't work anymore. Unfortunately, I don't control the poms in the repository that specify bundle in the packaging attribute. Is there a way to override certain things in ivy so I can fix all these and not use my temporary workaround?
I copied from the pom in nexus for that url which is the following and notice packaging is bundle
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.geronimo.genesis</groupId>
<artifactId>genesis-java5-flava</artifactId>
<version>2.0</version>
</parent>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-javamail_1.4_spec</artifactId>
<packaging>bundle</packaging>
<name>JavaMail 1.4</name>
<version>1.7.1</version>
<description>Javamail 1.4 Specification</description>
<url>
http://geronimo.apache.org/maven/${siteId}/${version}
</url>
<distributionManagement>
<site>
<id>apache-website</id>
<url>${site.deploy.url}/maven/${siteId}/${version}</url>
</site>
</distributionManagement>
The pom that brings that in is cxf-bundle which I depend on. The dependency in the cxf-bundle is
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-javamail_1.4_spec</artifactId>
<version>1.7.1</version>
<scope>compile</scope>
</dependency>
thanks,
Dean
Darnit, I copied the example on the ivy site which downloads an older version that has this bug
https://issues.apache.org/jira/browse/IVY-899
The newest version works just fine.

How to make one module depend on another module artifact?

I have maven multiple-module project.
A: parent.
B: child1.
C: child2.
B will be packaged to get jar file and then c will use this jar file to compile the code.
In B, if I run mvn package, it will create b.jar (stays in B/target/jars not in B/target -for another purpose).
In C, I need to use that b.jar to compile the code.
Now, from A, when I run: mvn package. First, I am successful to create b.jar file for B.
But when it come to C's compilation phase, it looks like C doesn't recognize b.jar in the classpath (the compilation gets errors because C's code can not import the class file from B).
My question is: How can I solve this problem?
---------- Below are the pom files
A: pom.xml
<groupId>AAA</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>C</module>
<module>B</module>
</modules>
B: pom.xml
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<parent>
<artifactId>A</artifactId>
<groupId>AAA</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
C: pom.xml
<parent>
<artifactId>A</artifactId>
<groupId>AAA</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>AAA</groupId>
<artifactId>C</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
....
Try ${project.version}
e.g.
<dependency>
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<version>${project.version}</version>
</dependency>
Looks like it should work to me. But you might try mvn install instead of mvn package.
My question is how I can solve this problem?
Dependency resolution is done through the local repository so the canonical way to "solve" the problem is to run install from A so that modules will get installed in the local repository.
Now, regarding the following comment
But if I go with install then c war file will also be installed. That one is not accepted in my current project".
Sure, I'm not on your project, I don't know all constraints and rules. But if you decide to use Maven, this is a totally ridiculous policy (seriously, WTF?) and using a system scoped dependency is certainly not a good solution (more troubles later guaranteed). If this policy is real, better not use Maven in that case.
i have a solution: using the dependency with the scope=system
in C pom.xml
<dependency>
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${basedir}\..\B\target\jars\b.jar</systemPath>
</dependency>
and in A pom.xml, put module B on the top like this
<modules>
<module>B</module>
<module>C</module>
</modules>
Doing mvn install only places the artifact into the local .m2 repository of the machine you're running the command on. How can that not be acceptable? I agree with Pascal. If you building A, there should be no reason that a the war is placed there.
On the other hand, if you're using Maven 2.2.x, take a look at the maven reactor plugin? This should help the crazy unacceptable cannot install C.war into your local .m2 repository policy for the current project.
If you have moduleA on your machine say at D:\moduleA and inside moduleA you have created another module say moduleB at D:\moduleA\moduleB , for you to use moduleB inside moduleA you create a dependency in the pom.xml file of moduleA like so:
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
...
<groupId>net.passioncloud</groupId>
<artifactId>moduleA</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>net.passioncloud</groupId>
<artifactId>moduleB</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependencies>
...
To compile the project so you can use it, from the module folder (moduleB) do:
.\mvnw clean install
Here are what I did to solve it:
From intelij , create new module from existing source.
Change the version of dependency B in A.pom same as version of B in B.pom

Maven: Using inherited property in dependency classifier causes build failure

Given three POM files:
C depends on B.
B inherits from A.
I can build A and B
C fails to build because of its dependency on B.
The full source-code and build output is included below for your review.
Here is A's POM:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo</groupId>
<artifactId>A</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>A</name>
<repositories>
<repository>
<id>foo releases</id>
<name>libs-releases-local</name>
<layout>default</layout>
<url>http://foo.net/artifactory/libs-releases-local</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.eclipse.swt</groupId>
<artifactId>swt</artifactId>
<classifier>${swt.classifier}</classifier>
<version>3.6.1</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>windows-x86</id>
<properties>
<swt.classifier>win32-x86</swt.classifier>
</properties>
</profile>
</profiles>
</project>
Here is B's POM:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.foo</groupId>
<artifactId>A</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../A</relativePath>
</parent>
<artifactId>B</artifactId>
<packaging>jar</packaging>
<name>B</name>
<profiles>
<profile>
<id>windows-x86</id>
<properties>
<swt.classifier>win32-x86</swt.classifier>
</properties>
</profile>
</profiles>
</project>
Here is C's POM:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo</groupId>
<artifactId>C</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>C</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>B</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Here is the build output from C:
------------------------------------------------------------------------
Building C
task-segment: [install]
------------------------------------------------------------------------
[compiler:compile]
Nothing to compile - all classes are up to date
Downloading: http://foo.net/artifactory/libs-releases-local/org/eclipse/swt/swt/3.6.1/swt-3.6.1-${swt.classifier}.jar
[WARNING] Unable to get resource 'org.eclipse.swt:swt:jar:${swt.classifier}:3.6.1' from repository foo releases (http://foo.net/artifactory/libs-releases-local): Error transferring file: foo.net
Downloading: http://repo1.maven.org/maven2/org/eclipse/swt/swt/3.6.1/swt-3.6.1-${swt.classifier}.jar
Unable to find resource 'org.eclipse.swt:swt:jar:${swt.classifier}:3.6.1' in repository central (http://repo1.maven.org/maven2)
------------------------------------------------------------------------
[ERROR]BUILD ERROR
------------------------------------------------------------------------
Failed to resolve artifact.
Missing:
----------
1) org.eclipse.swt:swt:jar:${swt.classifier}:3.6.1
I know this issue is related to https://issues.apache.org/jira/browse/MNG-3228 but I'm not sure how to fix it. Please help!
UPDATE:
Adding a classifier to B helped. Now C builds so long as the repository only contains B's jar file. If I upload B's POM file alongside the JAR in the repository, C fails with the aforementioned error (${swt.classifier} not defined). Any ideas?
In a comment you write, "I am expecting SWT's classifier to get resolved at B's build-time, not C's build-time", but that is wrong - you need the classifier at C's build time because C has a dependency on swt (transitive via A). That dependency is only fully-determined by a property, so you have to have a way of evaluating the property in C's pom.
A depends on swt-${classifier}
C depends on A
therefore C depends on swt-${classifier}
therefore C's pom must define the property. It can be defined by a profile (as in A), or manually at runtime (bad for reproducibility), but you can't build C without it.
It's as simple (and puzzling) as that.
If you're expecting the property to somehow get fully "resolved" along the way, and be already well-defined by the time you build C, you are not understanding how Maven treats those properties. It leaves them alone. There was an attempt to do some different stuff in Maven 2.1 (the classifier property expression would be transformed to its value when you installed A), but it was not successful, caused many surprising behaviours, it was reverted for 2.2, and in fact caused 2.1 to be quickly deprecated. For more details, and some hints as to how complicated the problem really is, see the link below.
https://cwiki.apache.org/confluence/display/MAVENOLD/Artifact-Coordinate+Expression+Transformation
Until the Maven developers decide otherwise, I think we will continue to have the behaviour that has been around since 2.0: "Expressions in artifact coordinates are ignored. Users have plenty of rope with which to hang themselves"
Once you get used to it, though, it's not confusing anymore. It's only when you're trying to second-guess Maven that you get surprised.
Maven is trying to find the artifact org.eclipse.swt:swt:3.6.1 but the coordinates aren't being resolved correctly. The error is saying that ${swt.classifier} isn't being recognized from a <properties/> block in your POM.xml. Since that value shows up in a <profile/> block, can you verify what Maven command you are running?
Try this: mvn dependency:resolve -P windows-x86
Also, verify that both the version of SWT and the Classifier are actually correct. The latest version I see on Maven Central is not 3.6.0, but 3.3.0-v3346
This isn't possible as of Maven 3.1.0. Here is the relevant feature request: https://issues.apache.org/jira/browse/MNG-1388
I know this issue is related to https://issues.apache.org/jira/browse/MNG-3228 but I'm not sure how to fix it.
I'm not sure there is a link with this issue, I don't see anything related to profile activation in the pom.xml shown above.
Actually, I'm not even sure to understand the expected result. From where is the classifier supposed to come? Maybe I'm missing some parts but I think you should install/deploy a qualified version of B (with a fully resolved POM) and have C depend on this qualified version.
How would I need to modify B's POM to deploy a qualified version? I am expecting SWT's classifier to get resolved at B's build-time, not C's build-time.
Yes but at C's build-time, C needs B and B's dependencies so the installed/deployed .pom of B has to be fully resolved. At least, that's how I think things can work.
But I must admit I'm not sure how to handle this case exactly and after reading issues like MNG-4140 or the Artifact-Coordinate Expression Transformation page, I'm totally confused.
I suggest to post this on the maven users list for the right way (and I'll follow the thread closely because I think I have some broken POMs using profiles, properties and dependencies to fix now, thanks :)

How do you use Maven to share source code for two projects?

I have a large Java Web Application project using Maven and I need to start a new project that will share most of the same code (so I don't have to repeat work), but not all of it. I'm going to copy the shared code into a new project (let's call it "root"). How do I make my original Project depend on root for source code? I can't just jar it because I want to change the source before compiling.
You should refactor your projects.
Identify the common code
Extract that into its own maven module
2.1. usually web-apps are multi module, so if you are going to share the common library across two web-apps, then separate the common library out into its own group-id
Build and install the jar file into your repository
change the poms of the web-apps to depend on your new library
Create a maven project which contains all your shared code. Keep packaging of this project (in the main pom.xml) as jar. This would help make this project kind of library for your usage.
In all the projects which access the shared code, add dependency for this project according to your needs. (compile, provided).
Now package and install the shared project before you build any of the dependent projects. This will add the shared project to your local repository which can be then used by your dependent projects.
Adding sample pom.xml for shared and dependent projects.
Shared project pom.
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>com.myspace.test</artifactId>
<groupId>com.myspace</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.myspace</groupId>
<artifactId>shared</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shared-module</name>
<description>shared module which contains code shared by other modules.</description>
</project>
Dependent project's pom.
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>com.myspace.test</artifactId>
<groupId>com.myspace</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.myspace</groupId>
<artifactId>dependent-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dependent-module</name>
<description>Dependent module.</description>
<dependencies>
<dependency>
<groupId>com.myspace</groupId>
<artifactId>shared</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Parent project can be added optionally in case such organization is required.
Hope this helps.
Install the shared code, using your current packaging setting of jar:
mvn install
Then, you can create a dependency in the child pom.xml (the code that is not shared) from whatever repository you are installing to.
This is good practice in general not only to avoid repeating work but also in case you want to change the implementation of the shared resources. You can change the logic in one place, install it to the repository, and other projects that depend on that code will use the new code the next time they are compiled.