-1

I have a project that includes the commons-vfs2 library from org.apache.commons and I would like to "shade" it with the maven-shade-plugin, and also minimizing it.

The problem is that, after I shade the jar, I run it and it tells me it could not find the class org.apache.commons.vfs2.impl.StandardFileSystemManager.

In fact the created jar does not have that class. How comes the shade plugin removes that class? How can I say to the plugin to retain that class?

This is my pom

<?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>blah</groupId>
<artifactId>MyApp</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
    <plugins>
        <!-- Maven Source Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>3.0.1</version>
            <executions>
                <execution>
                    <id>attach-sources</id>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- Maven JavaDoc Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>2.10.4</version>
            <executions>
                <execution>
                    <id>attach-javadocs</id>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- Maven Deploy Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>2.8.2</version>
        </plugin>
        <!-- Maven Shade Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.0.0</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <minimizeJar>true</minimizeJar>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>blah.MyMainFrame</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </plugin>
    </plugins>
</build>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>

    <!-- Apache -->
    <org.apache.commons.lang3.version>3.6</org.apache.commons.lang3.version>
    <org.apache.commons.collections4.version>4.1</org.apache.commons.collections4.version>
    <org.apache.commons.vfs2.version>2.1</org.apache.commons.vfs2.version>
    <org.apache.commons.io.version>2.5</org.apache.commons.io.version>

    <!-- Lombok -->
    <org.projectlombok.version>1.16.18</org.projectlombok.version>

    <!-- Jackson -->
    <com.fasterxml.jackson.version>2.8.9</com.fasterxml.jackson.version>

    <!-- Logging -->
    <org.slf4j.version>1.7.25</org.slf4j.version>
    <ch.qos.logback.version>1.2.3</ch.qos.logback.version>

    <!-- JUnit -->
    <junit.version>4.12</junit.version>
</properties>

<dependencies>
    <!-- Apache -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>${org.apache.commons.lang3.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>${org.apache.commons.collections4.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-vfs2</artifactId>
        <version>${org.apache.commons.vfs2.version}</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>${org.apache.commons.io.version}</version>
    </dependency>

    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${org.projectlombok.version}</version>
    </dependency>

    <!-- Jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${com.fasterxml.jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${com.fasterxml.jackson.version}</version>
        <exclusions>
            <exclusion>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- Logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${org.slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${ch.qos.logback.version}</version>
    </dependency>

    <!-- JUnit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

I use the VFS2 in this code:

import org.apache.commons.vfs2.FileListener;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.impl.DefaultFileMonitor;

public class FileListenerManager{

    private FileSystemManager fsManager;
    private DefaultFileMonitor fm;

    public FileListenerManager(FileListener fl) throws FileSystemException{
        fsManager = VFS.getManager();

        fm = new DefaultFileMonitor(fl);

        start();
    }

    public void addFile(File file) throws FileSystemException{
        fm.addFile(fsManager.resolveFile(file, file.getAbsolutePath()));
    }

    public final void start(){
        fm.start();
    }

    public final void stop(){
        fm.stop();
    }

}

As you can see there is no (explicit) reference to StandardFileSystemManager.

I would like the plugin to take care of what classes or methods should be removed from the final uber jar.

From the VFS.class file I can see that the method VFS.getManager() I called is

public static synchronized FileSystemManager getManager() throws FileSystemException{
    if(instance == null){
        instance = createManager("org.apache.commons.vfs2.impl.StandardFileSystemManager");
    }
    return instance;
}

I wonder why the plugin cannot sense the usage of the StandardFileSystemManager class.

Thank you.

MauroT
  • 320
  • 2
  • 12

1 Answers1

0

You have chosen to enable the minimizeJar option:

<minimizeJar>true</minimizeJar>

Which does this:

automatically remove all classes of dependencies that are not used by the project, thereby minimizing the resulting uber JAR.

But how it determines which classes are used by your project, depends on your code, so we can't reproduce.

If you remove that line, your uber-jar will include all the dependencies. Then you can use exclusions to manually select the parts you don't want.

Or you can keep it and manually select the parts that are excluded, but that you know you need.

For details about properly using it, there's this Q&A.

Hugues M.
  • 19,846
  • 6
  • 37
  • 65
  • See [this comment](https://stackoverflow.com/questions/8817257/minimize-an-uber-jar-correctly-using-shade-plugin#comment35246837_9762835), it is exactly your problem, and the choices you have. So this question is really a duplicate of the one I linked, I should have explained that in a comment instead of replying. – Hugues M. Jul 19 '17 at 08:42
  • I ended up following the suggestions made on the link you gave and I faced another problem, java.lang.ClassNotFoundException: org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider, although it seems to me the right way to follow. I hope to solve all of my problems. Thank you – MauroT Jul 19 '17 at 09:03