Maven shade plugin relocate and bundle not working

3.9k views Asked by At

In my POM.xml, I have used maven-shade plugin and relocated the httpClient dependency. But when I print the dependency tree using mvn dependency:tree, I still see the httpClient library in the tree as shown below. Why is this happening. Any help will be appreciated.

[INFO]    +- org.apache.httpcomponents:httpclient:jar:4.3.5:provided

My POM.xml is as below.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <version>1.0-SNAPSHOT</version>
 <artifactId>parser</artifactId>
  <packaging>jar</packaging>

 <!-- change these to the appropriate values -->
  <name>Parser Apps</name>
  <description>Applications to showcase different parsers</description>

  <properties>
<!-- change this if you desire to use a different version of Apex Core -->
<apex.version>3.4.0</apex.version>
    <apex.apppackage.classpath>lib/*.jar</apex.apppackage.classpath>
   <malhar.version>3.4.0</malhar.version>
 </properties>

  <build>
<plugins>
   <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-eclipse-plugin</artifactId>
     <version>2.9</version>
     <configuration>
       <downloadSources>true</downloadSources>
     </configuration>
   </plugin>
   <plugin>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>3.3</version>
     <configuration>
       <encoding>UTF-8</encoding>
       <source>1.7</source>
       <target>1.7</target>
       <debug>true</debug>
       <optimize>false</optimize>
       <showDeprecation>true</showDeprecation>
       <showWarnings>true</showWarnings>
     </configuration>
   </plugin>
   <plugin>
     <artifactId>maven-dependency-plugin</artifactId>
     <version>2.8</version>
     <executions>
       <execution>
         <id>copy-dependencies</id>
         <phase>prepare-package</phase>
         <goals>
           <goal>copy-dependencies</goal>
         </goals>
         <configuration>
           <outputDirectory>target/deps</outputDirectory>
           <includeScope>runtime</includeScope>
         </configuration>
       </execution>
     </executions>
   </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.4.3</version>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
        <configuration>
          <artifactSet>
            <includes>
              <include>org.apache.httpcomponents.*</include>
            </includes>
          </artifactSet>
          <relocations>
            <relocation>
              <pattern>org.apache.httpcomponents</pattern>
              <shadedPattern>org.shaded.httpcomponents</shadedPattern>
            </relocation>
          </relocations>
        </configuration>
      </execution>
    </executions>
  </plugin>
   <plugin>
     <artifactId>maven-assembly-plugin</artifactId>
     <executions>
       <execution>
         <id>app-package-assembly</id>
         <phase>package</phase>
         <goals>
           <goal>single</goal>
         </goals>
         <configuration>
           <finalName>${project.artifactId}-${project.version}-apexapp</finalName>
           <appendAssemblyId>false</appendAssemblyId>
           <descriptors>
             <descriptor>src/assemble/appPackage.xml</descriptor>
           </descriptors>
           <archiverConfig>
             <defaultDirectoryMode>0755</defaultDirectoryMode>
           </archiverConfig>
           <archive>
             <manifestEntries>
               <Class-Path>${apex.apppackage.classpath}</Class-Path>
               <DT-Engine-Version>${apex.version}</DT-Engine-Version>
               <DT-App-Package-Group-Id>${project.groupId}</DT-App-Package-Group-Id>
               <DT-App-Package-Name>${project.artifactId}</DT-App-Package-Name>
               <DT-App-Package-Version>${project.version}</DT-App-Package-Version>
               <DT-App-Package-Display-Name>${project.name}</DT-App-Package-Display-Name>
               <DT-App-Package-Description>${project.description}</DT-App-Package-Description>
             </manifestEntries>
           </archive>
         </configuration>
       </execution>
     </executions>
   </plugin>

   <plugin>
     <artifactId>maven-antrun-plugin</artifactId>
     <version>1.7</version>
     <executions>
       <execution>
         <phase>package</phase>
         <configuration>
           <target>
             <move file="${project.build.directory}/${project.artifactId}-${project.version}-apexapp.jar"
                   tofile="${project.build.directory}/${project.artifactId}-${project.version}.apa" />
           </target>
         </configuration>
         <goals>
           <goal>run</goal>
         </goals>
       </execution>
       <execution>
         <!-- create resource directory for xml javadoc-->
         <id>createJavadocDirectory</id>
         <phase>generate-resources</phase>
         <configuration>
           <tasks>
             <delete dir="${project.build.directory}/generated-resources/xml-javadoc"/>
             <mkdir dir="${project.build.directory}/generated-resources/xml-javadoc"/>
           </tasks>
         </configuration>
         <goals>
           <goal>run</goal>
         </goals>
       </execution>
     </executions>
   </plugin>

   <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>build-helper-maven-plugin</artifactId>
     <version>1.9.1</version>
     <executions>
       <execution>
         <id>attach-artifacts</id>
         <phase>package</phase>
         <goals>
           <goal>attach-artifact</goal>
         </goals>
         <configuration>
           <artifacts>
             <artifact>
               <file>target/${project.artifactId}-${project.version}.apa</file>
               <type>apa</type>
             </artifact>
           </artifacts>
           <skipAttach>false</skipAttach>
         </configuration>
       </execution>
     </executions>
   </plugin>

  <!-- generate javdoc -->
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <executions>
      <!-- generate xml javadoc -->
      <execution>
        <id>xml-doclet</id>
        <phase>generate-resources</phase>
        <goals>
          <goal>javadoc</goal>
        </goals>
        <configuration>
          <doclet>com.github.markusbernhardt.xmldoclet.XmlDoclet</doclet>
          <additionalparam>-d ${project.build.directory}/generated-resources/xml-javadoc -filename ${project.artifactId}-${project.version}-javadoc.xml</additionalparam>
          <useStandardDocletOptions>false</useStandardDocletOptions>
          <docletArtifact>
            <groupId>com.github.markusbernhardt</groupId>
            <artifactId>xml-doclet</artifactId>
            <version>1.0.4</version>
          </docletArtifact>
        </configuration>
      </execution>
    </executions>
  </plugin>
  <!-- Transform xml javadoc to stripped down version containing only class/interface comments and tags-->
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>xml-maven-plugin</artifactId>
    <version>1.0</version>
    <executions>
      <execution>
        <id>transform-xmljavadoc</id>
        <phase>generate-resources</phase>
        <goals>
          <goal>transform</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <transformationSets>
        <transformationSet>
          <dir>${project.build.directory}/generated-resources/xml-javadoc</dir>
          <includes>
            <include>${pmalhar.versioroject.artifactId}-${project.version}-javadoc.xml</include>
          </includes>
          <stylesheet>XmlJavadocCommentsExtractor.xsl</stylesheet>
          <outputDir>${project.build.directory}/generated-resources/xml-javadoc</outputDir>
        </transformationSet>
      </transformationSets>
    </configuration>
  </plugin>
  <!-- copy xml javadoc to class jar -->
  <plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.6</version>
    <executions>
      <execution>
        <id>copy-resources</id>
        <phase>process-resources</phase>
        <goals>
          <goal>copy-resources</goal>
        </goals>
        <configuration>
          <outputDirectory>${basedir}/target/classes</outputDirectory>
          <resources>
            <resource>
              <directory>${project.build.directory}/generated-resources/xml-javadoc</directory>
              <includes>
                <include>${project.artifactId}-${project.version}-javadoc.xml</include>
              </includes>
              <filtering>true</filtering>
            </resource>
          </resources>
        </configuration>
      </execution>
    </executions>
  </plugin>

</plugins>

 </build>

  <dependencies>
<!-- add your dependencies here -->
<dependency>
  <groupId>org.apache.apex</groupId>
  <artifactId>malhar-library</artifactId>
  <version>${malhar.version}</version>
  <!--
       If you know that your application does not need transitive dependencies pulled in by malhar-library,
       uncomment the following to reduce the size of your app package.
  -->
  <!--
  <exclusions>
    <exclusion>
      <groupId>*</groupId>
      <artifactId>*</artifactId>
    </exclusion>
  </exclusions>
  -->
</dependency>
<dependency>
  <groupId>org.apache.apex</groupId>
  <artifactId>malhar-contrib</artifactId>
  <version>${malhar.version}</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.5.4</version>
</dependency>
<dependency>
  <groupId>com.github.fge</groupId>
  <artifactId>json-schema-validator</artifactId>
  <version>2.0.1</version>
  <optional>true</optional>
</dependency>
<dependency>
  <groupId>net.sf.supercsv</groupId>
  <artifactId>super-csv</artifactId>
  <version>2.4.0</version>
  <optional>true</optional>
</dependency>
<dependency>
  <groupId>org.apache.apex</groupId>
  <artifactId>apex-common</artifactId>
  <version>${apex.version}</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.10</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.apex</groupId>
  <artifactId>apex-engine</artifactId>
  <version>${apex.version}</version>
  <scope>provided</scope>
</dependency>

2

There are 2 answers

0
Naman On

Two things -

  1. You should be aware what relocation does is not "...relocated the httpClient dependency" but as the source suggests -

    If the uber JAR is reused as a dependency of some other project, directly including classes from the artifact's dependencies in the uber JAR can cause class loading conflicts due to duplicate classes on the class path. To address this issue, one can relocate the classes which get included in the shaded artifact in order to create a private copy of their bytecode

  2. When you execute the mvn dependency:tree it would display all the dependencies(direct and transitive) included in your project. Instead, the maven shade plugin

shade:shade is bound to the package phase and is used to create a shaded jar.

renaming or optimizing the dependencies further. Here goes the details for Maven Shade Plugin -

This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.

0
Hugues M. On

The dependency is not removed from original POM, so the behavior of dependency:tree is correct.

Shade plugin will also generate a new POM (dependency-reduced-pom.xml) wherein shaded dependencies are removed from the <dependencies> section. This looks like the one you are after.