Search code examples
mavenmaven-assembly-plugin

Maven Create Jar and exclude Files


I am trying to create a runnable Jar file. I have to create a Jar of only one single java class (MyClass which is under the folder structure src/main/java/org/miso/mcs/util/MyClass) and exclude others. I am able to create to JAR but it has everything.

I am using mvn clean package assembly:single command to create Jar.

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
    <archive>
      <manifest>
        <mainClass>org.miso.mcs.util.MyClass</mainClass>
      </manifest>
    </archive>  
    <resources>
      <resource>
        <classesDirectory>src/main/java/org/miso/mcs/util</classesDirectory>
        <includes>
          <include>/*MyClass*</include>
        </includes>
        <excludes>
          <exclude>/*</exclude>
        </excludes>
      </resource>
    </resources>               
  </configuration>
</plugin>

Solution

  • You won't be able to do that by using the predefined jar-with-dependencies descriptor. However, we can make our own assembly descriptor for that:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
      <id>jar-with-dependencies</id>
      <formats>
        <format>jar</format>
      </formats>
      <includeBaseDirectory>false</includeBaseDirectory>
      <dependencySets>
        <dependencySet>
          <outputDirectory>/</outputDirectory>
          <useProjectArtifact>false</useProjectArtifact>
          <unpack>true</unpack>
        </dependencySet>
        <dependencySet>
          <outputDirectory>/</outputDirectory>
          <useProjectArtifact>false</useProjectArtifact>
          <useProjectAttachments>true</useProjectAttachments>
          <includes>
            <include>${project.groupId}:${project.artifactId}:jar:classes:${project.version}</include>
          </includes>
          <unpack>true</unpack>
          <unpackOptions>
            <excludes>
              <exclude>%regex[org\/miso\/(?!mcs\/util\/MyClass).*]</exclude>
            </excludes>
          </unpackOptions>
        </dependencySet>
      </dependencySets>
    </assembly>
    

    unpackOptions allows to control the content the unpacked dependencies in the JAR. In this case, we are excluding everything under the org.miso package (which I assume are the classes of your project) and we're only including the class you're interested in (org.miso.mcs.util.MyClass). This will result in a runnable JAR with only the specified class of your project.

    Since your project is a WAR, it is a little more complicated. The first dependency set declares all the dependencies of the project and unpacks them. The second only uses the projects attachments and includes only the classes attachment built by the maven-war-plugin.

    If you save that snippet into a file called assembly.xml located under src/assembly, your POM will then look like:

    <plugin>
      <artifactId>maven-war-plugin</artifactId>
      <version>2.6</version>
      <configuration>
        <attachClasses>true</attachClasses>
      </configuration>
    </plugin>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <version>2.6</version>
      <executions>
        <execution>
          <id>make-assembly</id>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
          <configuration>
            <descriptors>
              <descriptor>src/assembly/assembly.xml</descriptor>
            </descriptors>
            <archive>
              <manifest>
                <mainClass>org.miso.mcs.util.MyClass</mainClass>
              </manifest>
            </archive>
          </configuration>
        </execution>
      </executions>
    </plugin>
    

    With such a configuration, you just need to invoke Maven with mvn clean install and it will correctly generate the JAR. Then, you can launch that JAR with java -jar name-of-jar.jar.