leventov
leventov

Reputation: 15283

How to include tools.jar into uberjar (using maven-shade-plugin)?

pom.xml:

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

    <dependencies>
        <dependency>
            <groupId>com.sun</groupId>
            <artifactId>tools</artifactId>
            <version>1.7</version>
            <scope>system</scope>
            <systemPath>${java.home}/../lib/tools.jar</systemPath>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>test.Test</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

mvn install completes successfully, (i.e. maven sees tools.jar dependency during the build), but on execution I have

Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac/api/JavacScope
    at test.Test.main(Test.java:24)
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.api.JavacScope
...

Upvotes: 3

Views: 2647

Answers (2)

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49472

Most <scope>system</scope> dependencies are not made available to plugins.

Also, including the tools.jar in your uberjar isn't terribly portable across newer versions of JVMs. Its fine if you have a super controlled and limited deployment environment, but generally its better to discover the tools.jar and use it.

Here's an example from the maven-javadoc-plugin itself (it looks up the tools.jar and then validates that the active classloader has classes from the tools.jar)

In your case, instead of looking for com.sun.tools.doclets.Taglet, you'd look for com.sun.tools.javac.api.JavacScope to verify a valid environment.

From there it would be trivial to build up a new ClassLoader with your uberjar + tools.jar and then execute what you need from a valid Thread.currentThread().setContextClassLoader() scope

Upvotes: 1

Jigar Joshi
Jigar Joshi

Reputation: 240908

maven-shade plugin assumes System dependencies be present and it doesn't actually include them inside fat-jar

fast dirty workaround is to install tools.jar into your maven repository and refer it as a compile scoped dependency

better workaround is to use maven-assembly-plugin and include tools.jar as a <file>

Upvotes: 1

Related Questions