---
title: Tanzu Application Platformに古いバージョンのSpring Bootを使ったアプリをデプロイする際のWorkaround
tags: ["Kubernetes", "Tanzu", "TAP", "Tanzu Build Service", "kpack", "Maven"]
categories: ["Dev", "CaaS", "Kubernetes", "TAP"]
date: 2022-12-22T04:11:48Z
updated: 2022-12-22T04:16:26Z
---

TAPに古いバージョンのSpring Bootを使ったアプリをデプロイする際にいくつか問題が起きるので、回避策をメモします。


今回は https://github.com/making/demo-download-view をデプロイしてみます。


このアプリはSpring Boot **1.3** を使用して、7年前に作成されました。

このアプリをそのままTAPにデプロイしてみましょう。


```
tanzu apps workload apply demo-download-view \
  --app demo-download-view \
  --git-repo https://github.com/making/demo-download-view \
  --git-branch master \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --build-env BP_JVM_VERSION=8 \
  -n demo \
  -y
```

発生するエラーを1つ1つ対処していきます。

**目次**
<!-- toc -->


### Mavenが古いことによるビルドエラー

Build Serviceによるイメージ作成時に、まず次のエラーが発生しました。


```
Compiled Application: Contributing to layer
  Executing mvnw --settings=/platform/bindings/settings-xml/settings.xml --batch-mode -Dmaven.test.skip=true --no-transfer-progress package
    Downloading https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
    ........................................................................................................................................................................................................................................................................................................................................................................................................................
    Unzipping /home/cnb/.m2/wrapper/dists/apache-maven-3.3.3-bin/3opbjp6rgl6qp7k2a6tljcpvgp/apache-maven-3.3.3-bin.zip to /home/cnb/.m2/wrapper/dists/apache-maven-3.3.3-bin/3opbjp6rgl6qp7k2a6tljcpvgp
    Set executable permissions for: /home/cnb/.m2/wrapper/dists/apache-maven-3.3.3-bin/3opbjp6rgl6qp7k2a6tljcpvgp/apache-maven-3.3.3/bin/mvn
    Unable to parse command line options: Unrecognized option: --no-transfer-progress
```

Maven Buildpackはmavenビルドを実行時に `--no-transfer-progress` オプションをつけてログの出力を抑制するのですが、
このオプションはMaven 3.6.1で導入されました。今回のアプリに含まれるMaven WrapperはMavenを3.3.3を使用しており、このオプションが存在しないためにエラーが発生しました。

ソースコードのディレクトリで次のコマンドを実行すると、Maven Wrapperが使用するMavenのバージョンを最新にすることができます。
```
mvn wrapper:wrapper
```

次のように特定のバージョンを指定することもできます

```
mvn wrapper:wrapper -Dmaven=3.8.6
```


今回は次のコミットでMaven Wrapperを更新しました。

https://github.com/making/demo-download-view/commit/25eac90254d3c728ec1c4b90740aff51495e434c

もしくは次のビルド環境変数を設定し、 `--no-transfer-progress` オプションをつけないようにしても良いでしょう。

```
--build-env BP_MAVEN_BUILD_ARGUMENTS='-Dmaven.test.skip=true package' \
```

### Spring-Boot-LibがMANIFEST.MFに存在しないことによるビルドエラー

Git上のソースコードを更新すると、再度イメージのビルドが実行されます。今度は次のエラーが発生しました。

```
Paketo Buildpack for Spring Boot 5.19.0
  https://github.com/paketo-buildpacks/spring-boot
  Build Configuration:
    $BP_SPRING_CLOUD_BINDINGS_DISABLED   false  whether to contribute Spring Boot cloud bindings support
  Launch Configuration:
    $BPL_SPRING_CLOUD_BINDINGS_DISABLED  false  whether to auto-configure Spring Boot environment properties from bindings
    $BPL_SPRING_CLOUD_BINDINGS_ENABLED   true   Deprecated - whether to auto-configure Spring Boot environment properties from bindings

Paketo Buildpack for Spring Boot 5.19.0
  manifest does not container Spring-Boot-Lib
ERROR: failed to build: exit status 1
```

