Why is maven downloading dependencies from repository even if the jar exists on my local repository(one reason could be that jar doesn't have a pom), is there a way to get bypass that except with the -o option?
Why is maven downloading [SNAPSHOT] dependencies from repository even if the jar exists on my local repository
Because that's the expected behavior with SNASPSHOT dependencies. Unlike fixed versions, Maven will periodically try to download the most recent version of a given SNAPSHOT. That's extremely useful when you're depending on a project that is under active development. From the Maven Reference:
3.3.1.2. SNAPSHOT Versions
Maven versions can contain a string
literal to signify that a project is
currently under active development. If
a version contains the string
“SNAPSHOT,” then Maven will expand
this token to a date and time value
converted to UTC (Coordinated
Universal Time) when you install or
release this component. For example,
if your project has a version of
“1.0-SNAPSHOT” and you deploy this
project’s artifacts to a Maven
repository, Maven would expand this
version to “1.0-20080207-230803-1” if
you were to deploy a release at 11:08
PM on February 7th, 2008 UTC. In other
words, when you deploy a snapshot, you
are not making a release of a software
component; you are releasing a
snapshot of a component at a specific
time.
Why would you use this? SNAPSHOT
versions are used for projects under
active development. If your project
depends on a software component that
is under active development, you can
depend on a SNAPSHOT release, and
Maven will periodically attempt to
download the latest snapshot from a
repository when you run a build.
Similarly, if the next release of your
system is going to have a version
"1.4", your project would have a
version "1.4-SNAPSHOT" until it was
formally released.
As a default setting, Maven will not
check for SNAPSHOT releases on remote
repositories. To depend on SNAPSHOT
releases, users must explicitly enable
the ability to download snapshots
using a repository or pluginRepository
element in the POM.
When releasing a project, you should
resolve all dependencies on SNAPSHOT
versions to dependencies on released
versions. If a project depends on a
SNAPSHOT, it is not stable as the
dependencies may change over time.
Artifacts published to non-snapshot
Maven repositories such as
http://repo1.maven.org/maven2 cannot
depend on SNAPSHOT versions, as
Maven's Super POM has snapshot's
disabled from the Central repository.
SNAPSHOT versions are for development
only.
If you really want to change this behavior, you can change the updatePolicy of your snapshot enabled repository:
<repositories>
<repository>
<id>my-repo</id>
<name>My Corporate Repository</name>
<url>http://repo.mycompany.com/maven2</url>
<layout>default</layout>
...
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
Switching to never will force you to use a manual update (using mvn -U). But beware, this is usually not what people want and expect with SNAPSHOTs.
For the record, Maven 3 has a -nsu, --no-snapshot-updates command line option allowing to Suppress SNAPSHOT updates.
See also
3.2. The POM
Repositories in the POM reference
You could generate a pom in your local repository by installing the file manually:
mvn install:install-file
-Dfile=[FILE]
-DgroupId=[GROUP]
-DartifactId=[ARTIFACT]
-Dversion=[VERSION]
-Dpackaging=jar
-DgeneratePom=true
-DcreateChecksum=true
EDIT: You wouldn't want to do this for snapshots.
Related
when I am doing development I often need to change a dependency, but I'm not ready to deploy my changes. For example, I'm working on project Foo and I realize I need to add a method to the common library. Before deploying this change to our internal repository, I would like to install the changes to common library (mvn install) and recompile Foo to use the common library in the local repository (note that I'm using all SNAPSHOT versions).
However, after I mvn install my common library, when I recompile Foo it doesn't use the new common library--it keeps using the latest SNAPSHOT of common library in the internal repository. If I deploy the changed common library, Foo picks it up immediately.
How can I get maven to look first in the local repository?
UPDATE: when the file is installed into the local repository, it gets a name like foo-1.0.0-SNAPSHOT.jar, but when I deploy it, it gets a timestamp foo-1.0.0-20111104.191316-23.jar. I think this is why the remote artifact gets pulled each time. Any idea why mvn install is not working like mvn deploy? Does it have to do with the fact that I have a snapshot repository set up for deploy?
By default, Maven checks for new versions of SNAPSHOT artifacts once per day. When it does this check, it will download SNAPSHOTS from remote repos that are newer than what you have locally. Either your artifact timestamps are out of sync and you're doing something to override Maven's update policy (like calling it with -U or setting the udpatePolicy to "always"), or else the local repository you're installing the artifact to isn't the same one you're subsequently running Maven against. What you're describing isn't typical Maven behavior. For a better answer, give more details in your question.
One indicator you can look for: after you install your common artifact, when you next compile Foo, does Maven download the common artifact again? If so, then it really is getting it from the remote, and you need to check your update settings. If not, then you have something strange going on locally.
You can try this option. This worked for me.
In your project's main pom.xml change 'snapshots' enabled setting to 'false'.
<repository>
<id>yourRepo</id>
<name>Repository</name>
<url>http://your.repo.com/repo</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
So I have got my Maven build deploying both Java5 and Java6 versions to my snapshot repo (Nexus). I do this with build profiles and classifiers. All is good in the Maven side of things.
However, if I try to resolve the Java5 dependency from my IVY based project it will not work if the most recent Maven deploy was for the Java6 profile/classifier. I guess this is because the timestamp in maven-metadata.xml picks out the Java6 version. It does work if the most recent deploy was for Java5.
This is the resolver:
<ibiblio name="snapshot-repo-name"
m2compatible="true"
root="snapshot-repo-root"
pattern="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
usepoms="true"
checkmodified="true"
changingPattern=".*SNAPSHOT"/>
Deploying Java6 of the dependency therefore breaks the build of IVY-built application.
The work-around is to mark the Maven snapshot as non-unique versions in the <distributionManagement/> element. That is, there are no longer timestamped versions in the Maven snapshot repository.
<distributionManagement>
<repository>
<id>PROJECT-RELEASE</id>
<name>PROJECT-RELEASE</name>
<url>http://foo.bar:8081/nexus/content/repositories/PROJECT-RELEASE</url>
</repository>
<snapshotRepository>
<id>PROJECT-SNAPSHOT</id>
<name>PROJECT-SNAPSHOT</name>
<uniqueVersion>false</uniqueVersion>
<url>http://foo.bar:8081/nexus/content/repositories/PROJECT-SNAPSHOT</url>
</snapshotRepository>
</distributionManagement>
Is it the resolution that is failing or the retrieve? (Retrieve does an implicit resolve).
My build once failed because the following pattern wasn't unique (Needed a classifier in the name pattern to cater for source and javadoc artifacts):
<ivy:retrieve pattern="lib/[artifact].[ext]"/>
Let's say I have one project with the following POM:
<groupId>com.mine</groupId>
<artifactId>coreJar</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
And then in another project I always want to reference the latest SNAPSHOT:
<dependencies>
<dependency>
<groupId>com.mine</groupId>
<artifactId>coreJar</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
...
<dependencies>
But instead of 0.0.1-SNAPSHOT, I want it to always grab the latest SNAPSHOT version. In the past you could use LATEST, but this has since been deprecated (for reasonable reasons).
I do understand you can specify versions, such as:
[1.5,)
But I could never get it to work with a "-SNAPSHOT":
[0.0.1,)-SNAPSHOT // Doesn't work!
The question then is how do I get maven to grab the latest SNAPSHOT in my other project?
Another option (which I use) is to include the following in your pom.xml. updatePolicy tag will force maven to always use latest snapshot from this repo.
<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>
p.s. I always configure all repos in pom.xml because we use several CI servers and it will be quite hard to configure all of them (I am lazy...)
Doc on settings.xml updatePolicy for reference.
The frequency for downloading updates - can be "always", "daily" (default), "interval:XXX" (in minutes) or "never" (only if it doesn't exist locally).
Use
mvn -U, --update-snapshots
Forces a check for updated releases and snapshots on remote repository
A few words about dependency ranges and SNAPSHOT dependencies (quoting the Dependency Mediation and Conflict Resolution design document):
Incorporating SNAPSHOT versions into the specification
Resolution of dependency ranges should not resolve to a snapshot (development version) unless it is included as an explicit boundary. There is no need to compile against development code unless you are explicitly using a new feature, under which the snapshot will become the lower bound of your version specification. As releases are considered newer than the snapshot they belong to, they will be chosen over an old snapshot if found.
So, to answer your question, the only way to use a SNAPSHOT with dependency ranges is as boundary and you won't get higher SNAPSHOT versions automatically by design (which really makes sense).
Personally, I don't like to use dependency ranges because I find that it can lead to build reproducibility issues and makes the build more fragile. I do not recommend them.
Just in case, upgrading the SNAPSHOT version typically means that you are releasing some code and the maven release plugin provides support for that (see the Updating POM Versions).
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.
use mvn install -U
u must use this to force maven to get the latest snapshots
It's
<version>[0.0-SNAPSHOT,)</version>
In case you want to update your SNAPSHOT releases inside Eclipse (when using m2e / m2eclipse), right click the affected project, then select "Maven" -> "Update Project..." -> "OK" (with selected project causing problems).
I'm hosting a small open source project on Google Code, and I have been asked to submit the jar to a publicly accessible Maven repository. I have almost no practical knowledge of Maven. What would be the best way to do this?
Is there some central repository that I can submit to, or can I host my own? What would I need to do when I want to release a new version of the jar?
I've been Googling and found this, which looks nice and simple, but it seems a bit ... contrary to the spirit of Maven, to commit jar files to SVN :).
Also, would there be a way to still keep track of the download count, as Google Code does?
EDIT
I've been getting some answers, some of which containing hints on what to add to my pom.xml. Thanks guys! But obviously I forgot to mention one important thing: my build script is in ANT, and to put it bluntly, I intend to keep it that way :). I just want to make it easier for Maven users to include my jar in their projects.
The solution I went with in the end
In the end, I did use the solution I referenced before, where I simply commit a Maven repo to SVN. I have the ANT script call Maven to set up the local repo, and then call SVN to commit it to Google Code. For those interested: look at my build script here, in the publish-maven target.
There is a guide to the central repository that has a section on uploading projects that may help. If nothing else you can check the naming conventions and minimal information requirements against your project.
Sonatype also do OSS Repository hosting, see their guide for details.
Update: I'm not saying you should change your build process - if Ant works for you stick with it. It's worth following the Maven conventions in your POM regardless of your build method. As the point of putting your jar in a Maven repository is to make it accessible to Maven users, you will therefore need to define a POM for your published artifact. Following the naming conventions will help your users so you might as well do it. For example adding the SCM details to the pom will (amongst other things) allow your users to import the project into their workspace using the IDE integrations for Maven.
Basically, you have 4 options:
Perform a standard Maven build against a Maven repository (already ruled out)
Set up a Maven repository, do your builds with Ant, and use Maven to deploy the jar and POM.
Set up a Maven repository, ad use an Ant HTTP task to publish the artifacts
Use a Subversion "repository", and use the SvnAnt task to publish the artifacts
Option 1
Use Maven to build and deploy the artifacts (see the Maven book and the above links for details).
Option 2
Assuming you have a build process that creates your jar, and you've defined the POM, your best bet is to publish it to the Sonatype OSS repository as above.
Deploying an existing jar to a standard Maven repository is simple with the Maven deploy plugin's deploy-file goal:
Set up your repository (e.g on the Sonatype servers by raising a Jira request)
Build your jar with Ant.
If you have defined a POM, put it in the same directory as the jar.
Run the deploy-file goal:
mvn deploy:deploy-file -Durl=http://path/to/your/repository\
-DrepositoryId=some.id \
-Dfile=path-to-your-artifact-jar \
-DpomFile=path-to-your-pom.xml
Note that the Maven deploy goal will automatically translate the pom.xml to [project-name]-[version].pom. If you are doing either of the other two alternatives, you will need to ensure you commit the POM with the final name, i.e. [project-name]-[version].pom. You'll also need to ensure you compose the relative paths for the artifacts following the Maven conventions.
E.g. for groupId=com.foo.bar, artifactId=my-project version=1.0.0, the path to the files will be:
/com/foo/bar/my-project/my-project-1.0.0.jar
/com/foo/bar/my-project/my-project-1.0.0.pom
Option 3
If you want to use Ant to deploy to a Maven repository, you can use an Ant HTTP library (Note I've not tried this myself) . You would compose two HTTP put tasks, one for the jar and one for the POM.
<httpput url="http://path/to/your/repository" putFile="/path/to/yourproject.pom">
<userCredentials username="user" password="password"/>
</httpput>
<httpput url="http://path/to/your/repository" putFile="/path/to/yourproject.jar">
<userCredentials username="user" password="password"/>
</httpput>
Option 4
If you want to avoid Maven completely and use Ant to deploy to an SVN-backed repository, you can use the SvnAnt Subversion library. you would simply need to do configure the Svn import task to add your artifacts to the Remote Subversion repository.
<import path ="/dir/containing/the/jar/and/pom"
url="svn://your/svn/repository"
message="release"/>
Check wagon-svn. It will allow you to 'deploy' to a Subversion repository. It's a little convoluted, but it's better than nothing. I know of a few projects that use it at java.net, and I also came across some projects using it at code.google.com.
If you want to use it, then you first need to load wagon-svn as an extension:
<build>
...
<extensions>
<extension>
<groupId>org.jvnet.wagon-svn</groupId>
<artifactId>wagon-svn</artifactId>
<version>...</version>
</extension>
</extensions>
Next, you need to set your deployment targets using the svn: protocol identifier. Here's an example I copied from the Internet.
<distributionManagement>
<repository>
<id>maven-config-processor-plugin-repo-releases</id>
<name>Maven Repository for Config Processor Plugin (releases)</name>
<url>svn:https://maven-config-processor-plugin.googlecode.com/svn/maven-repo/releases</url>
<uniqueVersion>false</uniqueVersion>
</repository>
<snapshotRepository>
<id>maven-config-processor-plugin-repo-releases</id>
<name>Maven Repository for Config Processor Plugin (snapshots)</name>
<url>svn:https://maven-config-processor-plugin.googlecode.com/svn/maven-repo/snapshots</url>
<uniqueVersion>false</uniqueVersion>
</snapshotRepository>
</distributionManagement>
Check if the Maven repository support maven deploy plugin. This would be the easiest approach.
Most repositories uses ssh as the transport. See this for details.
Once it's setup, all you have to do is:
mvn deploy:deploy
You can submit your jar to https://clojars.org/
In your pom.xml:
<repositories>
<repository>
<id>clojars.org</id>
<url>http://clojars.org/repo</url>
</repository>
</repositories>
my problem with maven is that if the maven repository is not responding, one cannot build. It seems to fetch every "mvn package" time some poms, which won't change, because they are of the same version.
How can I say to maven that please don't look them up from server, and instead download them permanetly to offline repository?
Thanks!
You can run maven with the -o flag:
-o,--offline Work offline
This will cause Maven to never look for dependencies in remote repositories. On the other hand, your build will fail if the dependencies are not found in the local repository.
You can configure the repository to only check for updates occasionally, or never by setting the updatePolicy element on the repository declaration. From the settings documentation:
The frequency for downloading updates - can be "always", "daily" (default), "interval:XXX" (in minutes) or "never" (only if it doesn't exist locally).
Adding the following to your POM or the settings will configure the central repository to only download if the artifact doesn't exist locally:
<repositories>
<repository>
<id>central</id>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</repository>
</repositories>
If the repository in question is an internal remote repository, you need to ensure the maven-metadata.xml is configured correctly in the remote repository or Maven will attempt to download it each time. The simplest way to do this is to use a repository manager that will manage the metadata automatically