16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

shaded-jarの作り方

Last updated at Posted at 2020-06-10

Shaded jarとは

Javaでのdependency-hellを回避するための方法の一つ。

元々のコードベースが、ライブラリAのバージョンXに依存しているとする。
このコードベースに新たなライブラリBを追加したい。
しかしながら、ライブラリBはライブラリAのバージョンYに依存しており、
ライブラリAのバージョンXとYは互換性がないという状況を考えよう。

CodeBase
 |- Library A, Version X
 |- Library B
    |- Library A, Version Y # Conflict!!!

このままではライブラリAのバージョンX, Yのどちらを選んでも新規機能と既存機能の
両方を同時に動かすことはできない。

ここで登場するのがshaded-jarである。
Library AのバージョンYのクラスを全てLibrary Bに同梱してしまい、依存関係を排除したライブラリB'を作成するという方法だ。

CodeBase
 |- Library A, Version X
 |- Library B' (include Library A, Version Y)

relocation

しかしそのままではライブラリAに含まれるクラスと、ライブラリB'に同梱したライブラリAのクラスが同じクラスパスに置かれるため、コンフリクトが解消できない。

libraryA-versionX.jar
com.foo.libraryA.Bar.class
...
libraryB'.jar
com.bar.libraryB.Example.class
...
com.foo.libraryA.Bar.class # Conflict!!
...

ここで登場するのがrelocationである。
ライブラリBに同梱されるライブラリAのパッケージ名を変えることでクラスの競合を解消するのだ。

libraryB'.jar
com.bar.libraryB.Example.class
...
shaded.com.foo.libraryA.Bar.class # No Conflict :)
...

この例では com.foo.libraryAshaded.com.foo.libraryAに変更している。
ただリネームしているだけではなく、ライブラリBに含まれるライブラリAのクラスへの参照も全て書き換えることがポイントだ。

shaded-jarの作り方

今回の記事ではmavenを使ったやり方を説明する。

例として追加したいライブラリを com.google.firebase:firebase-admin,
競合を回避したいライブラリを com.google.guava:guavaとしよう。

まず、以下のようなpomファイルを用意する。

pom.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>shadeex</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.google.firebase/firebase-admin -->
        <dependency>
            <groupId>com.google.firebase</groupId>
            <artifactId>firebase-admin</artifactId>
            <version>6.13.0</version>
        </dependency>
    </dependencies>
        
</project>

firebase-adminの依存関係を確認しよう。