jarファイルの中のMANIFEST.MFに`Spring-Boot-Lib`がないというエラーです。

次のBuildpackのソースコードを読むと、BuildpackはBOMにdependenciesを追加するためにこの項目に設定されたディレクトリを見ているようです。

* https://github.com/paketo-buildpacks/spring-boot/blob/v5.19.0/boot/build.go#L89


この`Spring-Boot-Lib`はMavenの場合はSpring Boot 1.4.0、Gradleの場合は2.0.9から含まれたようです。

* https://github.com/spring-projects/spring-boot/issues/5183
* https://github.com/spring-projects/spring-boot/issues/16068


サポートされたバージョンでは次のような値がMANIFEST.MFに設定されます。

* https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-manifest.MF#L10 (jarの場合)
* https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-war-manifest.MF#L10 (warの場合)


サポートされていないバージョンでは何らかの方法で、MANIFEST.MFにこの値を設定する必要があります。
MANIFST.MFに対してはMavenではmaven-jar-pluginを使って次のように任意の項目を追加できます。

```xml
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifestEntries>
							<Spring-Boot-Lib>lib/</Spring-Boot-Lib>
						</manifestEntries>
					</archive>
				</configuration>
			</plugin>
```

warファイルを作成している場合はmaven-jar-pluginをmaven-war-pluginに変えてください。
設定すべき内容はSpring Bootのバージョンによって異なります。jarのレイアウトが変わるからです。


jarやwarのレイアウトを確認したい場合は`zipinfo`コマンドを使ってください。

```
$ zipinfo target/demo-0.0.1-SNAPSHOT.jar 
Archive:  target/demo-0.0.1-SNAPSHOT.jar
Zip file size: 20306425 bytes, number of entries: 122
-rw----     2.0 fat        0 bX defN 22-Dec-22 11:25 META-INF/
-rw----     2.0 fat      477 bl defN 22-Dec-22 11:25 META-INF/MANIFEST.MF
drwxr-xr-x  1.0 unx        0 b- stor 22-Dec-22 11:25 templates/
drwxr-xr-x  1.0 unx        0 b- stor 22-Dec-22 11:25 com/
drwxr-xr-x  1.0 unx        0 b- stor 22-Dec-22 11:25 com/example/
-rw-r--r--  2.0 unx      419 bl defN 22-Dec-22 11:25 templates/index.html
-rw-r--r--  2.0 unx       15 bl defN 22-Dec-22 11:25 hello.txt
-rw-r--r--  2.0 unx      730 bl defN 22-Dec-22 11:25 com/example/DemoDownloadViewApplication.class
-rw-r--r--  2.0 unx      701 bl defN 22-Dec-22 11:25 com/example/HelloForm.class
-rw-r--r--  2.0 unx     1586 bl defN 22-Dec-22 11:25 com/example/HelloController.class
-rw-r--r--  2.0 unx     2112 bl defN 22-Dec-22 11:25 com/example/DownloadView.class
-rw-r--r--  2.0 unx        0 bl defN 22-Dec-22 11:25 application.properties
drwxr-xr-x  1.0 unx        0 b- stor 22-Dec-22 11:25 META-INF/maven/
drwxr-xr-x  1.0 unx        0 b- stor 22-Dec-22 11:25 META-INF/maven/com.example/
drwxr-xr-x  1.0 unx        0 b- stor 22-Dec-22 11:25 META-INF/maven/com.example/demo/
-rw-r--r--  2.0 unx     1913 bl defN 22-Dec-22 11:24 META-INF/maven/com.example/demo/pom.xml
-rw-r--r--  2.0 unx      109 bl defN 22-Dec-22 11:25 META-INF/maven/com.example/demo/pom.properties
-rw----     2.0 fat        0 bl defN 22-Dec-22 11:25 lib/
-rw----     1.0 fat   193581 b- stor 15-Nov-16 02:45 lib/spring-boot-devtools-1.3.0.RELEASE.jar
-rw----     1.0 fat   533592 b- stor 15-Nov-16 02:34 lib/spring-boot-1.3.0.RELEASE.jar
...
-rw----     1.0 fat  1077165 b- stor 15-Nov-15 08:03 lib/spring-core-4.2.3.RELEASE.jar
-rw----     2.0 fat        0 bl defN 22-Dec-22 11:25 org/
-rw----     2.0 fat        0 bl defN 22-Dec-22 11:25 org/springframework/
-rw----     2.0 fat        0 bl defN 22-Dec-22 11:25 org/springframework/boot/
-rw----     2.0 fat        0 bl defN 22-Dec-22 11:25 org/springframework/boot/loader/
-rw----     2.0 fat     1257 bl defN 15-Nov-16 02:31 org/springframework/boot/loader/LaunchedURLClassLoader$Java7LockProvider.class
...
-rw----     2.0 fat      884 bl defN 15-Nov-16 02:31 org/springframework/boot/loader/archive/ExplodedArchive$FileNotFoundURLConnection.class
-rw----     2.0 fat      192 bl defN 15-Nov-16 02:31 org/springframework/boot/loader/JavaAgentDetector.class
122 files, 20382587 bytes uncompressed, 20285023 bytes compressed:  0.5%
```

