Maven - Handling Snapshot Dependencies - java

I have the following maven dependency in my web application POM, which in turn should pull other dependencies:
<dependency>
<groupId>com.my.libraries</groupId>
<artifactId>my-libs</artifactId>
<type>pom</type>
<version>1.6-SNAPSHOT</version>
</dependency>
NOTE I had release 1.5 for my-libs artifact previously pulled during an older build. But I have later upgraded the version to 1.6-SNAPSHOT. mathlibrary artifact wasn't present in 1.5 release.
I am expecting some jars to be present as part of my-libs artifact verson 1.6-SNAPSHOT which wasn't present in 1.5 - the pOM is below:
<!-- all the usual POM descriptionsm for my-libs -->
<groupId>com.my.libraries</groupId>
<artifactId>my-libs</artifactId>
<version>1.6-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- continues... all normal stuff, nothing to see here :'/ -->
<dependency>
<groupId>com.my</groupId>
<artifactId>mathlibrary</artifactId>
<version>1.0</version>
</dependency>
<!-- continues -->
I expected that mathlibrary jar would be pulled if I do mvn package for my project. But when I looked at the lib folder for my webapplication the jar wasn't there. I then checked my .m2 directory contents and it seems that only version 1.5 is present, so 1.6-snapshot wasn't automatically installed. From here, I am thinking that if a release version is pulled before, it doesn't pull the next SNAPSHOT?
After I manually installed my-libs artifact using mvn clean install - on the next build for my web application it pulled the jars correctly. Does this mean that my package phase is defined not to automatically pull the SNAPSHOT dependencies? or is this something expected (i.e. I have to manually run install phase it if it's not a release version) ?

Use mvn package pulls all SNAPSHOT dependencies from your local repository (and also updates your local repository from a remote repository every 24 hours, if the artifact comes a remote one).
I do not really understand what you mean by "manually installed my-libs" because there is no automatic way to install artifacts (except for CI servers, that install/deploy on checkin). If you want to use an artifact (like my-libs), you need to build it and put it in the local repository -- and you do this by using mvn install.

Answer to your question depends on which packaging you are using in your pom.xml and on which plugins have executions tailored to the packge phase. When dependencies are processed, Maven usually resolves them, which means that corresponding jar files will be in your local repository.
Getting jar files in your target folder (as is, or unpacked) is a result of some plugin's work (such plugin would execute a mojo at prepare-package or package phase (usually). So, make sure you use proper packaging (such as war) or e.g. "assembly" plugin (which can repack dependencies for you).
To make your dependency artefacts available for resolution and further use, you should either deploy them to a remote repository, or install them to local repository.

After reading #JFMeier answer on this, I did the following:
1) Removed all release/snapshots from my .m2 directory.
2) Changed my web app POM to use 1.5 release for my-libs
3) Kicked off the build.
4) Once the build finishes, I confirm that mylibraries jar hasn't been deployed in my final web application directory in tomcat's WEB-INF\lib
5) Repeated steps 2-4 - BUT changed the version to 1.6-SNAPSHOT for my-libs.
6) Now I can see the expected result.

Maven is only getting into repository (either global or local) when you make a mvn install. With Maven Install, Maven checks if all the POM libraries are present in your project and downloads from repositories into your project if some are missing. If you do a Maven package, it only packages the libraries present in your project.

Related

Using Maven dynamic versioning to release a library

Since Maven 3.5.0, it's possible to use some variables inside the <version> tag :
https://maven.apache.org/maven-ci-friendly.html
Let's say I have <version>${revision}</version>, in a library project (it produces a jar to be used in other projects, it's not just a web app or a batch application).
When I build and publish my library v1.0.0 (mvn deploy -Drevision=1.0.0-release) the artifact is named "my-library-1.0.0-release.jar", but the pom.xml metadata inside the jar is still at <version>${revision}</version>, are there some use cases where this will make my library unusable ?
EDIT : same question if my library is published in a SNAPSHOT repository and used from there as a dependency to other projects.
There will be problems with using your library as a dependency and publishing to shared artifact repository (e.g. Maven Central) because your pom.xml doesn't match the artifact version. Perhaps some artifact repositories will work (e.g. local Artifactory proxy with custom config) but it's asking for problems.
This is mentioned in the Maven CI Friendly Versions you linked to, under "Install/Deploy" chapter which suggests to use flatten-maven-plugin:
If you like to install or deploy artifacts by using the above setup you have to use the flatten-maven-plugin otherwise you will install/deploy artifacts in your repository which will not be consumable by Maven anymore.
Had this same issue. Solved with this maven extension (in an extension.xml file):
<extensions>
<!-- this extension ensures ${revision} gets replaced with the proper value in the output pom files-->
<extension>
<groupId>fr.jcgay.maven.extension</groupId>
<artifactId>unique-revision-maven-filtering</artifactId>
<version>1.2</version>
</extension>
</extensions>