$ mvn dependency:tree
...
INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ shadeex ---
[INFO] com.example:shadeex:jar:1.0.0
[INFO] \- com.google.firebase:firebase-admin:jar:6.13.0:compile
[INFO]    +- com.google.api-client:google-api-client:jar:1.30.1:compile
[INFO]    |  +- com.google.oauth-client:google-oauth-client:jar:1.30.1:compile
[INFO]    |  \- com.google.http-client:google-http-client-jackson2:jar:1.30.1:compile
[INFO]    |     \- com.fasterxml.jackson.core:jackson-core:jar:2.9.9:compile
[INFO]    +- com.google.api-client:google-api-client-gson:jar:1.30.1:compile
[INFO]    |  \- com.google.http-client:google-http-client-gson:jar:1.30.1:compile
[INFO]    |     \- com.google.code.gson:gson:jar:2.8.5:compile
[INFO]    +- com.google.http-client:google-http-client:jar:1.30.1:compile
[INFO]    |  +- org.apache.httpcomponents:httpclient:jar:4.5.8:compile
[INFO]    |  |  +- org.apache.httpcomponents:httpcore:jar:4.4.11:compile
[INFO]    |  |  +- commons-logging:commons-logging:jar:1.2:compile
[INFO]    |  |  \- commons-codec:commons-codec:jar:1.11:compile
[INFO]    |  +- com.google.code.findbugs:jsr305:jar:3.0.2:compile
[INFO]    |  +- com.google.j2objc:j2objc-annotations:jar:1.3:compile
[INFO]    |  +- io.opencensus:opencensus-api:jar:0.21.0:compile
[INFO]    |  |  \- io.grpc:grpc-context:jar:1.19.0:compile
[INFO]    |  \- io.opencensus:opencensus-contrib-http-util:jar:0.21.0:compile
[INFO]    +- com.google.api:api-common:jar:1.8.1:compile
[INFO]    |  \- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO]    +- com.google.auth:google-auth-library-oauth2-http:jar:0.17.1:compile
[INFO]    |  +- com.google.auto.value:auto-value-annotations:jar:1.6.6:compile
[INFO]    |  \- com.google.auth:google-auth-library-credentials:jar:0.17.1:compile
[INFO]    +- com.google.cloud:google-cloud-storage:jar:1.91.0:compile
[INFO]    |  +- com.google.cloud:google-cloud-core-http:jar:1.90.0:compile
[INFO]    |  |  +- com.google.cloud:google-cloud-core:jar:1.90.0:compile
[INFO]    |  |  |  +- com.google.protobuf:protobuf-java-util:jar:3.9.1:compile
[INFO]    |  |  |  |  \- com.google.errorprone:error_prone_annotations:jar:2.3.2:compile
[INFO]    |  |  |  \- com.google.api.grpc:proto-google-iam-v1:jar:0.12.0:compile
[INFO]    |  |  +- com.google.http-client:google-http-client-appengine:jar:1.31.0:compile
[INFO]    |  |  \- com.google.api:gax-httpjson:jar:0.65.1:compile
[INFO]    |  |     \- org.threeten:threetenbp:jar:1.3.3:compile
[INFO]    |  \- com.google.apis:google-api-services-storage:jar:v1-rev20190624-1.30.1:compile
[INFO]    +- com.google.cloud:google-cloud-firestore:jar:1.31.0:compile
[INFO]    |  +- com.google.cloud:google-cloud-core-grpc:jar:1.91.3:compile
[INFO]    |  |  +- com.google.api:gax:jar:1.49.1:compile
[INFO]    |  |  \- com.google.api:gax-grpc:jar:1.49.1:compile
[INFO]    |  |     +- io.grpc:grpc-stub:jar:1.23.0:compile
[INFO]    |  |     |  \- io.grpc:grpc-api:jar:1.23.0:compile
[INFO]    |  |     +- io.grpc:grpc-auth:jar:1.23.0:compile
[INFO]    |  |     +- io.grpc:grpc-protobuf:jar:1.23.0:compile
[INFO]    |  |     |  \- io.grpc:grpc-protobuf-lite:jar:1.23.0:compile
[INFO]    |  |     +- io.grpc:grpc-netty-shaded:jar:1.23.0:compile
[INFO]    |  |     |  \- io.grpc:grpc-core:jar:1.23.0:compile (version selected from constraint [1.23.0,1.23.0])
[INFO]    |  |     |     +- com.google.android:annotations:jar:4.1.1.4:compile
[INFO]    |  |     |     +- io.perfmark:perfmark-api:jar:0.17.0:compile
[INFO]    |  |     |     \- io.opencensus:opencensus-contrib-grpc-metrics:jar:0.21.0:compile
[INFO]    |  |     \- io.grpc:grpc-alts:jar:1.23.0:compile
[INFO]    |  |        +- io.grpc:grpc-grpclb:jar:1.23.0:compile
[INFO]    |  |        \- org.apache.commons:commons-lang3:jar:3.5:compile
[INFO]    |  +- com.google.api.grpc:proto-google-cloud-firestore-admin-v1:jar:1.31.0:compile
[INFO]    |  |  +- com.google.protobuf:protobuf-java:jar:3.10.0:compile
[INFO]    |  |  \- com.google.api.grpc:proto-google-common-protos:jar:1.17.0:compile
[INFO]    |  +- com.google.api.grpc:proto-google-cloud-firestore-v1:jar:1.31.0:compile
[INFO]    |  +- com.google.api.grpc:proto-google-cloud-firestore-v1beta1:jar:0.84.0:compile
[INFO]    |  \- io.opencensus:opencensus-contrib-grpc-util:jar:0.24.0:compile
[INFO]    +- com.google.guava:guava:jar:26.0-android:compile
[INFO]    |  +- org.checkerframework:checker-compat-qual:jar:2.5.2:compile
[INFO]    |  \- org.codehaus.mojo:animal-sniffer-annotations:jar:1.14:compile
[INFO]    +- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO]    +- io.netty:netty-codec-http:jar:4.1.45.Final:compile
[INFO]    |  +- io.netty:netty-common:jar:4.1.45.Final:compile
[INFO]    |  +- io.netty:netty-buffer:jar:4.1.45.Final:compile
[INFO]    |  \- io.netty:netty-codec:jar:4.1.45.Final:compile
[INFO]    +- io.netty:netty-handler:jar:4.1.45.Final:compile
[INFO]    \- io.netty:netty-transport:jar:4.1.45.Final:compile
[INFO]       \- io.netty:netty-resolver:jar:4.1.45.Final:compile
...

