Resolving dependencies ad-hoc in multi-module maven project - java

I have an multi-module project in maven, and when I run normal goals on it, everything works fine. For testing, I have an module mytest, and this module is run fine when I run mvn package in the parent directory.
But for not compiling and running everything everytime, I would prefer to run the tests standalone, and to take the packaged files as the dependencies. But if I try to do so using mvn test -Dtest=simpleTest in the test-submodule-directory, the tests are not run, because it can't find the dependencies. After a mvn install in the parent-directory, it finds them, but uses the artifacts from the repository - a behaviour I do not want, because I have to run install everytime. And if I try to run the tests from the parent directory with mvn test -Dtest=simpleTest, it does not find the tests in the other modules, and stops, or, if I add an project-list with -pl test, it just does not find the dependencies again.
Is there any way to run a maven test in a specific submodule, that has dependencies for other submodules, without installing the submodules to the local repository? It would be possible to archieve this by building the comand-line-call for the test onself, but that seems very time-consuming.
/EDIT:
To describe the problem more exactly, I'll add source of a minimal project.
There is a parent 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>minimalproject</groupId>
<artifactId>minimalproject</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>minimalproject</name>
<modules>
<module>datamodule</module>
<module>testmodule</module>
</modules>
</project>
a Pom for the module that needs to be tested (in a real-world project, there would be more similiar modules):
<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>minimalproject</groupId>
<artifactId>datamodule</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>datamodule</name>
</project>
and a Pom for the modules that tests:
<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>minimalproject</groupId>
<artifactId>testmodule</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>testmodule</name>
<dependencies>
<dependency>
<groupId>minimalproject</groupId>
<artifactId>datamodule</artifactId>
<version>0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
There are now two classes, one in datamodule/src/main/java:
public class Thing{
int i = 5;
}
and one in testmodule/src/test/java:
import org.junit.Test;
import junit.framework.Assert;
public class MyTest{
#Test
public void testThing(){
Thing t = new Thing();
Assert.assertEquals(5, t.i);
}
}
When I now run mvn package in the parent folder, everything works fine. But if I run mvn test in the testmodule folder, it crashes because it can't resolve the dependency to the datamodule. If I run mvn install in the parent folder before, it works - but takes the old installed version.
What I want is the ability to run the integration-test in the testmodule, without calling other tests or invoking the build-process of other parts. Is there any possibility to do so?
/EDIT2:
I found out when googling the issue, that one could have done that in maven 2 with the reactor plugin: Build single module from multimodule pom . Anyways, this plugin is not used anymore (http://maven.40175.n5.nabble.com/VOTE-Retire-Maven-Reactor-Plugin-td5789172.html). In fact, like proposed in the first answer, people say one could use profiles to do this: How do you perform a reactor build in Maven3 without a root project?
But, when adding a profile like this:
<profiles>
<profile>
<id>onlyRunTests</id>
<modules>
<module>testmodule</module>
</modules>
</profile>
</profiles>
And runnning it with mvn test -P onlyRunTests, still everything which comes before testing the testmodule (so compiling and running the datamodule) is executed. Unfortunately, this is the behaviour not wanted - I want to call integration tests, not the unit tests from the other modules. So is there any way to do so?
/EDIT 3:
There were two other promising ways to avoid this Problem: building with --pl e.g. --pl testmodule --also-make-dependencies. This does not work either, it does not build the dependencies.
The other way would be defining a path (with systemPath) of the depencies. This does not work, as it only works with absolute paths, and this would make the pom unexecutable under all other systems.

The problem in your build is (based on the example pom files) not a multi-module build cause if you have a multi-module build all your childs need to have a parent which is not the case. In your case you are having an aggregator which is not what you need.
The test module should look like this:
<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>minimalproject</groupId>
<artifactId>minimalproject</artifactId>
<version>0.1-SNAPSHOT</version>
</parent>
<artifactId>testmodule</artifactId>
<name>testmodule</name>
<dependencies>
<dependency>
<groupId>minimalproject</groupId>
<artifactId>datamodule</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
and your datamodule should look like this:
<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>minimalproject</groupId>
<artifactId>minimalproject</artifactId>
<version>0.1-SNAPSHOT</version>
</parent>
<artifactId>datamodule</artifactId>
<name>datamodule</name>
</project>
Now if you look at the root and try mvn clean package you should see that the testmodule is build after the datamodule. This is needed as you already determined to let Maven calculate the build order of the artifacts.

Related

Maven not using newer locally built/installed dependency

I've been hitting an annoying issue recently. I have two different maven projects checked out to my development machine. One project depends on the other (let's say Project A depends on Project B), and I actively make changes to both projects. Sometimes though, Project A won't pick up the latest Project B changes. Let's say I make some changes to Project B, I build/install it with...
mvn clean install
I even check my local ~/.m2/repository to see that the jar has been updated. But Project A will still continue to use an older version of Project B. Even though it was just updated... If I remove the entire Project B folder, as in...
rm -rf ~/.m2/repository/project-b/version/
And then build/install Project B again, then at this point my problem is gone. Project A will finally make use of the updated Project B. But I don't want to have to go through this exercise every time. Any clues what could be causing this?
Edit: Here's more or less the relevant parts of the pom.xml for both projects. It's extremely basic.
Project A pom.xml
<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>org.opendaylight.mdsal</groupId>
<artifactId>binding-parent</artifactId>
<version>3.0.10</version>
<relativePath/>
</parent>
<groupId>company.group</groupId>
<version>1.0.0-SNAPSHOT</version>
<artifactId>project-A</artifactId>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>company.group</groupId>
<artifactId>project-B</artifactId>
<version>3.1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>
</project>
Project B 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>company.group</groupId>
<artifactId>project-B-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
</parent>
<groupId>company.group</groupId>
<artifactId>project-B</artifactId>
<version>3.1.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
...
<dependencies>
</project>
Since you are using IntelliJ in the right upper corner there is this maven menu, where you can reimport all dependencies which helps me in this case :)
Try below maven command for loading all updated libraries,
mvn clean install -U