今回は次のコミットでpom.xmlを更新しました。

https://github.com/making/demo-download-view/commit/e13e75a10560721e9f2c86563494bafb94dae8d1


### Spring-Boot-ClassesがMANIFEST.MFに存在しないことによるビルドエラー

Git上のソースコードを更新すると、再度イメージのビルドが実行されます。今度は次のエラーが発生しました。

```
Paketo Buildpack for Spring Boot 5.19.0
  https://github.com/paketo-buildpacks/spring-boot
  Build Configuration:
    $BP_SPRING_CLOUD_BINDINGS_DISABLED   false  whether to contribute Spring Boot cloud bindings support
  Launch Configuration:
    $BPL_SPRING_CLOUD_BINDINGS_DISABLED  false  whether to auto-configure Spring Boot environment properties from bindings
    $BPL_SPRING_CLOUD_BINDINGS_ENABLED   true   Deprecated - whether to auto-configure Spring Boot environment properties from bindings

Paketo Buildpack for Spring Boot 5.19.0
  manifest does not contain Spring-Boot-Classes
ERROR: failed to build: exit status 1
```

先ほどと同様にjarファイルの中のMANIFEST.MFに`Spring-Boot-Classes`がないというエラーです。


次のBuildpackのソースコードを読むと、アプリケーションのタイプを検出するためにこの項目に設定されたディレクトリを見ているようです。

* https://github.com/paketo-buildpacks/spring-boot/blob/v5.19.0/boot/build.go#L152


サポートされたバージョンでは次のような値がMANIFEST.MFに設定されます。

* https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-manifest.MF#L9 (jarの場合)
* https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-war-manifest.MF#L9 (warの場合)


今回もmaven-jar-plugin or maven-war-pluginでこの項目を設定します。


```xml
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifestEntries>
							<Spring-Boot-Lib>lib/</Spring-Boot-Lib>
							<Spring-Boot-Classes>.</Spring-Boot-Classes>							
						</manifestEntries>
					</archive>
				</configuration>
			</plugin>
```

今回は次のコミットでpom.xmlを更新しました。

https://github.com/making/demo-download-view/commit/ae127b2bbad58f663573489cbe95f24ff165129e


### Spring Cloud Bindingsに関するランタイムエラー


Git上のソースコードを更新すると、再度イメージのビルドが実行されます。今度はイメージのビルドが成功し、アプリの起動が始まりました。
しかし、起動時に次のようなエラーが発生し、アプリは起動しません。

```
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
	at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.context.ApplicationListener :  org.springframework.cloud.bindings.boot.BindingSpecificEnvironmentPostProcessor
	at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:396)
	at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:373)
	at org.springframework.boot.SpringApplication.initialize(SpringApplication.java:253)
	at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:227)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1112)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1101)
	at com.example.DemoDownloadViewApplication.main(DemoDownloadViewApplication.java:10)
	... 6 more
Caused by: java.lang.ClassNotFoundException:  org.springframework.cloud.bindings.boot.BindingSpecificEnvironmentPostProcessor
	at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at org.springframework.boot.loader.LaunchedURLClassLoader.doLoadClass(LaunchedURLClassLoader.java:166)
	at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:130)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
	at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:389)
	... 12 more
```