add external jar to our dependency

There is a jar file lets say "abc.jar" which maven dependency does not exist(ie created a jar by using java command of own classes). I want to add this jar as maven dependency so that at build time it will automatically copy that jar in lib folder as like other maven dependency. how i will do. please help .
Add it as a dependency with a system scope. See the docs here.
However, rather than adding it as a system dependency it might be better to mavenize the jar itself, then you can build and install it into your dependency management system.
Also, see this question: Can I add jars to maven 2 build classpath without installing them?
You can use the systemPath attribute in the dependency tag in the POM file of your project.
In your pom.xml, use the following snippet corresponding to abc.jar:
<dependencies>
<!-- Other dependencies -->
<dependency>
<groupId>abc</groupId>
<artifactId>x</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>{path_to_abc.jar}</systemPath>
</dependency>
</dependencies>
The scope parameter corresponding to this artifact must be set to system, for the artifact to be picked up from the specified systemPath.
Hope this helps!
A normal maven dependency is always resolved by looking into a repository. So you must put your JAR file into a repository.
You could install your JAR into your local repository. Have a look at the install plugin. The install-file goal is your friend.
If other developers also need this JAR (because they are working with the same project), they either need to install it locally too, or - better - you deploy the JAR to a remote repository. Have a look at the deploy plugin. Here the deploy-file goal is your friend. For deploying artifacts, you need a repository manager like Nexus or Artifactory.
However, a dependency could also have the system scope (look at the other answers).

Embed local jar files in maven project

I have some local jar files from a non-maven project which I wish to include in my maven-based eclipse project.
These jar files are undergoing a lot of change as me and my project buddy attempt to 'fix' them, so I'd prefer not to upload them to a repository to avoid making a maven version of this non-maven project if this is possible.
Of course, the jar files need to be embedded in the resulting deployment jar. We did this before using Ant which let us specify that those jar files should be included.
How do you do the same thing in maven? Take into consideration that we do have maven dependencies too which all work fine and aren't required in the deployment. Some answers I've seen don't allow for this requirement.
Here's one of my attempts - the problem is that the jar does not get embedded:
<dependency>
<groupId>se.krka.kahlua</groupId>
<artifactId>kahlua-core</artifactId>
<version>5.1_2.1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/kahlua-5.1_2.1.0-core.jar</systemPath>
</dependency>
System paths are a very bad idea. When anybody else checks out your projects, he cannot build it anymore. (I always see such crap in many companies). The right solution would be to install the jar into the local repository:
$ mvn install:install-file -Dfile=[JAR NAME] -DgroupId=[GROUPID OF
JAR] -DartifactId=[ARTIFACT OF JAR] -Dversion=[VERSION OF JAR]
-Dpackaging=jar
In your project, you just add the dependency as usual after you installed the jar into the local repository.
<dependency>
<groupId>[GROUPID OF JAR]</groupId>
<artifactId>[ARTIFACT OF JAR]</artifactId>
<version>[VERSION OF JAR]</version>
</dependency>
You can use maven-install-plugin to install kahlua-5.1_2.1.0-core.jar into the local repository then this dependency will behave as any other, see http://maven.apache.org/plugins/maven-install-plugin/usage.html. Or make a remote repository in a location shared with your buddy and let him upload his jar there with maven-deploy-plugin:deploy-file (http://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html) each time he changes it and add this repository to your pom. You can use SNAPSHOT version if this jar changes often

Maven: Add local dependencies to jar

