LoginSignup
1
0

More than 1 year has passed since last update.

MavenでGoogleAdsAPIを使用する実行可能Jarを作成するときに気を付けること

Posted at

記事を書くに至ったきっかけ

タイトルの通りのことをやろうとした時に、あるエラーがなかなか解決できず(2022/04/27時点)、Mavenの設定やらで少し調べることになったので、備忘録も兼ねて記事を書くことにしました。

問題になったエラー

io.grpc.internal.ManagedChannelImpl$2 uncaughtException
重大: [Channel<1>: (googleads.googleapis.com:443)] Uncaught exception in the SynchronizationContext. Panic!
java.lang.IllegalStateException: Could not find policy 'pick_first'. 
Make sure its implementation is either registered to LoadBalancerRegistry or included in META-INF/services/io.grpc.LoadBalancerProvider from your jar files.

MavenプロジェクトにGoogleAdsAPIとその依存関係をimportするだけではエラーが起き、そのエラーはどうやらgRPC絡みのようです。

ちなみに、gRPCはGoogleが開発したプロトコルであり、GoogleのAPIではデフォルトでこのプロトコルが使われるように実装されています。
gRPCが用いるデータ通信方式である「Protocol Buffers」はRESTよりも高速な通信を実現できるため、最近よくgRPCが使われているらしいです。

対応

1. 使用するプラグインについて

Mavenで依存ライブラリを含んだ実行可能Jarを作る場合は、

  • Maven-Assembly-plugin
  • Maven-Shade-Plugin

のいずれかを使うことになります。

たぶんどちらを使っても行けると思いますが、今回私は後者を使ったので、後者のプラグインでJarを作成する前提でいきます。

2. pom.xmlの設定

該当する設定部分を以下に記述します。

pom.xml
<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>
                <transformers>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>  <!-- 1 -->
                  <!-- <finalName>${project.name}</finalName> -->
                  <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">    <!-- 2 -->
                    <resource>META-INF/services</resource>
                    <file>io.grpc.LoadBalancerProvider</file>
                  </transformer>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
                    <resource>META-INF/services</resource>
                    <file>io.grpc.NameResolverProvider</file>
                  </transformer>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 3 -->
                    <manifestEntries>
                      <Main-Class>com.example.App</Main-Class>
                    </manifestEntries>
                  </transformer>
                </transformers>

                <filters>
                  <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                      <exclude>META-INF/*.SF</exclude>
                      <exclude>META-INF/*.DSA</exclude>
                      <exclude>META-INF/*.RSA</exclude>
                    </excludes>
                  </filter>
                </filters>
              </configuration>
            </execution>
          </executions>
        </plugin>
  </plugins>
</build>

具体的に問題になるのは「Configuration」の中と「filters」の中です。

3.Configurationについて

Transformerの設定が必要になります。

  • 1について
    このオプションをきじゅつすることで、META-INF/services/配下にあるService Loaderによりロードするファイルをマージするようになります。

  • 2について
    このオプションでは、指定したリソースを追加することができます。
    この記述をすれば動く、という解決策は、Githubのissueで報告されていました。(参考URL:https://github.com/googleapis/google-cloud-java/issues/4700)
    io.grpc.LoadBalancerProviderio.grpc.NameResolverProvider を追加する設定を自分で書かないといけないようです。

  • 3について
    メインクラスを指定しないと動かないので、このオプションで指定しましょう。

4. filtersについて

上記のpom.xmlに記述されている形式のファイルは不要で、この設定を書き忘れてもエラーが出るので、忘れないようにしましょう。
なんでexcludeしないといけないのかは忘れてしまったので、どなたか教えてください。

最後に

以上の設定を行えば、Mavenプロジェクト上でgRPCを使用するAPIは問題なく使用できると思います。
備忘録として利用してくださるとうれしいです。

1
0
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
1
0