What is the proper way to specify that a JAR is provided by the application container so it should not be included in an EAR or WAR file?

I have a JAR that depends on another JAR that is provided by the application container (so it is not included in the WAR file). But it needs to be included in the package when that component is used in a different standalone application.
What is the proper way to specify that a JAR is provided by the application container so it should not be included in an EAR or WAR file, but included when packaged in a standalone application?
Here is the dependency tree:
WAR(app1) JAR(app2)
+ +
| |
v v
Dependency
+
|
v
Dependency (provided by the application server)
This is the pom.xml of the JAR that depends on a JAR provided by the application container, but required if building a standalone application.
<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>testgroup</groupId>
<artifactId>moduledao</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
</dependency>
</dependencies>
</project>
This is the pom.xml of the web application:
<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>testgroup</groupId>
<artifactId>mywebapp</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>testgroup</groupId>
<artifactId>moduledao</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
This is the pom.xml of the standalone application:
<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>testgroup</groupId>
<artifactId>standaloneapp</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>testgroup</groupId>
<artifactId>moduledao</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
As others said, you need to set the scope.
BUT
In order to use it in 2 different cases, you need to declare 2 profiles, the application container based one and the standalone application one which will have a propery named e.g. profile.scope.
In first case it will be provided and compile in second and you must use each profile respectively depending on the case you need to run.
sth like this
<profile>
<id>appServer</id>
<profile.scope>provided</profile.scope>
</properties>
</profile>
<profile>
<id>standaloneApp</id>
<profile.scope>compile</profile.scope>
</properties>
</profile>
and then
<scope>${profile.scope}</scope>
You need three projects:
"core": Application Core with all the logic with default packaging
"web": Web Application with war packaging
"standalone": Standalone Application with default packaging
In core pom.xml you define all dependencies as they are required for your application logic, with default scope.
In web pom.xml you define dependency on core with default scope, and additionally you define all dependencies that are provided by container with <scope>provided</scope>. These additional dependencies will basically override dependencies in core and will end up not being bundled in .war. If you have any tests, they will run with the provided dependencies - this can be important if the versions are different and you want to make sure your app works with the versions that will be on the application server. This project might also contain some additional code for running within application container.
In standalone pom.xml you define dependency on core, and additionally any dependencies necessary for it to run standalone, such as command-line parsing library, etc. Additionally you'll define here settings for running this as standalone application, such as maven-jar-plugin to include main class in manifest. This project might also contain some additional code for running standalone.

Is there a way to build all my Maven projects with just one command ?