I have a dependency
<dependency>
<groupId>de.matthiasmann</groupId>
<artifactId>twl</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/TWL.jar</systemPath>
</dependency>
Then I execute mvn assembly:assembly. All natives files and remote maven libs are added, but there is no this jar.
UPDATE
When I am trying to run app by java -jar myjar.jar. It returns an error that there is no class from the above dependency (NoClassDefFoundError : de.matthiasmann.twl.ForExample).
I want to add classes from this jar to myjar.jar (the same what maven does with remote dependencies). How I can configure maven to do that?
See Maven 2 assembly with dependencies: jar under scope "system" not included for why system dependencies are not included and how you can work around it, specifically the mvn install:install-file code is what you want.
You cannot use systemPath, unless your Java EE server/container has that jar configured.
Remember that maven is development and compile time only. Once the war file is built, maven has no effect except for having placed all the desired jars into the WEB-INF/lib folder.
When you specify system scope, it means that it is your responsibility to ensure that the jar is present when the war is deployed. You already have a framework to do that and you do not wish to encumber your build dependency with that jar, but you have to make it available thro Maven only during development.
The other similar scope is "provided". e.g., JBoss or your corporate common deployment Tomcat framework already provides many of the jars like Spring and Hibernate that are loaded by the server startup and common to all apps in the server. Therefore, you would not want maven build to include those into the war file.
The right way, Maven gurus would tell you. is to have your own maven server and build whatever artefacts you need into that server. However, occasionally that is not possible.
Therefore, on such occasions, I create project level repository that is distributed with the project and checked into version control. I run the command mvn install to create a project level directory called, say, "project-repo".
http://maven.apache.org/plugins/maven-install-plugin/examples/specific-local-repo.html (Due to familiarity, most of the time, I build the repo by hand rather than run mvn install).
Then in the POM, I specify file://${project.basedir}/project-repo as one of the repositories. The caveat with this is that in Windows, the slashes other than the pair after "file://" has to be back-slashes when referring to Windows file system paths.
<repositories>
<repository>
<id>my-repo1</id>
<name>my custom repo</name>
<url>http://ho.ho.ho</url>
</repository>
<repository>
<id>project-repo</id>
<name>my project repo</name>
<url>file://${project.basedir}\project-repo</url>
</repository>
</repositories>
YOu can implement this in many ways refer the blog below
http://blog.valdaris.com/post/custom-jar/
If you have such an dependency the best solution is first to use a repository manager and simply put that dependency into the repository manager and afterwards use it as simple dependency.

Java to Maven project conversion related details

I am having a java project with a ant build file, using this ant file i create an ejb of the project and deploy it on the jboss server.
Now I am planning to use maven and convert this existing project which consist of nearly 28-30 jar's in its class path(jars related to ejb3, hibernate, jboss, etc).
I can easily do it using eclipse i.e right click project goto maven and click Conver to Maven.
A pom.xml is generated and the MavenClassPath Container is also added to the project.
Now I want to know how to get rid of those 28-30 jar's present in the lib folder of the project and in the classpath. i.e. I want my pom.xml handle all the dependencies.
Does Maven provide any mechanism to achieve this goal while converting the project or I have to add all of these jar dependencies one by one manually in the pom.xml file.
The intention of doing this is I want to have common maven remote repository where the jars will be stored and each developer machine will point to it through their maven project.
Thanks
I think you're after a repository manager like Nexus (I use Nexus, it seems to be the most popular http://nexus.sonatype.org/ ).
Nexus can be used as:
A proxy repository (for Maven Central, etc)
A repository for your own releases.
Nexus provides user management for your developers to release builds into the repo.
Developers will then point their Maven settings.xml file to your Nexus repository, and all their dependencies will come from here (Nexus will cache them).
I'm afraid you will have to configure the dependencies individually, but that is a good thing, because you should pay attention to what version ranges you are interested in for each dependency.
Any jars which can't be found in Maven Central, etc, you can add to your own Nexus repository .
Ofcourse there are alternatives to Nexus, but I haven't used any.
HTH
The most important thing i can recommend is to use a Maven Repository Manager (Nexus, Artifactory or Achiva or other..).
Second your pom conversion via Eclipse shows me that you are not using an up-to-date Eclipse nor an up-to-date Maven Plugin for Eclipse. The best thing would be use Eclipse-Indigo (m2e is the newest and greatest).
Furthermore you have to go through all your jar's and add them step by step to you pom (dependencies) and see if your project can be compiled. This should be checked on command line not inside Eclipse.
After you got a working pom.xml file put it into your version control and check if you can remove some of your added dependencies based on transitive dependencies. After that you can finally delete your lib folder.

Categories