Spring Cloud Bindingsに関連するエラーです。このライブラリはイメージビルド時に自動で追加されるライブラリですが、Spring Bootのバージョンのせいか、ClassNotFoundExceptionが発生してしまいます。

Service Binidngを使わない場合は、Spring Cloud Bindingsはなくても良いので、`--build-env BP_SPRING_CLOUD_BINDINGS_DISABLED=true`オプションをつけて、ビルド時にSpring Cloud Bindingsを無効にします。

最終的に実行したコマンドは次です。

```
tanzu apps workload apply demo-download-view \
  --app demo-download-view \
  --git-repo https://github.com/making/demo-download-view \
  --git-branch tap \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --build-env BP_JVM_VERSION=8 \
  --build-env BP_SPRING_CLOUD_BINDINGS_DISABLED=true \
  -n demo \
  -y
```



```
$ tanzu apps workload get -n demo demo-download-view 
📡 Overview
   name:   demo-download-view
   type:   web

💾 Source
   type:     git
   url:      https://github.com/making/demo-download-view
   branch:   tap

📦 Supply Chain
   name:   source-to-url

   RESOURCE           READY   HEALTHY   TIME   OUTPUT
   source-provider    True    True      42m    GitRepository/demo-download-view
   image-provider     True    True      101s   Image/demo-download-view
   config-provider    True    True      12m    PodIntent/demo-download-view
   app-config         True    True      12m    ConfigMap/demo-download-view
   service-bindings   True    True      12m    ConfigMap/demo-download-view-with-claims
   api-descriptors    True    True      12m    ConfigMap/demo-download-view-with-api-descriptors
   config-writer      True    True      81s    Runnable/demo-download-view-config-writer

🚚 Delivery
   name:   delivery-basic

   RESOURCE          READY   HEALTHY   TIME   OUTPUT
   source-provider   True    True      11m    ImageRepository/demo-download-view-delivery
   deployer          True    True      69s    App/demo-download-view

💬 Messages
   No messages found.

🛶 Pods
   NAME                                                   READY   STATUS        RESTARTS        AGE
   demo-download-view-00001-deployment-76b5cc876c-t9clq   0/2     Terminating   7 (5m19s ago)   11m
   demo-download-view-00002-deployment-76dbf5f776-z7qvj   2/2     Running       0               71s
   demo-download-view-build-1-build-pod                   0/1     Init:Error    0               47m
   demo-download-view-build-2-build-pod                   0/1     Init:Error    0               42m
   demo-download-view-build-3-build-pod                   0/1     Init:Error    0               26m
   demo-download-view-build-4-build-pod                   0/1     Init:Error    0               16m
   demo-download-view-build-5-build-pod                   0/1     Completed     0               14m
   demo-download-view-build-6-build-pod                   0/1     Completed     0               2m29s
   demo-download-view-config-writer-d9l79-pod             0/1     Completed     0               92s
   demo-download-view-config-writer-f9kvp-pod             0/1     Completed     0               12m

🚢 Knative Services
   NAME                 READY   URL
   demo-download-view   Ready   https://demo-download-view-demo.127-0-0-1.sslip.io

To see logs: "tanzu apps workload tail demo-download-view --namespace demo"
```

これでアプリが起動し、アプリにアクセできました。


```
$ curl -k "https://demo-download-view-demo.127-0-0-1.sslip.io/download?fileName=tap"    
Hello Download!
```

### Tanzu Build Service単体の場合

Tanzu Build Serviceのみを使用している場合は、次のコマンドが等価です。

```
kp image save demo-download-view \
  --git https://github.com/making/demo-download-view \
  --git-revision tap \
  --tag ghcr.io/making/demo-download-view \
  --env BP_JVM_VERSION=8 \
  --env BP_SPRING_CLOUD_BINDINGS_DISABLED=true \
  -n demo
```

---

古いSpring Bootのバージョンに起因するbuildpackの問題を回避しました。

この回避策を使うのではなく、できればSpring Bootをバージョンアップしてください。
