32

I am using the Maven-Shade-Plugin to create a runnable Uber-jar. According to the last frame on this page, the size of the jar can be minimized by using:

<configuration>
      <minimizeJar>true</minimizeJar>
</configuration>

But this feature does not take into consideration the classes that are declared in the log4j.properties file. Hence, e.g. org.apache.log4j.appender.TimeAndSizeRollingAppender is not included in the Uber-jar, even though it’s declared in the log4j.properties file.

I believe I will face the same problem with Spring. If my code only refers to interface A and my Spring file contains an instantiation of class B that implements A, then B might not be added to the jar, since it’s not in the code.

How can I solve this problem?

summerbulb
  • 5,709
  • 8
  • 37
  • 83
  • Alsmot, but not quite, a duplicate of http://stackoverflow.com/questions/8698814/configure-maven-shade-minimizejar-to-include-class-files – Raedwald Apr 26 '13 at 15:02

1 Answers1

42

This functionality has been added to version 1.6 of the maven-shade-plugin (just released). minimizeJar will now not remove classes that have been specifically included with filters. Note that including some of an artifact's classes in a filter will exclude non-specified classes for that artifact, so be sure to include all the classes that you need.

Here's an example plugin config:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>1.6</version>    
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>                        
            <configuration>
                <minimizeJar>true</minimizeJar>    
                <filters> 
                    <filter>
                       <artifact>log4j:log4j</artifact>
                       <includes>
                           <include>**</include>
                       </includes>
                    </filter> 
                    <filter>
                       <artifact>commons-logging:commons-logging</artifact>
                       <includes>
                           <include>**</include>
                       </includes>
                    </filter>                      
                </filters>
            </configuration>
        </execution>
    </executions>
</plugin>

To only include specific classes, add them as includes using path slashes in the class name in a filter (again, non-included classes will be automatically excluded).

<filter>
  <artifact>org.yourorg:your-artifact</artifact>
  <includes>
    <include>org/yourorg/yourartifact/api/*</include>
    <include>org/yourorg/yourartifact/util/*</include>
  </includes>
</filter>
rjdkolb
  • 10,377
  • 11
  • 69
  • 89
Shane
  • 4,179
  • 1
  • 28
  • 26
  • A copy of the Maven documentation. – Raedwald Apr 30 '13 at 13:47
  • Can you support "always keep specific classes" option? For instance, a configuration lists particular classes/masks to keep, and maven-shade-plugin automatically calculates unused classes? – Vladimir Sitnikov Nov 29 '13 at 13:54
  • @VladimirSitnikov Edited answer, I believe the includes filter at the bottom should work to include specific classes. – Shane Dec 02 '13 at 10:41
  • >again, non-included classes will be automatically excluded I do not want to manually figure out all the classes I need to include. – Vladimir Sitnikov Apr 11 '14 at 12:16
  • 1
    I do not want to manually figure out all the classes I need to include. For instance, jarjar ant plugin automatically scans for the used classes and all you need to do is to specify Main class – Vladimir Sitnikov Apr 14 '14 at 08:04
  • 5
    maven-shade-plugin already scans a project for dependencies and automatically includes then when using `true`. However, when your code or a depdendency uses dynamic class loading, there's no way for maven-shade-plugin to detect a dependency on the dynamically loaded classes, so you **have to** manually include those dependencies using filter includes as demonstrated here. If you don't want to do this, use `false` and just deal with the larger shaded jar. Those are your choices. – Shane Apr 14 '14 at 16:26
  • In this case Proguard is the way to go... It can handle things when a depdendency uses dynamic class loading. – Stephan Feb 02 '16 at 01:03
  • Does Proguard have a runtime profile aspect to gather details of which classes are actually accessed, that it uses to feed the jar-minification-generation-thingie? – JeeBee Oct 18 '16 at 15:55