com.google.guava:guava:jar:26.0-android:compileに依存しているようだ。
android用バージョンに依存しているのは気持ち悪いので、jdk用のバージョンに書き換えて、
依存関係に追加しよう。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>shadeex</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.google.firebase/firebase-admin -->
        <dependency>
            <groupId>com.google.firebase</groupId>
            <artifactId>firebase-admin</artifactId>
            <version>6.13.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>26.0-jre</version>
        </dependency>
    </dependencies>
        
</project>

もう一度依存関係を確認すると以下のようになる。

$ mvn dependency:tree
...
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ shadeex ---
[INFO] com.example:shadeex:jar:1.0.0
[INFO] +- com.google.firebase:firebase-admin:jar:6.13.0:compile
[INFO] |  +- com.google.api-client:google-api-client:jar:1.30.1:compile
[INFO] |  |  +- com.google.oauth-client:google-oauth-client:jar:1.30.1:compile
[INFO] |  |  \- com.google.http-client:google-http-client-jackson2:jar:1.30.1:compile
[INFO] |  |     \- com.fasterxml.jackson.core:jackson-core:jar:2.9.9:compile
[INFO] |  +- com.google.api-client:google-api-client-gson:jar:1.30.1:compile
[INFO] |  |  \- com.google.http-client:google-http-client-gson:jar:1.30.1:compile
[INFO] |  |     \- com.google.code.gson:gson:jar:2.8.5:compile
[INFO] |  +- com.google.http-client:google-http-client:jar:1.30.1:compile
[INFO] |  |  +- org.apache.httpcomponents:httpclient:jar:4.5.8:compile
[INFO] |  |  |  +- org.apache.httpcomponents:httpcore:jar:4.4.11:compile
[INFO] |  |  |  +- commons-logging:commons-logging:jar:1.2:compile
[INFO] |  |  |  \- commons-codec:commons-codec:jar:1.11:compile
[INFO] |  |  +- io.opencensus:opencensus-api:jar:0.21.0:compile
[INFO] |  |  |  \- io.grpc:grpc-context:jar:1.19.0:compile
[INFO] |  |  \- io.opencensus:opencensus-contrib-http-util:jar:0.21.0:compile
[INFO] |  +- com.google.api:api-common:jar:1.8.1:compile
[INFO] |  |  \- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] |  +- com.google.auth:google-auth-library-oauth2-http:jar:0.17.1:compile
[INFO] |  |  +- com.google.auto.value:auto-value-annotations:jar:1.6.6:compile
[INFO] |  |  \- com.google.auth:google-auth-library-credentials:jar:0.17.1:compile
[INFO] |  +- com.google.cloud:google-cloud-storage:jar:1.91.0:compile
[INFO] |  |  +- com.google.cloud:google-cloud-core-http:jar:1.90.0:compile
[INFO] |  |  |  +- com.google.cloud:google-cloud-core:jar:1.90.0:compile
[INFO] |  |  |  |  +- com.google.protobuf:protobuf-java-util:jar:3.9.1:compile
[INFO] |  |  |  |  |  \- com.google.errorprone:error_prone_annotations:jar:2.3.2:compile
[INFO] |  |  |  |  \- com.google.api.grpc:proto-google-iam-v1:jar:0.12.0:compile
[INFO] |  |  |  +- com.google.http-client:google-http-client-appengine:jar:1.31.0:compile
[INFO] |  |  |  \- com.google.api:gax-httpjson:jar:0.65.1:compile
[INFO] |  |  |     \- org.threeten:threetenbp:jar:1.3.3:compile
[INFO] |  |  \- com.google.apis:google-api-services-storage:jar:v1-rev20190624-1.30.1:compile
[INFO] |  +- com.google.cloud:google-cloud-firestore:jar:1.31.0:compile
[INFO] |  |  +- com.google.cloud:google-cloud-core-grpc:jar:1.91.3:compile
[INFO] |  |  |  +- com.google.api:gax:jar:1.49.1:compile
[INFO] |  |  |  \- com.google.api:gax-grpc:jar:1.49.1:compile
[INFO] |  |  |     +- io.grpc:grpc-stub:jar:1.23.0:compile
[INFO] |  |  |     |  \- io.grpc:grpc-api:jar:1.23.0:compile
[INFO] |  |  |     +- io.grpc:grpc-auth:jar:1.23.0:compile
[INFO] |  |  |     +- io.grpc:grpc-protobuf:jar:1.23.0:compile
[INFO] |  |  |     |  \- io.grpc:grpc-protobuf-lite:jar:1.23.0:compile
[INFO] |  |  |     +- io.grpc:grpc-netty-shaded:jar:1.23.0:compile
[INFO] |  |  |     |  \- io.grpc:grpc-core:jar:1.23.0:compile (version selected from constraint [1.23.0,1.23.0])
[INFO] |  |  |     |     +- com.google.android:annotations:jar:4.1.1.4:compile
[INFO] |  |  |     |     +- io.perfmark:perfmark-api:jar:0.17.0:compile
[INFO] |  |  |     |     \- io.opencensus:opencensus-contrib-grpc-metrics:jar:0.21.0:compile
[INFO] |  |  |     \- io.grpc:grpc-alts:jar:1.23.0:compile
[INFO] |  |  |        +- io.grpc:grpc-grpclb:jar:1.23.0:compile
[INFO] |  |  |        \- org.apache.commons:commons-lang3:jar:3.5:compile
[INFO] |  |  +- com.google.api.grpc:proto-google-cloud-firestore-admin-v1:jar:1.31.0:compile
[INFO] |  |  |  +- com.google.protobuf:protobuf-java:jar:3.10.0:compile
[INFO] |  |  |  \- com.google.api.grpc:proto-google-common-protos:jar:1.17.0:compile
[INFO] |  |  +- com.google.api.grpc:proto-google-cloud-firestore-v1:jar:1.31.0:compile
[INFO] |  |  +- com.google.api.grpc:proto-google-cloud-firestore-v1beta1:jar:0.84.0:compile
[INFO] |  |  \- io.opencensus:opencensus-contrib-grpc-util:jar:0.24.0:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO] |  +- io.netty:netty-codec-http:jar:4.1.45.Final:compile
[INFO] |  |  +- io.netty:netty-common:jar:4.1.45.Final:compile
[INFO] |  |  +- io.netty:netty-buffer:jar:4.1.45.Final:compile
[INFO] |  |  \- io.netty:netty-codec:jar:4.1.45.Final:compile
[INFO] |  +- io.netty:netty-handler:jar:4.1.45.Final:compile
[INFO] |  \- io.netty:netty-transport:jar:4.1.45.Final:compile
[INFO] |     \- io.netty:netty-resolver:jar:4.1.45.Final:compile
[INFO] \- com.google.guava:guava:jar:26.0-jre:compile
[INFO]    +- com.google.code.findbugs:jsr305:jar:3.0.2:compile
[INFO]    +- org.checkerframework:checker-qual:jar:2.5.2:compile
[INFO]    +- com.google.j2objc:j2objc-annotations:jar:1.1:compile
[INFO]    \- org.codehaus.mojo:animal-sniffer-annotations:jar:1.14:compile
...

