I am not sure I really understand the strongest feature of Maven - Dependency Management.
When I am developing a project I need to add all dependencies while I am writing the code. Therefore when building the project with Maven I already have all dependencies downloaded.
What is the point of the Dependency Management then?
Thanks to Maven you do not need to download the dependencies and put it into the lib on Tomcat for instance. It is done automatically by maven. You can see directly in the pom.xml file all you dependencies and also other settings.
Dependencies management is just one of the main feature of Maven. I think you should ask yourself what are the addotional tasks (external libs, deployment, documentation etc...) you are performing in your project and see if Maven can help you on these tasks with its plugins.
Let's assume For your local you have downloaded all the necessary jars and kept in lib.Now you want to move your code into many machines.
So now you have to transfer all the files to another machine.
By mistake if you miss some jars while sending or let's say in future you want newer version of jar.So Do you like to send it to all the machines the jar and remove the older version from lib or write a configuration that automatically does all the things in one go.
Once the project gets bigger you will feel the real essence of Maven.It's just the pom.xml you need to take care all the jar management.
Maven's dependency management makes most sense in an environment where you work on multiple projects, across multiple dev machines and more than one dev.
Imagine the simplest of scenarios:
Project_1
\lib
\log4j.jar
Project_2
\lib
\log4j.jar
Project_3
\lib
\log4j.jar
While you are developing you will need to copy paste the log4j.jar file to all of those projects, which translates to extra disk space used locally and on any SCM you may use, and need to go into each project and define it as a library (add it to the classpath). If you want to change the version of the jar you need to repeat the process.
If you use Maven, all you need to do is
define an online repository (example Maven online repo)
create a pom for your project:
<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>COM.MY.COMPANY</groupId>
<artifactId>NAME_OF_PROJECT</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
Most IDE's already have seamless integration with Maven and no further hassle is needed. And the above steps are only executed once.
Some additional references:
Why maven? What are the benefits?
Why should we use Maven?
Maven Dependency Plugin Example
Related
we are creating a lot of short lived test projects at my work. Dozens of them each day. we have about 10 dependencies that we use internally at our workplace - these are all custom plugins.
I want to get people to not have to mess with their pom.xml for the official dependencies just to get started. so either create a bash script that has all the dependencies on cli...or try to inherit one common xml from all these pom.xml.
I looked at other answers (like Reusing ant-snippets in multi-module maven build), but i dont think these work. im also looking to see if i can use multimodule builds, but then it is even more boilerplate.
i was also looking at maven-dependency-plugin, but I think it only copies/downloads dependencies...u still need to add them to pom.xml.
I also saw some similar questions in gradle area (Add dynamic dependencies via command line), but unsure if it works in maven.
so my question stands - how do I add a large number of dependencies to a maven project, WITHOUT messing with the pom.xml file ?
Any help will be much appreciated.
You can create a parent pom dependency, include all needed dependencies in it and then use it as parent dependency for your small projects, like this:
<parent>
<groupId>com.example</groupId>
<artifactId>some-parent-pom</artifactId>
<version>DEV-SNAPSHOT</version>
</parent>
Do not forget to run mvn clean install to install the parent POM to your local repository.
I am currently learning Maven for a specific project. In this project, I need to have multiple modules (in the sense of a collection of classes and resources) that depend on each-other. Specifically, I need a module to store the classes of a public-facing API (the API is a Java API, as the desktop program can load addons at runtime), another for a set of common classes that are shared between the client and server but that are not part of the API, and of course the client and server themselves need a module each.
Using the system that I used before Maven (IntelliJ Idea's build system), I would simply create different modules and setup dependencies using IntelliJ's GUI. This works well because I can then put the whole IntelliJ Idea project in a git repository, and keep everything nicely tracked together with no fuss and no problems.
When researching how to do this in Maven, however, I ran into some problems. Maven's documentation has a section that seems to explain how to accomplish something similar, but its technique seems to have two problems. When Each sub-project, with its own pom.xml, needs to specify the version of the other sub-projects that it depends on¹. This implies that I need to make many changes all over the project whenever the version changes. This will (hopefully) be quite frequent. As it is perfectly plausible that my project will grow to have hundreds of modules, this is obviously impractical.
Additionally, based on my other research, it seems like a Maven repository is involved in the documented technique. Specifically, it seems like when, for example, the API module is built to be included in the client and server modules it will first be placed in a local repository and then the client and server modules will retrieve it from there. This sounds problematic as the API module will also be published in a public repository (maybe Maven central, I haven't really thought about this too much -- but it will be public in a repo), and this repository step seems like it could end up building the client and server with a published jar rather than the local one, which is problematic for many reasons. (eg. if a developer is making local changes to the api jar, building half the project without those changes is a problem).
Is there some better way to combine multiple modules to mitigate these problems (versions all over the place, and getting wrong jars from repos)? Is it better to modify the technique in the linked documentation instead? Am I misunderstanding something and the problems don't exist?
I have checked DuckDuckGo and all relevant questions that I can find on StackOverflow, and none address either of the two aforementioned problems.
¹:
<dependencies>
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
In your multi-module project, you usually use just one version for all modules. This means that you can define dependencies between modules with <version>${project.version}</version> where the property ${project.version}$ is resolved during the build. Maven builds all the modules in the correct order.
Regarding your first question: you can create a parent pom over your whole project. In this parent pom you can add a dependencyManagement section where you can list your own modules with their version. In your modules you then only need to specify the dependeny without the version.
Here an example:
in parent pom:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>yourgroup</groupId>
<artifactId>yourmoduleA</artifactId>
<version>3.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>yourgroup</groupId>
<artifactId>yourmoduleB</artifactId>
<version>3.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
and if your module A uses module B, you can add in pom of module A
<dependencies>
<dependency>
<groupId>yourgroup</groupId>
<artifactId>yourmoduleB</artifactId>
</dependency>
</dependencies>
I have an application that depends on 2 jar file :
OperatorInterface.jar
Operator.jar
I want to build my project using Maven structure. I've followed the Maven site tutorial to create the structure like so:
mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=source.app -DartifactId=project
I've put my source file FileProcess.java in E:\project\src\main\java\source\app.
FileProcess has dependency in 2 external .jar files but I don't know how to define this dependency in pom.xml.
Here is the content of the pom.xml so far:
<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>source.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Can anyone help me?
First thing you need to install your jars in your maven local repository. You can follow the official tutorial here:
https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
During the installation you will have to choose your own artifactId, groupId and version. You can choose whatever value you want but remember them because you will need those to include your jars in the pom.
After that you can include them in your pom.xml adding these lines under the tag dependencies for each library to include:
<dependency>
<groupId>your_group_id</groupId>
<artifactId>your_artifact_id</artifactId>
<version>your_version</version>
</dependency>
In the case when the JARs in question are your own code rather than third-party, the best approach is to "mavenize" the projects that build them as well. After you do that, running mvn install on those projects will place them in your Maven local repository where they will be available to other local Maven projects who declare them as dependencies.
Avoid adding them to yourpom.xml file straight. When you add .jars using this process, they will automatically reflect in your pom.xml
Steps are -
1. Right click on your project in the file explorer in your eclipse.
2. Go to build Path option.
3. Select configure build path
4. Chose the Libraries tab in the window that appears.
5. Add your .jar file externally.
6. Click ok and come back to your project interface
Update your maven project by pressing Alt+F5 and restart eclipse. Your problem should be solved.
I would take the following route since this is for corporate use. This is the hard and ultimately portable way that sets you up for future Maven usage as it is intended to be done.
1) make those dependent jars Maven projects (because then you can easily version-manage them too using Maven)
2) use a local repository manager and deploy your own projects to it using Maven release management through either the mvn:release plugin, or use a build server such as Hudson to automate the release process with a simple button press which I can highly recommend setting up.
https://maven.apache.org/repository-management.html
http://maven.apache.org/maven-release/maven-release-plugin/
3) mvn:release the dependency jars to your local repository manager so they will be available for other Maven projects
4) you're actually done, when you have a local repository where your deploy your own snapshot and release artifacts to, then your maven build can find your own maven modules and include them in the application dependencies - if you don't forget to configure the repository in the project's pom of course. And your build server if you have one can find them too.
The easy/lazy route is as suggested to manually install the jars in your local .m2 folder where Maven caches dependencies that it downloads, but it is absolutely not a portable solution that will stand the test of time. It won't work when somebody else needs to work on this project until they too install the jars locally. Or if its only you, you need to redo it every time you checkout the project on another computer / as another user. Also you need to update the jars each and every time you make changes to them, everywhere the project is checked out. You may need to do specific setup steps to get it working in an IDE, should you inevitably choose to start to use one.
However if you are having a time-pressure problem, then I would certainly go ahead and do that as a temporary workaround solution to be able to get going.
We started to develop a new web application project and decided to use Maven. This project will use some older internal ant based jar library, so I decided to use Nexus to create our internal repository. I deployed the library to Nexus and linked pom.xml to the new repository and set the dependency to newly created artefact. Maven builds war without problems, I can deploy it on server and launch. So far, everything is working fine.
But now, when I try to call some code of the library, I got a NoClassDefFoundError exception.
java.lang.NoClassDefFoundError: HTTPClient/HTTPConnection
at com.logica.imfplus.authentication.client.HttpConnection.connect(HttpConnection.java:217)
at com.logica.imfplus.authentication.client.HttpConnection.<init>(HttpConnection.java:135)
at com.logica.imfplus.authentication.client.LoginController.getResponse(LoginController.java:402)
at com.logica.imfplus.authentication.client.LoginController.login(LoginController.java:169)
at com.logica.imfplus.authentication.client.AuthClientAPI.internalLogin(AuthClientAPI.java:416)
at ...
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.ClassNotFoundException: HTTPClient.HTTPConnection
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1718)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1569)
... 38 more
I googled little bit and added dependency manually to the missing library.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.3</version>
</dependency>
But I got another various NoClassDefFoundError exceptions. All problem seems to be more complex.
I think I understand the problem: The jar library has it's own internal dependencies defined by ant, but they are not visible for maven so they are still missing. But I don't know, how to solve it.
If I am right, I was thinking of examining all those internal dependencies manually and add them to pom.xml. But it seems like dirty solution and I don't feel safe about it. I also don't want to add mess to my pom.xml, if I don't have to. Is there any cleaner way, how to do it? Can maven examine and resolve internal dependencies of non-mavenized jar library defined earlier by ant?
I am still learning with maven, so solution is maybe obvious. I still didn't find anything useful.
EDIT:
Solution found and working. I created a new pom.xml with defined dependencies as suggested and (manually) uploaded to Nexus. Now transitive dependencies are correctly resolved and downloaded by maven. Here it is fyi. (There was in fact only one dependency to define.)
<?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>com.logica.imfplus.authentication</groupId>
<artifactId>authenticationClient</artifactId>
<packaging>jar</packaging>
<version>1.3.1.0_8</version>
<name>IMFplus authenticationClient</name>
<dependencies>
<dependency>
<groupId>net.sf.grinder</groupId>
<artifactId>grinder-httpclient</artifactId>
<version>3.9.1</version>
</dependency>
</dependencies>
</project>
I still got some ClassNotFoundException, but it is probably caused by some collision in libraries, this is different story.
The ideal way to do this is to rebuild your internal library with a pom of its own where you specify all its dependencies. Then you should point that pom.xml to your nexus repository and deploy it (as in mvn deploy). This way, the pom.xml will get published too in nexus and any application using the maven dependency will download too every dependency that your legacy library carries with it.
In general, you should only be deploying your internal artifacts to your internal Nexus. 3rd party artifacts should be obtained via your internal Nexus that acts as a Proxy Repository to the public Nexus repositories. These days, you can normally find most 3rd party artifacts in a public repository somewhere.
When it comes to Maven, it uses what's called transitive dependencies, which in short means that if artifact A depends on artifact B and you create a new artifact that depends on A, you'll also depend on B.
For this to work it's important that artifact A is built with Maven because the dependencies are captured at build time. The alternative is that you manually deploy the pre-built artifact, in which case the dependency information has been lost and you'll have to define it yourself by creating a pom for the 3rd party artifact.
Assuming the dependencies are correct (you can list them with mvn dependency:list), when you build a WAR with Maven, all the compile and runtime dependencies will be included in the WEB-INF/lib directory.
A good solution for this problem is to create a pom.xml for the ant project that declares the dependencies correctly and use the aether ant tasks to deploy the jar from the Ant build to the Nexus instance.
Then you can use the Ant built Jar from Maven like any other dependency and it will even have the correct transitive dependencies managed automaticall.y
With maven is it possible to have a top-level project who's packaging type is "war" which will build itself and all of its dependent modules (packaged as jar) and have the build generate a project.war file?
Much of the documentation examples and other examples I've seen often use a top-level project with packaging type of "pom" and the project only serves the purpose of tying the modules together. Can I avoid this?
So basically I need something which is effectively like declaring a <module>my-module</module> for maven to build, and in that same POM, declaring a <dependency>...my-module's artifact...</dependency> on that same module which needs to be built. Maybe a plugin as someone already suggested?
Update: In other words (to simplify the problem): If I have project A and project B, where project A depends on project B - is there a way for me to execute a build on project A and also have it automatically build project B (and include project B as its dependency - creating projectA.war which contains projectB.jar)?
super_aardvark suggested correct way but,
For requirement I would suggest following structure It is suitable and good structure also :
Consedering ProjectA as project-webapp , ProjectB as project-core
You can have following structure :
Your Grand 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>com.mycompany.project</groupId>
<artifactId>project</artifactId>
<version>2.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Project Repository System</name>
<description>Project Repository System R2</description>
<modules>
<module>project-core</module>
<module>project-webapp</module>
</modules>
</project>
Your WebApp 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">
<parent>
<groupId>com.mycompany.project</groupId>
<artifactId>project</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>project-webapp</artifactId>
<version>2.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Project Web Application</name>
<description>Project Repository</description>
<dependency>
<groupId>com.mycompany.project</groupId>
<artifactId>project-core</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
</project>
Your Core Project:
<project>
<parent>
<groupId>com.mycompany.project</groupId>
<artifactId>project</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>project-core</artifactId>
<version>2.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Project Core</name>
<description>ProjectCore</description>
</project>
Your Directory structure should look like:
-------Grand Parent.pom
|
|--------project-webapp
| |
| project-webapp.pom
|
| -------project-core.pom
|
project-core.pom
From parent pom execute mvn clean install it will build both the web-app and core project
That's not really what a top-level project is for. Your WAR project has dependencies, which are the artifacts (e.g. jars) that will be included in the WAR (in WEB-INF/lib) when you run 'mvn package'. Your WAR project pom can have the top-level project as its parent, but it shouldn't be the parent of its dependencies. You may want to have that top-level project be the parent of both the WAR project and of the JAR projects that are dependencies in the WAR.
This is not possible in Maven 1, 2 or 3.
I'd recommend to give up this idea, because Maven's whole purpose is to enforce standardized development process. Don't fight the structure, just create a parent POM module and make the WAR module and other dependencies underneath it.
When you have a multi-module project and you're doing work in several modules simultaneously it can be tedious and error-prone to make sure all the necessary dependencies are updated.
In my situation, I would like my build system to detect changes and only build the modules that are necessary. One way this might be possible with maven is for someone to write a custom plugin that does this, which doesn't seem insurmountable given there are already complex plugins available, like the maven release plugin.
Others have already mentioned the aggregation pom concept, which is repeatable and does produce the necessary artifacts. But sometimes you end up building more than you really need to.
Maven profiles can help and here's a good article in that regard:
Using Aggregate and Parent POMs
Also note in the article the concept of the batch pom, which I was not previously aware of.
Remember, mvn clean install will push your artifact into your local repo. So if module A depends on module B, as long as your local repo has the latest build of module B then you should be all set. So, if there were an external tool that was watching for changes to module B and automatically built it when there were and pushed those changes into the local repo then when module A was rebuilt it would pick up those changes. There are continuous integration (CI) tools that can do this, like Jenkins. But you would need a local install to have this work directly with your local repo. It's still an option, though.
Another option would be for the CI environment to push your builds to an external maven repo (or even one you setup locally with something like Nexus). Then you setup your CI builds to pull from that location as well.
So, there are solutions that rely on other tools or potential plugins to do what you want - just depends how much time and effort you want to invest to get it all setup. But, once you get over that hurdle you'll have a system (and knowledge and experience) that you can use on all your projects, not to mention you'll be familiar with how many development shops/teams work.
I would recommend researching continuous integration and continuous delivery for more information and ideas.
In parent pom, you have to define a sequential order of modules to be compiled. You can add a war packing module to the last in that list. It will simply aggregate all previous compiled code together.
Not really - (Well, I can think of a couple of ways, but I'd not use them as they're convoluted and go against the basic ethos/practices of Maven).
Don't forget that the other purpose of the top-level pom is to provide a single point to set common details such the particular versions of dependencies used in the modules of the project.
NetBeans has an option that allows you to do exactly this with Maven projects but I don't know any pure Maven solutions. I think that the task is more suited for an IDE, because it knows for what depended projects you have the code (based of what projects you have opened in the workspace). How would Maven itself differentiate between a dependency that you want to build and one that needs to be fetched from the repository. And for those that need to be built, where should it look for the source code?
Anyway, another solution to the problem, that I used successfully a few times, is to create a simple shell script that navigates to your projects folders and starts the build then it waits for it to finish then proceeds to the next project and so on.