sodik
sodik

Reputation: 4683

Maven 3 does not update snapshot dependency from local repository

I am trying to use external library inside my maven project. Since I want the project to build out of the box on any machine, I don't want to use mvn install solution. I have therefore defined local repository in my pom.xml:

    <dependency>
        <groupId>com.test</groupId>
        <artifactId>fooLib</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    ....
    <repository>
        <id>in-project</id>
        <snapshots>
            <updatePolicy>always</updatePolicy>
            <enabled>true</enabled>
        </snapshots>
        <name>In Project Repo</name>
        <url>file://${project.basedir}/libRepo</url>
    </repository>

The problem is when I replace the jar in libRepo (without updating version number since it is just another snapshot) that this updated jar is not used (old version from .m2 directory is used instead) even for mvn -U clean install How to make maven to update this jar?

EDIT: According to What exactly is a Maven Snapshot and why do we need it? maven shall try to find newer version of SNAPSHOT dependency, "even if a version of this library is found on the local repository". What is wrong with my setting?

DIRTY SOLUTION: Based on answer from Maven 2 assembly with dependencies: jar under scope "system" not included following extension of my original solution seems to work:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <executions>
                <execution>
                    <id>hack-binary</id>
                    <phase>validate</phase>
                    <configuration>
                        <file>${repo.path.to.jar}</file>
                        <repositoryLayout>default</repositoryLayout>
                        <groupId>com.test</groupId>
                        <artifactId>fooLib</artifactId>
                        <version>1.0-SNAPSHOT</version>
                        <packaging>jar</packaging>
                        <generatePom>true</generatePom>
                    </configuration>
                    <goals>
                        <goal>install-file</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

As mentioned in comment to that solution, it does not work alone, thus it works in combination with in-project repository (which works when the dependency is not available in local .m2 repository) and this second parts refreshes .m2 during every build.

However it is still not clear to me why ordinary "SNAPSHOT" mechanism does not work (i.e. current dirty solution would work also without SNAPSHOTs as local .m2 repo is explicitly updated every time). Is there any cleaner way?

SOLUTION (based on Aaron's answer & discussion): The problem was that I tried to install file into libRepo using install-file. The actual solution is that if library updates, use

mvn deploy:deploy-file -Dfile=fooLib.jar  -DgroupId=com.test \
    -DartifactId=fooLib -Dversion=1.0-SNAPSHOT -Dpackaging=jar \
    -Durl=file://..\libRepo -DrepositoryId=in-project

to deployed it to repo. After proper deploy, maven correctly handles SNAPSHOTs.

Upvotes: 9

Views: 33558

Answers (3)

BoomZilla
BoomZilla

Reputation: 746

The previous answerer (and one commenter) pointed out, that maven looks within the local project-repository only once, and on subsequent builds it gets the cached jar from the .m2-repository.

I just found a workaround for the need to increment the version number (e.g. on small changes of a dev-library):

First reinstall the jar into your local project-repository:

mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -DgroupId=com.johndoe.dev -DartifactId=Helpers -Dversion=0.1 -Dfile=C:/path/to/helpers.jar

(Where -Dfile could point to an external Project which produces the helpers.jar)

Then purge just this specific artifact in the .m2-repository:

mvn dependency:purge-local-repository -DmanualInclude=com.johndoe.dev:Helpers:0.1

(With com.johndoe.dev as the GroupId, Helpers as the ArtifactId and the same version installed in the previous step)

Executing the latter step, maven rebuilds the artifact inside .m2 using your local project-repository jar-file.

Alternative and maybe dirty variant: Just copy helpers.jar to C:\Users\johndoe\.m2\repository\com\johndoe\dev\Helpers\0.1\Helpers-0.1.jar (don't know about linux as I haven't used mave there).

Upvotes: 1

Aaron Digulla
Aaron Digulla

Reputation: 328820

If you use a repository for this, then Maven will copy the JAR once into it's local repository (usually in $HOME/.m2/repository/). Unless the version number changes, Maven won't consider this file to have changed and it won't copy it. Note that the version number is the only thing that Maven looks at; it doesn't care about checksums or file sizes or dates.

Incidentally, snapshots are assigned a version number internally for just this purpose: So that Maven can internally notice that a snapshot has been updated.

I suggest to use a system dependency instead. That way, the actual JAR is going to be added to the classpath (without any copying or stuff). You also don't need to replicate a repo structure for this approach and it will clearly communicate your intent.

[EDIT] I understand that Maven handles dependencies with scope system differently. I'm not sure whether this makes sense or not (if it uses the dependency to compile, it surely can use it to run?)

As I see it, you have these options:

  1. Install the dependency into your libRepo using deploy:deploy-file instead of copying it yourself. That should update the meta data in such a way that Maven will copy it again when you run mvn install again on the real project.

    Note that file:install doesn't work. The file plugin is used to access the local repository but you need to use the deploy plugin which knows how to update a shared / server repository.

  2. Install the dependency into your local repo; I suggest to use a script for this that you can include in your project. That way, you avoid all the problems and it will be easy to set this up on a new machine.

  3. Change the version number of the dependency but that's tedious and you might get into trouble when the real version number of the dependency changes.

  4. Set up a local repo server for your company and deploy the dependency to it. That will take a few hours but a) you will get a local cache of all your dependencies, making your initial builds faster and b) it will make setup for additional developers much faster.

Upvotes: 6

ItachiUchiha
ItachiUchiha

Reputation: 36792

Maven will never read the jar present inside any library folder. You must first understand how maven works. The only place where maven looks for jar is the localRepository (.m2), if absent it searches the other repository, mentioned in your POM.xml

Upvotes: 1

Related Questions