さて、ここからshaded-jarの設定をしていく。

pom.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>shadeex</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                          ...
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    ... 
</project>

shade-jarを作るのには maven-shade-pluginを使う。

configurations以下が重要なので詳しく説明しよう。

<configuration>
    <artifactSet>
        <includes>
            <include>com.google.guava:guava</include>
            <include>com.google.firebase:firebase-admin</include>
        </includes>
    </artifactSet>
    <relocations>
        <relocation>
            <pattern>com.google</pattern>
            <shadedPattern>com.example.shaded.com.google</shadedPattern>
            <excludes>
                <exclude>com.google.firebase.**</exclude>
            </excludes>
        </relocation>
    </relocations>
</configuration>

<artifactSet>でshaded-jarに同梱するartifactの一覧を設定する。
今回のメインとなる、firebase-adminと、同梱したい依存ライブラリ guavaを指定している。

<relocations>でrelocationの設定を行う。
<pattern>にはrelocationしたいjavaパッケージのprefixをつける。
guava.jarの中には com.google.common.**com.google.thirdparty.**が含まれている
ので com.googleを指定した。
一方で firebase-adminには com.google.firebase.**が含まれており、
firebase-admin自体のrelocationは必要ないので <excludes>で除外設定をしている。

これで設定は終わりである。実行してどのようなjarが作られるか確認しよう。

