Java 10でSpring Boot 2.0 アプリケーションを開発するときの初歩的な注意点

# 概要

[SPRING Initializr] (https://start.spring.io/)で生成したSpring Boot 2.0のアプリケーションのひな型をJava 10でコンパイル、実行するために必要な環境設定などのメモです。
ひな型をベースにしているのでこの記事で取り上げているのは初歩的なものです。プロダクトの複雑なアプリケーションの場合はもっと多くの注意点が出てくるかもしれません。

**環境**

* Windows 10 Professional
* Oracle JDK 10.0.1
* Spring Boot 2.0.2
* Maven 3.5.3

java

```text
> java -version
java version "10.0.1" 2018-04-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)
```

maven

```text
> mvn.cmd -version
Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T04:49:05+09:00)
Maven home: D:\dev\apache-maven-3.5.3\bin\..
Java version: 10.0.1, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk-10.0.1
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
```

**参考**

* [Spring Boot with Java 9 and above] (https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-with-Java-9-and-above)
* [dsyer/spring-boot-java-9] (https://github.com/dsyer/spring-boot-java-9)
* [Java Development Kit 10 Release Notes] (http://www.oracle.com/technetwork/java/javase/10u-relnotes-4108739.html)
* [ヌーラボのアカウント基盤を Java 9 にマイグレーションして起きた問題と解決法 | ヌーラボ] (https://nulab-inc.com/ja/blog/nulab/java9-migration/)

# Spring BootのJava 10のサポートについて

まず、Spring Boot 2.0で開発したアプリケーションはJava 10で動作するのかという点ですが、[Spring Boot with Java 9 and above] (https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-with-Java-9-and-above)のRequirementsに記載がある通り、Spring Boot 2.0.1でJava 10での動作はサポートされています。

> **Requirements**
> 
> Spring Boot 2 is the first version to support Java 9 (Java 8 is also supported). If you are using 1.5 and wish to use Java 9 you should upgrade to 2.0 as we have no plans to support Java 9 on Spring Boot 1.5.x.
> 
> Java 10 is supported as of Spring Boot 2.0.1.RELEASE. We intend to support Java 11 as of Spring Boot 2.1.x


# Java 10を使用するときの注意点について

Java 10 (および9)では、Java 1.8で必要がなかったいくつかの注意点があります。

## Illegal reflective access

アプリケーションを起動すると、起動時のログに下記のワーニングが出力されます。
Java 9から発生していたことですが、Java 10でも同様に発生します。

```text
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
```

Spring Frameworkはリフレクションを使用しているので、このワーニングは想定内（不正ではない）のようです。（また、将来的に改善されるようです。[MethodHandles.Lookup.defineClass for CGLIB class definition purposes] (https://jira.spring.io/browse/SPR-15859)）
たんにワーニングの出力を抑制したい場合は、JVM Optionに下記のオプションを追加します。

```text
--illegal-access=deny
```

jar実行時

```text
> java --illegal-access=deny -jar demo.jar
```

## JAXB

プロジェクトでJPA (Hibernate)を利用する場合は依存関係にJAXBを追加する必要があります。

> Hibernate typically requires JAXB that’s no longer provided by default. 

```xml
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>
```

## Lombokのバージョン指定

Spring Boot 2.0.2の依存関係管理ではlombok 1.16.20がデフォルトで利用されますが、Java 10を利用する場合はlombok 1.16.22 (2018年6月時点)を指定する必要があります。

```xml
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    <version>1.16.22</version>
</dependency>
```

2018年6月5日にlombok 1.18.0がリリースされました（[changelog] (https://projectlombok.org/changelog)）が、こちらのPR（[Update Lombok to 1.18.0] (https://github.com/spring-projects/spring-boot/pull/13413)）によれば、Spring Bootが正式に採用するのはSpring Boot 2.1からのようです。

ちなみに、Spring Bootの依存管理からlombokを除外するかどうかを検討するIssues "[Consider removing lombok from dependency management] (https://github.com/spring-projects/spring-boot/issues/12576)"があります。若しかすると将来のバージョンではlombokを利用する場合はバージョンを明示しなければならないかもしれません。

## maven-surefire-pluginのダウングレードは不要

Java 9ではmaven-surefire-pluginをバージョン2.20.0へダウングレードする必要がありましたが、バージョン2.21.0で問題が解決されたのでダウングレードする必要はなくなりました。
また、Spring Boot 2.0.2ではバージョン2.21.0がデフォルトになったのでバージョンを明示する必要もありません。

[Outdated wiki reference on Spring Boot with Java 9] (https://github.com/spring-projects/spring-boot/issues/12936)

## Java 9, 10に関係するOpen中のIssues

2018年6月時点でのステータスです。

* [Support Devtools with Java 9+ modulepath] (https://github.com/spring-projects/spring-boot/issues/12832) (Backlog)
* [Support Java 9 Multi-Release JAR files] (https://github.com/spring-projects/spring-boot/issues/12523)
* [Upgrade to a Cassandra version that works with Java 9] (https://github.com/spring-projects/spring-boot/issues/10453)
    * Cassandraの対応待ちです。
* [SpringBootTest does not work with Java 10/modules] (https://github.com/spring-projects/spring-boot/issues/13581) 
 (external-project)
    * Spring Bootの課題としてはClosedになっていますが、引き続きSpring Frameworkの課題として扱われています。

# Java 11のサポートについて

## Spring Framework

Spring Frameworkではバージョン 5.1 GAでサポートされることになっています。

[[SPR-16391] Compatibility with JDK 11] (https://jira.spring.io/browse/SPR-16391)

2018年9月21日に、Spring Framework 5.1 GAがリリースされました。
アナウンスにあるようにこのバージョンから正式にJava 11をサポートしています。

[Spring Framework 5.1 goes GA] (https://spring.io/blog/2018/09/21/spring-framework-5-1-goes-ga)

> Spring Framework 5.1 requires JDK 8 or higher and specifically supports JDK 11 as the next long-term support release. It comes with initial refinements for GraalVM compatibility and deeply integrates with the recently released Reactor Californium and Hibernate ORM 5.3.

## Spring Boot

Spring Bootはバージョン 2.1.0 M4からSpring Framework 5.1 GAをサポートするようになっています。


# 補足

## 依存関係管理のサポート状況

多数のライブラリ、フレームワーク名を記載することになり、Google検索などのノイズになりかねないので、別の限定共有公開ページへ切り出しました。

[Spring Bootの依存関係管理のJava 10サポート状況] (https://qiita.com/rubytomato@github/private/be9ca17d2a572ec5dbe4)

## OpenJDK 9, 10のバグ

* [Java9、10でStringの+=に副作用があるバグ - きしだのはてな] (http://d.hatena.ne.jp/nowokay/20180611#1528730611)

## Java 11で削除されるモジュール

[JEP 320: Remove the Java EE and CORBA Modules] (http://openjdk.java.net/jeps/320)で決められた以下のモジュールがJava 11で削除されることになっています。

* java.xml.ws
* java.xml.bind
* java.activation
* java.xml.ws.annotation
* java.corba
* java.transaction

アプリケーションが引き続きこれらのモジュールを必要とする場合は、下記のように別途依存関係を追加することで利用することができます（CORBA除く）。

[JAX WS RI Standalone Zipped Bundle] (https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-ri)

```
<!-- https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-ri -->
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-ri</artifactId>
    <version>2.3.0.1</version>
    <type>pom</type>
</dependency>
```

[JAXB API] (https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api)

```
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>
```

[JavaBeans Activation Framework] (https://mvnrepository.com/artifact/com.sun.activation/javax.activation)

```
<!-- https://mvnrepository.com/artifact/com.sun.activation/javax.activation -->
<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>javax.activation</artifactId>
    <version>1.2.0</version>
</dependency>
```

[Javax Annotation API] (https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api)

```
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>
```

[Javax Transaction API] (https://mvnrepository.com/artifact/javax.transaction/javax.transaction-api)

```
<!-- https://mvnrepository.com/artifact/javax.transaction/javax.transaction-api -->
<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.3</version>
</dependency>
```

CORBA

> There will not be a standalone version of CORBA unless third parties take over maintenance of the CORBA APIs, ORB implementation, CosNaming provider, etc.

現時点(2018年6月)では、CORBAのスタンドアローン版はないようです。