I am really new with Maven, and I have set up 2 maven projects, one of them is my utility API, the second is Jersey API. I installed utility API as part of my local Maven repository and added it in the pom.xml file.
Everything is working fine, it's just that when I want to build/run tests I need to go to each directory where projects are and run the commands. Is there a way to run one command or reconfigure the project in a way, so that I am able to process everything just from my REST API directory?
Eg. mvn clean test ... something ... -> goes and tests both of my projects.
Once again, I am new to Maven, but also I did a research and could not find a proper useful information that could help me out. If this is one of those questions that needs to be close, could you please at least provide me with some more information before closing it ? Thank you.
You can use multimodule maven projects. You define a structure like this
/
pom.xml (A)
util-api
pom.xml (B)
jersey.api
pom.xml (C)
In the children pom's you specify a <parent> node.
(A) 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mygroup.id</groupId>
<artifactId>myparentartifact</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
...
<modules>
<module>util-api</module>
<module>jersey-api</module>
</modules>
</pom>
(B) 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>myparentartifact</artifactId>
<groupId>mygroup.id</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>util-api</artifactId>
<packaging>jar</packaging>
</pom>
(C) 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>myparentartifact</artifactId>
<groupId>mygroup.id</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>jersey-api</artifactId>
<packaging>jar</packaging>
</pom>
With this configuration you can build all modules with one command: mvn clean install
You can use Maven's aggregation pom.
Are you looking for a command , which can run your test and also build you app with all the module included ?
I thin you are looking for mvn clean install.
Please make sure, you say this in the highest maven pom.xml, which all include all the dependencies.
There is an option to combine related projects into one by having a top level POM using modules feature.
<modules>
<module>utility-api</module>
<module>Jersey-api</module>
</modules>
and can compile and run the test cases with
mvn clean install
You need to create parent POM for your 2 modules with
<packaging>pom</packaging>
so when you run for example mvn install on your parent POM it will run it on it's every child module.
More info on working with multiple modules here

how to make maven build dependent project

I have project with several dependencies on other project.
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>group1</groupId>
<artifactId>artifact1<artifactId>
<name>RealtyRegistry</name>
<packaging>war</packaging>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>group1</groupId>
<artifactId>artifact2</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>group1</groupId>
<artifactId>artifact3</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
All of them developed by me simultaniously. I add edition to files of all of project and i need to build main project together with dependent ones. How to do that for projects without tree structure?
There can be 2 or more covering trees for projects hierachy, for example: A depends on B,C; D depends on C,E; A and D are independent.
You can build multiple projects together using "Modules". Normally, you would do this by creating a "mother" project with <packaging>pom</packaging> and adding your real project as modules using the <modules> tag. Then, when you build the "mother" project, all modules are automatically built in the right order.
Here is an example from the Maven by Example book:
<groupId>org.sonatype.mavenbook.multi</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>simple-weather</module>
<module>simple-webapp</module>
</modules>
Note that this requires you to have your modules in subfolders that are named accordingly. For example, you would have the "mother" pom in some folder:
/.../my-project/
and the modules in:
/.../my-project/simple-weather/
/.../my-project/simple-webapp/
For more information, read Chapter 6. A Multi-module Project of the book, it's freely available on the Sonatype website.

Unit more then one project to one maven project

i have 3 maven project (starto.commons,starto.hibernate,starto.server) that use some same dependencies and two of then use the thread project(commons).
i try to unit the 3 project to one big maven project (lets call him starto.bigMavenProject for the example)
i mean that:
1) every project stay project on its own bat use the starto.bigMavenProject pom for dependencies
2)when i build (run mvn insatll) starto.bigMavenProject it's build the all three project (starto.commons,starto.hibernate,starto.server).
thanks in advance.
It sounds like you want a Maven parent project for your three projects. I'd suggest taking a look at the POM documentation on inheritance as well as Sonatype's simple example.
Basically, you want a POM for start.bigMavenProject something like this:
<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>starto</groupId>
<artifactId>bigMavenProject</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<modules>
<module>commons</module>
<module>hibernate</module>
<module>server</module>
</modules>
</project>
Though you may need to do some additional tweaking to, e.g., your directory structure, etc.
The key thing is your parent POM should have <packaging>pom</packaging> and define each sub-project as a module.

Categories

Resources