$ mvn package

target/shadeex-1.0.0.jarにshaded-jarが出力される。
中身を確認してみると、確かに、guava.jarに含まれるクラスがrelocationされていることがわかる。

$ unzip -l target/shadeex-1.0.0.jar  | grep 'com/example/shaded' | head
        0  04-13-2020 17:23   com/example/shaded/
        0  04-13-2020 17:23   com/example/shaded/com/
        0  04-13-2020 17:23   com/example/shaded/com/google/
        0  04-13-2020 17:23   com/example/shaded/com/google/common/
        0  04-13-2020 17:23   com/example/shaded/com/google/common/annotations/
      624  04-13-2020 17:23   com/example/shaded/com/google/common/annotations/Beta.class
      678  04-13-2020 17:23   com/example/shaded/com/google/common/annotations/GwtCompatible.class
      686  04-13-2020 17:23   com/example/shaded/com/google/common/annotations/GwtIncompatible.class
      312  04-13-2020 17:23   com/example/shaded/com/google/common/annotations/VisibleForTesting.class
        0  04-13-2020 17:23   com/example/shaded/com/google/common/base/

一方で、 firebase-admin.jarのクラスはrelocationされていない。

$ unzip -l target/shadeex-1.0.0.jar  | grep -v 'shaded' | grep 'com/google' | head
        0  05-14-2020 19:36   com/google/
        0  05-14-2020 19:36   com/google/firebase/
        0  05-14-2020 19:36   com/google/firebase/messaging/
     1647  05-14-2020 19:36   com/google/firebase/messaging/Notification$Builder.class
     4528  05-14-2020 19:36   com/google/firebase/messaging/AndroidConfig$Builder.class
     1340  05-14-2020 19:36   com/google/firebase/messaging/AndroidFcmOptions$Builder.class
      277  05-14-2020 19:36   com/google/firebase/messaging/TopicManagementResponse$1.class
     1492  05-14-2020 19:36   com/google/firebase/messaging/TopicManagementResponse$Error.class
      409  05-14-2020 19:36   com/google/firebase/messaging/BatchResponse.class
     2910  05-14-2020 19:36   com/google/firebase/messaging/CriticalSound.class

