Custom maven assembly

前端 未结 1 673
北恋
北恋 2020-12-29 14:28

I\'m starting to work with Maven but am not yet successfully thinking in Maven\'s terms. I have a specific requirement and the docs aren\'t giving me enough clues, so I coul

相关标签:
1条回答
  • 2020-12-29 15:01

    I'm starting to work with Maven but am not yet successfully thinking in Maven's terms.

    Welcome on board, Carl! :D

    I want to fire this assembly up from the command line (only), hence no need to tie to a phase (or goal? mojo?). Preferrably using either assembly:assembly or assembly:single.

    Just to clarify: the build lifecycle itself is made of phases (compile, test, package, etc) and plugin goals (technically Mojos) are bound on phases. You then either invoke a phase... or just a specific plugin goal.

    Do I need a custom assembly descriptor for this?

    Well, since you want behavior that the pre-defined descriptors don't cover, yes. You'll even need two of them (of for the uberjar, one for the zip).

    And is it true I can't nest it in the pom.xml? So it goes in src/assembly/something.xml and gets referenced with a descriptorRef?

    Yes, that's true (descriptors use a custom format) and they usually go into src/main/assembly. And no, descriptorRef is for the built-in descriptors, you'll have to use descriptor here.

    Can I code this as two relatively simple assemblies, of which one builds on the other (i.e. the .Zip assembly uses the .Jar assembly) or do I have to do everything in one assembly?

    As hinted, you'll need two assembly descriptors. Let me help a bit...

    Let's assume you have the following project structure:

    $ tree .
    .
    ├── pom.xml
    └── src
        ├── main
        │   ├── assembly
        │   │   ├── jar.xml
        │   │   └── zip.xml
        │   ├── java
        │   │   └── com
        │   │       └── stackoverflow
        │   │           └── App.java
        │   └── resources
        │       └── log4j.properties
        └── test
            └── java
                └── com
                    └── stackoverflow
                        └── AppTest.java
    

    Where the pom.xml contains the following configuration for the assembly plugin:

    <project>
      ...
      <dependencies>
        ...
      </dependencies>
      ...
      <build>
        <plugins>
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2-beta-5</version>
            <configuration>
              <descriptors>
                <descriptor>src/main/assembly/jar.xml</descriptor>
                <descriptor>src/main/assembly/zip.xml</descriptor>
              </descriptors>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    

    The descriptor for the "filtered" uberjar (jar.xml) looks like this:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
      <id>uberjar</id>
      <formats>
        <format>jar</format>
      </formats>
      <includeBaseDirectory>false</includeBaseDirectory>
      <dependencySets>
        <dependencySet>
          <unpack>true</unpack>
          <scope>runtime</scope>
          <useProjectArtifact>false</useProjectArtifact>
        </dependencySet>
      </dependencySets>
      <fileSets>
        <fileSet>
          <directory>${project.build.outputDirectory}</directory>
          <outputDirectory>/</outputDirectory>
          <excludes>
            <exclude>log4j.properties</exclude>
          </excludes>
        </fileSet>
      </fileSets>
    </assembly>
    

    What this descriptor does is (in short):

    • include the dependencies, unpack them, but exclude the project itself (yes, this is counter intuitive but this weird default behavior has been kept for backward compatibility)
    • include the project files but exclude some of them.

    And the descriptor for the zip (zip.xml) looks like this:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
      <id>bin</id>
      <formats>
        <format>zip</format>
      </formats>
      <includeBaseDirectory>false</includeBaseDirectory>
      <fileSets>
        <fileSet>
          <directory>${project.basedir}/src/main/resources</directory>
          <outputDirectory/>
          <includes>
            <include>log4j.properties</include>
          </includes>
        </fileSet>
        <fileSet>
          <directory>${project.build.directory}</directory>
          <outputDirectory/>
          <includes>
            <include>*-uberjar.jar</include>
          </includes>
        </fileSet>
      </fileSets>
    </assembly>
    

    Which is (somehow) self explaining :)

    • it includes the configuration files (relatively to <directory>) at the root of the assembly
    • it includes the uberjar (relatively to <directory>) at the root of the assembly

    Finally, just run mvn assembly:assembly (that's the goal intended to be used on the CLI).


    I didn't (knowingly) include META-INF/maven/** in the assembly for the uberjar. Is there a simple way to prevent inclusion of these?

    These are coming from the libraries that are unpacked. You can exclude them using unpackOptions. Here is a modified version of the jar.xml:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
      <id>uberjar</id>
      <formats>
        <format>jar</format>
      </formats>
      <includeBaseDirectory>false</includeBaseDirectory>
      <dependencySets>
        <dependencySet>
          <unpack>true</unpack>
          <scope>runtime</scope>
          <unpackOptions>
            <excludes>
              <exclude>META-INF/maven/**</exclude>
            </excludes>
          </unpackOptions>
          <useProjectArtifact>false</useProjectArtifact>
        </dependencySet>
      </dependencySets>
      <fileSets>
        <fileSet>
          <directory>${project.build.outputDirectory}</directory>
          <outputDirectory>/</outputDirectory>
          <excludes>
            <exclude>log4j.properties</exclude>
          </excludes>
        </fileSet>
      </fileSets>
    </assembly>
    
    0 讨论(0)
提交回复
热议问题