How to shade a jar into uber jar and make uber jar's pom depending on shaded jar's dependencies?

27 Views Asked by At

I created a multi-module maven project in my IDE, which is structured in following form:

├── pom.xml # root pom.xml
├── commons
│   ├── pom.xml # commons pom.xml  -[child of     ]-> root pom.xml
│   ├── bom     # bom pom.xml      -[detached from]-> root pom.xml
│   └── core    # core             -[sub module of]-> commons
├── releases
│   ├── pom.xml # releases pom.xml -[detached from]-> root pom.xml
│   └── client  # client           -[sub module of]-> releases
└── services
    ├── pom.xml # services pom.xml -[child of     ]-> root pom.xml
    ├── xx-api  # xx-api           -[sub module of]-> services 
    └── xx-impl # xx-impl          -[sub module of]-> services

Note that releases and its sub modules is intended for deploying to a private maven repo, and here's an example of pom.xml files for those modules.

The ROOT pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>commons</module>
        <module>services</module>
        <module>releases</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.demo</groupId>
                <artifactId>bom</artifactId>
                <version>1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

The releases pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo</groupId>
    <artifactId>releases</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>client</module>
    </modules>
    <distributionManagement/> <!-- intended for a deploy into a private maven repo -->
</project>

The releases/client pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>releases</artifactId>
        <groupId>com.demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.demo</groupId>
            <artifactId>xx-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- other dependencies -->
   </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.3.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <!--
                            ONLY shade com.demo:* artifacts in this uber jar!
                            We don't want artifacts like core or xx-api
                            being released to maven repo
                            -->
                            <artifactSet>
                                <includes>
                                    <include>com.demo</include>
                                </includes>
                            </artifactSet>
                            <shadedArtifactAttached>true</shadedArtifactAttached>
                            <shadedClassifierName>all</shadedClassifierName>
                            <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

The services pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>demo</artifactId>
        <groupId>com.demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>services</artifactId>

    <packaging>pom</packaging>
    <modules>
        <module>xx-impl</module>
        <module>xx-api</module>
    </modules>
</project>

The services/xx-api pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>services</artifactId>
        <groupId>com.demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.demo</groupId>
            <artifactId>core</artifactId> <!-- version is reduced by "bom" module -->
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId> <!-- version is reduced by "bom" module -->
        </dependency>
        <!-- other dependencies -->
   </dependencies>
</project>

After running mvn clean install, i installed those modules into my local maven repo, then i cd into releases to execute mvn deploy. Then releases/pom.xml, releases/client.jar, releases/client-all.jar were deployed into the private maven repo.

But when i create a new maven project to import the client-all.jar for unit testing, i got an exception claimed that classess xx-api or core depended is missing.

It turns out that module client is not depending on dependencies xx-api is depended on, and i want know how to make client depending on dependencies xx-api depended automaticly.

Any reply will be appreciated.

0

There are 0 best solutions below