また、それ以外の依存ライブラリのクラスは同梱されない。

$ unzip -l target/shadeex-1.0.0.jar  | grep -v 'shaded' | grep -v 'com/google' 
Archive:  target/shadeex-1.0.0.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  06-11-2020 00:24   META-INF/
      135  06-11-2020 00:24   META-INF/MANIFEST.MF
        0  06-11-2020 00:24   META-INF/maven/
        0  06-11-2020 00:24   META-INF/maven/com.example/
        0  06-11-2020 00:24   META-INF/maven/com.example/shadeex/
     2603  06-11-2020 00:24   META-INF/maven/com.example/shadeex/pom.xml
      103  06-10-2020 23:05   META-INF/maven/com.example/shadeex/pom.properties
      599  05-14-2020 19:36   admin_sdk.properties
        0  05-14-2020 19:36   com/
        0  05-14-2020 19:35   META-INF/maven/com.google.firebase/
        0  05-14-2020 19:35   META-INF/maven/com.google.firebase/firebase-admin/
    19833  05-14-2020 19:35   META-INF/maven/com.google.firebase/firebase-admin/pom.xml
      119  05-14-2020 19:36   META-INF/maven/com.google.firebase/firebase-admin/pom.properties
        0  04-13-2020 17:23   META-INF/maven/com.google.guava/
        0  04-13-2020 17:23   META-INF/maven/com.google.guava/guava/
      133  04-13-2020 17:23   META-INF/maven/com.google.guava/guava/pom.properties
    10920  04-13-2020 17:12   META-INF/maven/com.google.guava/guava/pom.xml
        0  04-13-2020 17:23   com/example/
---------                     -------
  8638864                     2699 files

maven-shade-pluginはshaded-jar用のpom.xmldependency-reduced-pom.xmlに出力してくれる。

dependency-reduced-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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>shadeex</artifactId>
  <version>1.0.0</version>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <artifactSet>
                <includes>
                  <include>com.google.guava:guava</include>
                  <include>com.google.firebase:firebase-admin</include>
                </includes>
              </artifactSet>
              <relocations>
                <relocation>
                  <pattern>com.google</pattern>
                  <shadedPattern>com.example.shaded.com.google</shadedPattern>
                  <excludes>
                    <exclude>com.google.firebase.**</exclude>
                  </excludes>
                </relocation>
              </relocations>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

同梱した guavafirebase-adminのdependencyが消えていることがわかるだろう。

しかし、このpomには問題がある。
それは firebase-adminの依存ライブラリはguava以外にもあったということだ。

