Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven Assembly: include a dependency with a different classifier

I would like to build two different versions of a WAR in Maven (I know that's a no-no, that's just the way it is given the current situation). In the version of a WAR depicted by an assembly, I want to replace a dependency by the same dependency with a different classifier. For example, I was expecting this assembly to work:

<assembly>
  <id>end-user</id>
  <formats>
    <format>war</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <excludes>
        <exclude>group:artifact:jar:${project.version}</exclude>
      </excludes>
      <includes>
        <include>group:artifact:jar:${project.version}:end-user</include>
      </includes>
    </dependencySet>
  </dependencySets>
</assembly>

This doesn't work, but am I heading in the right direction? I've already read all the pages on the Maven assembly page and the section on the Maven Definitive Guide that seems relevant. Any pointers would be helpful.

like image 886
James Kingsbery Avatar asked Apr 22 '10 22:04

James Kingsbery


People also ask

What is classifier in Maven dependency?

classifier: The classifier distinguishes artifacts that were built from the same POM but differ in content. It is some optional and arbitrary string that - if present - is appended to the artifact name just after the version number.

What is assembly descriptor in Maven?

So in order for you to customize the way the Assembly Plugin creates your assemblies, you need to know how to use the Assembly Descriptor. This descriptor specifies the type of assembly archive to create, the contents of the assembly, and the ways in which dependencies or its modules are bundled with an assembly.

Which of the following is a type of Maven Assembly plugin's built in descriptors?

A list of references to assembly descriptors available on the plugin's classpath. The default classpath includes these built-in descriptors: bin , jar-with-dependencies , src , and project .

How does Maven Assembly plugin work?

The Assembly Plugin for Maven enables developers to combine project output into a single distributable archive that also contains dependencies, modules, site documentation, and other files. Your project can easily build distribution "assemblies" using one of the prefabricated assembly descriptors.


2 Answers

Personally, I think that the cleanest solution would be to use two profiles (one of them depending on the artifact with the classifier, the other on the "regular" artifact). But you can indeed achieve what you want with a custom assembly. I just don't think you're heading in the right direction. Here is how I would do it...

First, create a specific project for the assembly and declare both the webapp and the artifact with the classifier as dependencies. Something like this:

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>artifact</artifactId>
      <version>${project.version}</version>
      <classifier>end-user<classifier>
    </dependency>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>zewebapp</artifactId>
      <version>${project.version}</version>
      <type>war</type>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2-beta-5</version>
        <configuration>
          <descriptors>
            <descriptor>src/main/assembly/end-user.xml</descriptor>
          </descriptors>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <!-- this is used for inheritance merges -->
            <phase>package</phase>
            <!-- append to the packaging phase. -->
            <goals>
              <goal>single</goal>
              <!-- goals == mojos -->
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Then, in your assembly descriptor:

<assembly>
  <id>end-user</id>
  <formats>
    <format>war</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <unpack>true</unpack>
      <unpackOptions>
        <excludes>
          <exclude>**/artifact-*.jar</exclude>
        </excludes>
      </unpackOptions>
      <includes>
        <include>*:war</include>
      </includes>
    </dependencySet>
    <dependencySet>
      <unpack>false</unpack>
      <outputDirectory>WEB-INF/lib</outputDirectory>
      <includes>
        <include>group:artifact:jar:*:end-user</include>
      </includes>
    </dependencySet>    
  </dependencySets>
</assembly>

Basically, this tells the assembly plugin to get the war for zewebapp and to unpack it but to exclude the unwanted artifact while unpacking. Then, the assembly plugin get the artifact with the classifier and place it in WEB-INF/lib (so we substitute it to the original). Finally, the whole thing is packaged as a war.

I tested this on a simplified example, it should work.

like image 91
Pascal Thivent Avatar answered Sep 17 '22 16:09

Pascal Thivent


The "version" information is not required when specifying artifact coordinates for includes/include*.

This should work:

<assembly>
  <id>end-user</id>
  <formats>
    <format>war</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <includes>
        <include>group:artifact:jar:end-user</include>
      </includes>
    </dependencySet>
  </dependencySets>
</assembly>

I think the maven assembly documentation for the includes/include* section is incorrect. It says "Artifact coordinatess may be given in simple groupId:artifactId form, or they may be fully qualified in the form groupId:artifactId:type:version[:classifier]." However, from my testing, the "version" is not required. I got the hint from here.

Took me while to find out, thought might be useful to others in the future.

like image 23
kctang Avatar answered Sep 19 '22 16:09

kctang