views:

219

answers:

1

Context

We have this application, using about 60 coding projects.

We have several products that are realized using this same code base, so we follow the maven best-practices : we assemble each product using an assembly project, using the assembly plugin.

We have an historical assembly using Ant, that need many improvements. In a first phase, I am trying to obtain the same result using a clean Maven assembly. Later on, I will improve that one.

Question

In my assembly, I want to have the same jar artifact in several versions. I want:

    commons-beanutils-1.7.0.jar
    commons-beanutils-1.8.0.jar

I list both in my assembly project dependencies in my pom, but only one shows (the 1.8.0). How could I do it?

This is my pom.xml for the assembly project. Everything works if I specify only one or the other, except I don't get the other one obviously.

pom.xml:

      <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.7.0</version>
      </dependency>
      <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.8.0</version>
      </dependency>
+4  A: 

Maven doesn't want you to do this because the behaviour at runtime is indeterminate. If you define multiple dependencies with the same groupId and artifactId, and different versions, Maven will resolve the conflict and give you one of them. You should really look at resolving the conflict so that only one version is required.

If you do have a good reason to do this, to avoid the problem you need to specify the dependencies as artifactItems in the dependency plugin. The following config will copy both versions of the jar to target/output, if the dependency plugin is executed before the assembly plugin, you will be able to include the downloaded jars in your assembly by specifying a fileSet pointing to the target/output directory:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>copy</id>
        <phase>package</phase>
        <goals>
          <goal>copy</goal>
        </goals>
        <configuration>
          <artifactItems>
            <artifactItem>
              <groupId>commons-beanutils</groupId>
              <artifactId>commons-beanutils</artifactId>
              <version>1.7.0</version>
              <type>jar</type>
              <overWrite>false</overWrite>
            </artifactItem>
            <artifactItem>
              <groupId>commons-beanutils</groupId>
              <artifactId>commons-beanutils</artifactId>
              <version>1.8.0</version>
              <type>jar</type>
              <overWrite>false</overWrite>
            </artifactItem>
          </artifactItems>
          <outputDirectory>${project.build.directory}/output</outputDirectory>
          <overWriteReleases>false</overWriteReleases>
          <overWriteSnapshots>true</overWriteSnapshots>
        </configuration>
      </execution>
    </executions>
  </plugin>
Rich Seller
@Rich Hi Rich. I knew you would answer. Yes, I have a good reason, I gave it in the context part. I need to obtain the same packaging as a previous clunky assembly, not made in Maven. Only later will I use the correct one...
KLE
It was a general warning that this is not a good idea. You have your reasons so I'm not going to argue. Hopefully this workaround will help. Note you could specify only the omitted version as an artifactItem, and have another configuration using dependencies to resolve the one that Maven selects
Rich Seller
@Rich I understand your warning, and I take it seriously. Following your answer, we have been evaluating the risk of deleting the extra library.
KLE
Something is great about this answer: now we know that the *assembly* plugin is not guilty, it is the *dependency* plugin that is against us. So we can stop fighting against the wrong one ;-)
KLE
@Rich I like your third edit, that explains how the result of the copying could be taken into account by the assembly plugin. I was worried about this, and at first I thought of rejecting your solution. Now, I know I can make it work if I want to.
KLE
This solution is not perfect for our need, as it is not straightforward (as configuring the assembly descriptor would have). But it has the merits to work.
KLE
I don't think there is a perfect solution to the problem. The assembly plugin won't handle specific artifacts unless they're modules of the build. The dependency plugin will help get both versions of the jar into the local system so they can be assembled. But you will still have potential issues at runtime as only one version of the beanutils code will be loaded by the classloader even if you have both on the classpath
Rich Seller