$ mvn dependency:tree
...
INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ shadeex ---
[INFO] com.example:shadeex:jar:1.0.0
[INFO] \- com.google.firebase:firebase-admin:jar:6.13.0:compile
[INFO]    +- com.google.api-client:google-api-client:jar:1.30.1:compile
[INFO]    |  +- com.google.oauth-client:google-oauth-client:jar:1.30.1:compile
[INFO]    |  \- com.google.http-client:google-http-client-jackson2:jar:1.30.1:compile
[INFO]    |     \- com.fasterxml.jackson.core:jackson-core:jar:2.9.9:compile
[INFO]    +- com.google.api-client:google-api-client-gson:jar:1.30.1:compile
[INFO]    |  \- com.google.http-client:google-http-client-gson:jar:1.30.1:compile
[INFO]    |     \- com.google.code.gson:gson:jar:2.8.5:compile
[INFO]    +- com.google.http-client:google-http-client:jar:1.30.1:compile
[INFO]    |  +- org.apache.httpcomponents:httpclient:jar:4.5.8:compile
[INFO]    |  |  +- org.apache.httpcomponents:httpcore:jar:4.4.11:compile
[INFO]    |  |  +- commons-logging:commons-logging:jar:1.2:compile
[INFO]    |  |  \- commons-codec:commons-codec:jar:1.11:compile
[INFO]    |  +- com.google.code.findbugs:jsr305:jar:3.0.2:compile
[INFO]    |  +- com.google.j2objc:j2objc-annotations:jar:1.3:compile
[INFO]    |  +- io.opencensus:opencensus-api:jar:0.21.0:compile
[INFO]    |  |  \- io.grpc:grpc-context:jar:1.19.0:compile
[INFO]    |  \- io.opencensus:opencensus-contrib-http-util:jar:0.21.0:compile
[INFO]    +- com.google.api:api-common:jar:1.8.1:compile
[INFO]    |  \- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO]    +- com.google.auth:google-auth-library-oauth2-http:jar:0.17.1:compile
[INFO]    |  +- com.google.auto.value:auto-value-annotations:jar:1.6.6:compile
[INFO]    |  \- com.google.auth:google-auth-library-credentials:jar:0.17.1:compile
[INFO]    +- com.google.cloud:google-cloud-storage:jar:1.91.0:compile
[INFO]    |  +- com.google.cloud:google-cloud-core-http:jar:1.90.0:compile
[INFO]    |  |  +- com.google.cloud:google-cloud-core:jar:1.90.0:compile
[INFO]    |  |  |  +- com.google.protobuf:protobuf-java-util:jar:3.9.1:compile
[INFO]    |  |  |  |  \- com.google.errorprone:error_prone_annotations:jar:2.3.2:compile
[INFO]    |  |  |  \- com.google.api.grpc:proto-google-iam-v1:jar:0.12.0:compile
[INFO]    |  |  +- com.google.http-client:google-http-client-appengine:jar:1.31.0:compile
[INFO]    |  |  \- com.google.api:gax-httpjson:jar:0.65.1:compile
[INFO]    |  |     \- org.threeten:threetenbp:jar:1.3.3:compile
[INFO]    |  \- com.google.apis:google-api-services-storage:jar:v1-rev20190624-1.30.1:compile
[INFO]    +- com.google.cloud:google-cloud-firestore:jar:1.31.0:compile
[INFO]    |  +- com.google.cloud:google-cloud-core-grpc:jar:1.91.3:compile
[INFO]    |  |  +- com.google.api:gax:jar:1.49.1:compile
[INFO]    |  |  \- com.google.api:gax-grpc:jar:1.49.1:compile
[INFO]    |  |     +- io.grpc:grpc-stub:jar:1.23.0:compile
[INFO]    |  |     |  \- io.grpc:grpc-api:jar:1.23.0:compile
[INFO]    |  |     +- io.grpc:grpc-auth:jar:1.23.0:compile
[INFO]    |  |     +- io.grpc:grpc-protobuf:jar:1.23.0:compile
[INFO]    |  |     |  \- io.grpc:grpc-protobuf-lite:jar:1.23.0:compile
[INFO]    |  |     +- io.grpc:grpc-netty-shaded:jar:1.23.0:compile
[INFO]    |  |     |  \- io.grpc:grpc-core:jar:1.23.0:compile (version selected from constraint [1.23.0,1.23.0])
[INFO]    |  |     |     +- com.google.android:annotations:jar:4.1.1.4:compile
[INFO]    |  |     |     +- io.perfmark:perfmark-api:jar:0.17.0:compile
[INFO]    |  |     |     \- io.opencensus:opencensus-contrib-grpc-metrics:jar:0.21.0:compile
[INFO]    |  |     \- io.grpc:grpc-alts:jar:1.23.0:compile
[INFO]    |  |        +- io.grpc:grpc-grpclb:jar:1.23.0:compile
[INFO]    |  |        \- org.apache.commons:commons-lang3:jar:3.5:compile
[INFO]    |  +- com.google.api.grpc:proto-google-cloud-firestore-admin-v1:jar:1.31.0:compile
[INFO]    |  |  +- com.google.protobuf:protobuf-java:jar:3.10.0:compile
[INFO]    |  |  \- com.google.api.grpc:proto-google-common-protos:jar:1.17.0:compile
[INFO]    |  +- com.google.api.grpc:proto-google-cloud-firestore-v1:jar:1.31.0:compile
[INFO]    |  +- com.google.api.grpc:proto-google-cloud-firestore-v1beta1:jar:0.84.0:compile
[INFO]    |  \- io.opencensus:opencensus-contrib-grpc-util:jar:0.24.0:compile
[INFO]    +- com.google.guava:guava:jar:26.0-android:compile
[INFO]    |  +- org.checkerframework:checker-compat-qual:jar:2.5.2:compile
[INFO]    |  \- org.codehaus.mojo:animal-sniffer-annotations:jar:1.14:compile
[INFO]    +- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO]    +- io.netty:netty-codec-http:jar:4.1.45.Final:compile
[INFO]    |  +- io.netty:netty-common:jar:4.1.45.Final:compile
[INFO]    |  +- io.netty:netty-buffer:jar:4.1.45.Final:compile
[INFO]    |  \- io.netty:netty-codec:jar:4.1.45.Final:compile
[INFO]    +- io.netty:netty-handler:jar:4.1.45.Final:compile
[INFO]    \- io.netty:netty-transport:jar:4.1.45.Final:compile
[INFO]       \- io.netty:netty-resolver:jar:4.1.45.Final:compile

