Relative path for Maven pom versions - maven

Forgive my ignorance here, as I'm new to maven. I have a Remote Repository that my project pom is using to download dependencies from. A general structure of my pom.xml is 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>
<groupId>MVNProject</groupId>
<artifactId>MVNProject</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>
Now I know that if I have to get a new version of the dependency scala-parser-combinators I just have to specify the new version. Something like this:
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>1.0.1</version>
</dependency>
But what I would like to do is, without making any change to pom.xml I'd like to replace my old jar with the upgraded jar in my remote repository(which I'm able to do).
So what I'd like to know is whether there is a way to specify in pom to take whatever version is available in the remote repository for a particular artifact i.e., something like this(and this is just a guess):
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>${CurrentVersion}</version>
</dependency>
Some guidance would be very much appreciated.

If you are using maven2, then using LATEST or RELEASE value in version tag can solve the dependency updation automatically. Albeit , this solution will not work in maven3 (it is deprecated).
If you are using maven3, then you have to update the settings.xml a bit. The snapshots repository will get an addition updatePolicy tag. Something like this:-
<repositories>
<repository>
<id>you-snapshots</id>
<url>http://host/nexus/repos/snapshots</url>
<snapshots>
<updatePolicy>always</updatePolicy>
</snapshots>
<releases>
<updatePolicy>always</updatePolicy>
</releases>
</repository>
</repositories>
Also , There is a Versions plugin for Maven which allows you to update your pom to the latest greatest SNAPSHOTS in visible repositories. It does this by inspecting your pom and comparing against remote repositories and then modifying as required.
It is a useful tool but I would definitely like to see an equivalent to the deprecated LATEST option. I find this kind of dependency particularly useful in continuous integration scenarios.

Some things to notice:
You should not delete a specific release version of an artifact from a remote repository and replace it, like having 1.0.1 in your remote repository, removing it and uploading a different artifact under 1.0.1 again. Maven caches release versions in the local repository, so you will never know which artifact you get.
If you have a newer version, give it a newer version number (like 1.0.2).
Now the way to go is not to use RELEASE or LATEST, but to use the versions plugin to update your dependencies (like versions:use-latest-releases).

Related

Are Maven repository declarations transitive?

