19

I create my application archive with the maven assembly plugin. All the dependency present in my pom are included without any problem.

Now I need to include two or more version of the same artifact.

If in my pom I put

<dependencies>
        [...]
        <dependency>
            <groupId>db.test</groupId>
            <artifactId>my-model</artifactId>
            <version>1.0.3</version>
        </dependency>
        <dependency>
            <groupId>db.test</groupId>
            <artifactId>my-model</artifactId>
            <version>1.1.0</version>
        </dependency>
</dependencies>

Of source the dependenvcy resolver remove the old version and only the 1.1.0 is packaged in the archive

I try to include the jar by using assembly xml descriptor file. And I didn't find any solution.

A possible solution will be to manually put all the needed model.jar inside a folder and tell the assembly to copy it in the archive. But I'm looking for a more configurable solution.

Any idea ?

Vlagorce
  • 866
  • 2
  • 6
  • 17

4 Answers4

13

I found a solution by using maven-dependency-plugin to copy resolved pom dependencies and additional jar.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
    <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
            <goal>copy-dependencies</goal>
        </goals>
        <configuration>
            <outputDirectory>${project.build.directory}/lib</outputDirectory>
            <overWriteReleases>false</overWriteReleases>
            <overWriteSnapshots>false</overWriteSnapshots>
            <overWriteIfNewer>true</overWriteIfNewer>
            <includeScope>runtime</includeScope>
        </configuration>
    </execution>
    <execution>
        <id>copy-model</id>
        <phase>package</phase>
        <goals>
            <goal>copy</goal>
        </goals>
        <configuration>
            <artifactItems>
                <artifactItem>
                    <groupId>my.test.pkg</groupId>
                    <artifactId>my-model</artifactId>
                    <classifier>server</classifier>
                    <version>1.0.3</version>
                    <type>jar</type>
                </artifactItem>
                <artifactItem>
                    <groupId>my.test.pkg</groupId>
                    <artifactId>my-model</artifactId>
                    <classifier>server</classifier>
                    <version>1.1.0</version>
                    <type>jar</type>
                </artifactItem>
            </artifactItems>
            <outputDirectory>${project.build.directory}/lib</outputDirectory>
        </configuration>
    </execution>
</executions>

Now I just have to add the following lines in my assembly xml

    <fileSet>
        <directory>${project.build.directory}/lib</directory>
        <outputDirectory>/lib</outputDirectory>
        <filtered>false</filtered>
        <includes>
            <include>*.jar</include>
        </includes>
        <fileMode>0600</fileMode>
    </fileSet>
Vlagorce
  • 866
  • 2
  • 6
  • 17
  • 1
    may ask if you do this, when both versions are loaded to jvm, shouldn't there be a conflict? – lucky_start_izumi Oct 20 '16 at 17:18
  • I had exact same requirement and your solution saved time. @lucky_start_izumi - it does in most cases, but in my case it is for an application which uses YAJSW which needed an older library and my application needed a newer one. In my scenario, they run on different classpaths. – Pavan Kumar Feb 16 '18 at 04:57
12

Maven assumes it doesn't make any sense to have more than one version of a module at once. It assumes that a newer version replaces the older version. If it doesn't it is not the same module. I suggest you give the newer module a different name and make sure it has different packages to avoid choising a random module.

In general Maven tried to encourage good application design and deliberately makes it difficult to do things it has determined to be a bad idea.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • This jar have different classes with different package name. They will be loaded by using ServiceLoader to build different xml model to keep back compatibility. I think in my case it's not a bad practice. I will try to see if it's possible and not boring to change name on every release. – Vlagorce Nov 30 '10 at 10:31
  • 2
    I would vouch for the name change two, if you're going to use both. – Valentin Rocher Nov 30 '10 at 10:36
  • Of course yes ! Everything is different only the groupeid and the artifactid are the same. – Vlagorce Nov 30 '10 at 10:45
  • 3
    We need to ship multiple different versions of a database driver in our distribution, so that the our application can support different legacy and current versions of the database. They are all the same groupId:artifactId but different versions. We will of course package them in separate subdirs in our .zip. But maven should not assume so much, without thinking through every use-case. – Ed Randall Feb 24 '15 at 14:51
  • 1
    The reason maven was created was that there are so many details which you need to specify for a Java build that it's not manageable to do everything by hand - which is what ant was asking of you. Hence, maven _always_ assumes, by design. Only, it also (almost) always has a way to change every possible default it assumes. – user625488 Jun 30 '16 at 16:23
1

I agree, different versions means replacing the older one. If we have to consume two different versions of a webservice for some business requirement. It is a good idea to generate the stubs in different packages and while adding to maven you can specify different them in groupid. This should work.

MWiesner
  • 8,868
  • 11
  • 36
  • 70
Purushothaman
  • 417
  • 4
  • 6
1

Another ugly solution might be to use WAR file overlays, exploiting the fact that this mechanism pays no attention to the versions of component JAR files when applying the overlays.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216