しかし、dependency-reduced-pom.xmlではこれらのライブラリのdependencyが取り除かれてしまっている。

この問題を解決するオプションが <promoteTransitiveDependencies>である。
このオプションを指定することで、 firebase-adminの依存ライブラリが全て、 dependency-reduced-pom.xmlの直接のdependencyとして記載され、その後、 firebase-adminguavaが取り除かれる。

したがって同梱しないライブラリの依存関係を正しく残すことができる。

最終的なpom.xmlは以下のようになる。

pom.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>shadeex</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
                            <artifactSet>
                                <includes>
                                    <include>com.google.guava:guava</include>
                                    <include>com.google.firebase:firebase-admin</include>
                                </includes>
                            </artifactSet>
                            <relocations>
                                <relocation>
                                    <pattern>com.google</pattern>
                                    <shadedPattern>com.example.shaded.com.google</shadedPattern>
                                    <excludes>
                                        <exclude>com.google.firebase.**</exclude>
                                    </excludes>
                                </relocation>
                            </relocations>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.google.firebase/firebase-admin -->
        <dependency>
            <groupId>com.google.firebase</groupId>
            <artifactId>firebase-admin</artifactId>
            <version>6.13.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>
    </dependencies>
        
</project>

これに対して、mvn packageを実行して出力されるdependency-reduced-pom.xmlは以下のようになる。

dependency-reduced-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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>shadeex</artifactId>
  <version>1.0.0</version>
  <build>
    ...
  </build>
  <dependencies>
    <dependency>
      <groupId>com.google.api-client</groupId>
      <artifactId>google-api-client</artifactId>
      <version>1.30.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.google.oauth-client</groupId>
      <artifactId>google-oauth-client</artifactId>
      <version>1.30.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.google.http-client</groupId>
      <artifactId>google-http-client-jackson2</artifactId>
      <version>1.30.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.9</version>
      <scope>compile</scope>
    </dependency>
    ...
  </dependencies>
</project>

firebase-adminの依存ライブラリが正しく残っている。

あとは このjarとdependency-reduced-pom.xmlをinternal maven repositoryにアップロードすればよい。

参考文献

Apache Maven Shade Plugin

16
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?