Suppose I have the following project, a library which declares some 3rd party repository that it needs to use to grab an artifact.
<project ...>
<groupId>com.mygroup</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>some-id</id>
<url>https://some.repo.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.thirdparty</groupId>
<artifactId>used-at-compile-time</artifactId> <!-- like Lombok, say -->
<version>1.0.0</version>
<scope>provided</scope> <!-- so, not transitive -->
</dependency>
</dependencies>
</project>
Then I have a totally separate project which depends upon that library
<project ...>
<groupId>com.mygroup</groupId>
<artifactId>some-app</artifactId>
<version>2.0.0</version>
<dependencies>
<dependency>
<groupId>com.mygroup</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
Does Maven try to include the repository definition in all dependent projects? Will some-app ever try to access https://some.repo.com?
I'd always been under the impression that this didn't happen, but I've started seeing build failures which contract that belief.
It might initially seem convenient if that's how it worked, but what if the repo was internal and was not publicly accessible over the internet? The project which declared it might use it for some compile-time dependencies, like in my example above. If that repo were dragged in, the dependent project might try to access a repository that it can't for some other non-Maven Central dependencies.
So I can see valid reasons for either behaviour, but as far as I can see, the documentation for repositories doesn't say one way or another what happens, and neither does the POM reference.
Repositories are context aware, in the context of their pom. Dependencies from com.mygroup:library can use the repo's central and some-id.
On the other hand, dependencies from com.mygroup:some-app will only use central.
When running Maven from the commandline, you'll see the repositories it'll try to download the artifacts from (in case the first one fails, it'll go for the next).
When publishing to Central, there are several requirements. However, based on the last paragraph repositories are not banned, you're advised not to use them.
You might wan't to read this classic article: Why Putting Repositories in your POMs is a Bad Idea

How to force maven to always download parent pom

I am using a parent pom to share dependencies and plugins across multiple projects. The parent pom is deployed to our nexus repository. In child project, parent pom is included like this:
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app-parent</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app-web</artifactId>
<version>1.2.0</version>
<repositories>
<repository>
<id>my-internal-site</id>
<url>http://nexus/repo</url>
</repository>
</repositories>
</project>
When parent pom gets updated, would like to keep the same version so child project automatically gets the updated dependencies without updates. However, it seems parent pom is not updated even if I use
mvn clean -U
How do I force maven (maven 3) to always download parent pom from remote repo even if it is already in local repository?
If you have defined such parent which is a release it will be downloaded exactly once. Afterwards it will not downloaded a second time cause release are imutable. As already mentioned you mind need to think about using SNAPSHOT's instead.
you should re-install parent project into your local repo, try run mvn install under app-parent directory!
FWIW I had a case where maven was not downloading a parent but just a .lastUpdated file (which listed a download failure). Even if I ran help:effective-pom it seem to just ignore the fact the parent was undownloadable and absent, and continue on its merry way.
Fix was to upgrade from maven 3.3.3 to 3.3.9

Maven - Never Update Snapshots by GroupID

How can I prevent Maven from ever updating a SNAPSHOT dependency from a particular group?
I'm stuck depending on a library that insists on daily updates to 1.0-SNAPSHOT, but only makes releases every few months. I need changes from a daily SNAPSHOT build that was made recently, but I'm getting fed up with the developers of this framework introducing breaking changes. Hence, I'd like to tell Maven to never update anything from this groupId unless I specifically say so.
Any ideas? The only other approach I can think of is to fork the repo, edit the POM to a version number all of my own, and then depend on that.
Using snapshots this can always happen. But you could install the version you need with a specific version number in your local repository and then use your version. Something like:
<dependency>
<groupId>my.group</groupId>
<artifactId>my.artifact</artifactId>
<version>1.2-TEMPVERSION</version>
</dependency>
It's a workaround and should not go in Production like this.
Assuming you use maven 3, you can use a timestamed snapshot, i.e. replace the dependency with its timestamped version. Something like:
<dependency>
<groupId>my.group</groupId>
<artifactId>my.artifact</artifactId>
<version>1.2-20140401.124312.1</version>
</dependency>
You can also convert a SNAPSHOT dependency automatically to its corresponding timestamped version ("locking a version") using the [versions-maven-plugin][1]:
mvn versions:lock-snapshots -Dincludes=my.group:my.artifact:jar::1.2-SNAPSHOT
Of course, if your repository manager throws out old SNAPSHOTS after a while, this might cease to work when the needed SNAPSHOT is no longer in your local repository.
I think setting the update policy to never for snapshots solves the issue; see here
like
<repository>
<id>my_id</id>
<name>my_name</name>
<releases>[...]</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
<url>http://the-repository.org/repositories/</url>
<layout>default</layout>
</repository>
Haven't (successfuly) tried yet. But I went into the same problem and that's my attempt to handle it.

Adding db2 jars to java webapp using maven

I'm trying to add the following db2 jars to my Java web application using Maven...
db2jcc_license_cu.jar
db2jcc_javax.jar
db2jcc.jar
I'm following the instructions posted in this post...
Can I add jars to maven 2 build classpath without installing them?
I want to use the static in-project repository solution. So far I have...
Created a folder in my root directory named lib. Inside this
directory lives the three db2 jars.
Added the following to my pom file...
<repository>
<id>lib</id>
<releases>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>file://${project.basedir}/lib</url>
</repository>
</repositories>
<dependency>
<groupId>com.ibm.db2.jcc</groupId>
<artifactId>db2jcc</artifactId>
<version>3.8.47</version>
</dependency>
<dependency>
<groupId>com.ibm.db2.jcc</groupId>
<artifactId>db2jcc_license_cu</artifactId>
<version>3.8.47</version>
</dependency>
But when I run a maven install I get ...
[WARNING] The POM for com.ibm.db2.jcc:db2jcc:jar:3.8.47 is missing, no dependency information available
[WARNING] The POM for com.ibm.db2.jcc:db2jcc_license_cu:jar:3.8.47 is missing, no dependency information available
I got the version of the Jars by running a...
java com.ibm.db2.jcc.DB2Jcc -version
Have I specified this version info corretly? Can anyone suggest what I am doing wrong?
The problem is that you didn't install the jars properly in your "project-maven-repository" (i.e. in the folder ${project.basedir}/lib)
Maven stores (when you do mvn install) the jar files in a maven repository. A maven repository have precise hierarchical structure. Here is a simplified vision of this structure:
the artifact groupId+artifactId define the first part of folder path (in the repository) where the artifact is stored.
the artifact version is the second part of the folder path
the artifact version is also a suffix to the artifact name
the artifactId is the artifact name
the packaging is the artifact extension (default is jar)
By default maven use a repository located under <USER_HOME>/.m2/repository
The solution you are trying to setup use another location for the repository : ${project.basedir}/lib and even if it is not the default repository location it is still a maven-repository and so maven is expecting to find the usual maven repository hierarchy under this location.
That's why you need to organize your ${project.basedir}/lib folder just like a maven repository. That's explained in this part of the referenced post:
Use Maven to install to project repo
Instead of creating this structure by hand I recommend to use a Maven plugin to install your jars as artifacts. So, to install an artifact to an in-project repository under repo folder execute:
mvn install:install-file -DlocalRepositoryPath=lib -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...]
If you'll choose this approach you'll be able to simplify the repository declaration in pom to:
<repository>
<id>repo</id>
<url>file://${project.basedir}/lib</url>
</repository>
So you need to do an mvn install to create the ${project.basedir}/lib hierarchy (you can do it by hand, but it's not recommended and error prone).
I your case, the commands to run will be like this: (assuming you put the jar in your HOME_DIR and run this command in your ${project.basedir})
mvn install:install-file -DlocalRepositoryPath=lib -DcreateChecksum=true -Dpackaging=jar -Dfile=<USER_HOME>/db2jcc_license_cu.jar -DgroupId=com.ibm.db2.jcc -DartifactId=db2jcc_license_cu -Dversion=3.8.47
What are the advantages of the approch you choose :
a developer with no maven setup will have the libraries available inside the project sources, under SCM system.
you can easily reference jars that aren't in a public maven repository without the need of something like artifactory or nexus
The drawbacks :
a quite complex folder structure under ${project.basedir}/lib looking very strange for someone not used to work with maven.
you will store the libraries under SCM (lot's of huge binary files)
Another solution would be to download those jars before hand and put them somewhere relatively to your project (like lib directory). Now just tell maven to use those jars. Here the groupId, artifactdId and version are JFYI since they won't be used to download anything.
The merit of this solution is that you won't have to build a maven repository.
<dependencies>
...
<dependency>
<groupId>com.ibm.db2.jcc</groupId>
<artifactId>licences</artifactId>
<version>1.0</version> <!-- Adjust this properly -->
<scope>system</scope>
<systemPath>${basedir}/lib/db2jcc_license_cu.jar</systemPath>
</dependency>
<dependency>
<groupId>com.ibm.db2.jcc</groupId>
<artifactId>db2jcc4</artifactId>
<version>1.0</version> <!-- Adjust this properly -->
<scope>system</scope>
<systemPath>${basedir}/lib/db2jcc4.jar</systemPath>
</dependency>
<dependency>
<groupId>com.ibm.db2.jcc</groupId>
<artifactId>db2jcc_javax</artifactId>
<version>1.0</version> <!-- Adjust this properly -->
<scope>system</scope>
<systemPath>${basedir}/lib/db2jcc_javax.jar</systemPath>
</dependency>
</dependencies>
Refer Link (Japanese): Mavenリポジトリで提供されていないサードパーティJarをどうするか
I guess these jars do not have a pom.xml. Hence the warning. If the jars get packaged and the application works, then I guess you do not have a problem.

Maven can't resolve the dependency it just found

Maven must be losing its mind.
I added a dependency using Netbeans Add Dependency dialog. I searched for jax-rs-ri. It updated the index from central and showed several versions of jax-rs-ri. I selected 1.9.1 and it added this to the pom.xml:
<dependency>
<groupId>com.sun.jersey.ri</groupId>
<artifactId>jax-rs-ri</artifactId>
<version>1.9.1</version>
</dependency>
Looks right, but when I build I get the following error:
Failed to execute goal on project reply-to.test-web:
Could not resolve dependencies for project jms:reply-to.test-web:war:1.0-SNAPSHOT:
Could not find artifact com.sun.jersey.ri:jax-rs-ri:jar:1.10-b03 in
central (http://repo1.maven.org/maven2) -> [Help 1]
I've also tried changing the repository the following with the same results:
<repositories>
<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2</url>
<layout>default</layout>
</repository>
</repositories>
This was working earlier today. Did something just get broken with Maven?
In these cases it's worth to check the local repository (usually c:\Users\<username>\.m2\repository\com\sun\jersey\ri\jax-rs-ri or /home/<username>/.m2/repository/com/sun/jersey/jax-rs-ri) and Central:
http://search.maven.org/#artifactdetails|com.sun.jersey.ri|jax-rs-ri|1.9.1|pom
(The important part now is the "Available Downloads" table.)
So, there isn't any jar file just a zip (and the POM). You should use <type>zip</type> in your dependency like this:
<dependency>
<groupId>com.sun.jersey.ri</groupId>
<artifactId>jax-rs-ri</artifactId>
<version>1.9.1</version>
<type>zip</type>
</dependency>
Since it's a zip maybe you want to unpack it. This answer could help: Unzip dependency in maven
Please note that 1.9.1 is not the latest jax-rs-ri version and your Maven uses 1.10-b03. If you want to force it to use 1.9.1 you have to use <version>[1.9.1]</version> inside the dependency tag.

Resources