15

I am trying to minimize the UberJar's size by using Maven Shade Plugin's minimizeJar. It looks like minimizeJar only includes classes that are statically imported in the code (I suspect this because I see LogFactory.class in uber jar at org\apache\commons\logging\ but no classes of the impl package are included, hence throwing java.lang.ClassNotFoundException: org.apache.commons.logging.impl.LogFactoryImpl when I run the uber-jar).

Is there any way I can tell Maven's Shade plugin to include specified packages into the final jar no matter what the minimizeJar suggests?

Here the pom snippet of what I am trying:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.5</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <minimizeJar>true</minimizeJar>
                    <filters>
                        <filter>
                            <artifact>commons-logging:commons-logging</artifact>
                            <includes>
                                <include>org/apache/commons/logging/**</include>
                            </includes>
                        </filter>    
                    </filters>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.myproject.Main</mainClass>
                        </transformer>
                    </transformers>                            
                </configuration>
            </execution>
        </executions>
    </plugin>
Sled
  • 18,541
  • 27
  • 119
  • 168
kdabir
  • 9,623
  • 3
  • 43
  • 45
  • 1
    `org/apache/commons/logging/**` only matches directories, you maybe want to match all files. Use `org/apache/commons/logging/**/*` instead. – Corubba Jan 02 '12 at 12:00
  • Following your suggestion, I tried `...logging/**` , `...logging/**/*`, `...logging/**/*.*` but none worked. I guess the problem is includes are included first then minimizeJar ignores everything else and bundles the jar as it thinks is suitable. – kdabir Jan 02 '12 at 13:24

2 Answers2

16

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>
Shane
  • 4,179
  • 1
  • 28
  • 26
  • 1
    The bottom-level `**` didn't work for me. It seems to include a lot of things from other packages too. Instead I had to use `org/apache/logging/log4j/** Log4j-*` – Quantum7 Mar 17 '14 at 16:38
  • Still not work with version 3.2.4 – scruel Oct 28 '21 at 10:40
13

I am using the 2.0 version of the Maven Shade Plugin and still I am not able to include classes after "minimizing" the JAR.

As a workaround the only thing that comes to my mind is to create references to the needed classes to avoid the minimization code to get rid of them. ie:

/*
 * This block prevents the Maven Shade plugin to remove the specified classes
 */
static {
    @SuppressWarnings ("unused") Class<?>[] classes = new Class<?>[] {
        JButton.class,
        JMenu.class,
        JMenuBar.class,
        JMenuItem.class
    };
}

I hope Maven developers implement a way to handle this situation (which I guess is very common).

jaguililla
  • 1,916
  • 18
  • 21