spring boot を1.5系から2.0系にバージョンアップする

# はじめに
spring bootの2系がリリースされていたので、せっかくなのでバージョンアップした時のメモ

移行ガイドが公式から出ているのでこの手順に沿って行います。 [Spring Boot 2.0 Migration Guide](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide)
また、こちらの記事は大変参考になりました。[Spring Boot 1.5.10 → Spring Boot 2.0.0 にしたときの覚書](https://qiita.com/yukina-ge/items/1ca029ed69494bfd36d6)

# 対応内容
## プロパティチェックツールの導入  
[Before You Start](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#before-you-start)に書いてあるように`build.gradle`に以下のように追加します。  

```build.gradle
runtime("org.springframework.boot:spring-boot-properties-migrator")
```
これで`application.yml`の仕様変更分を警告してくれます。
## gradleプラグイン関連の修正

### 依存関係を解決するプラグインの追加
[Dependency Management](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#dependency-management)に書いてあるように依存関係を解決するプラグインを追加します。

```build.gradle
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'  // <-- add this to your build.gradle
```

### 構文が変更されたapplication.yml の修正
`spring.batch.initializer.enabled` が `spring.batch.initialize-schema`に変更されていたのでこちらに変更します。
初期化はしないので `never` を設定します。
[Initialize a Spring Batch Database](https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html#howto-initialize-a-database-using-spring-jdbc)

* 変更前

```application.yml
spring:
  batch:
    initializer:
       enabled: false
```

* 変更後

```application.yml
spring:
  batch:
    initialize-schema: never
```

### application.yml 上でのキャメルケース廃止
application.yml 上でキャメルケースで設定したものがエラーになっていました。
ケバブケースにせよ。とのことなのでケバブケースにします。

* 変更前

```application.yml
spring:
  datasource:
    hogeHoge:
      driverClassName: com.mysql.jdbc.Driver
```

* 変更後

```application.yml
spring:
  datasource:
    hoge-hoge:
      driver-class-name: com.mysql.jdbc.Driver
```

## build.gradleの構文変更
### jar生成時の設定変更
以前まではパッケージ生成に`bootRepackage`でjarファイルを生成していましたが、こちらが廃止されたようで、
`bootJar`と`bootWar`に置き換えられました。とありますが案件の設定の関係で`bootJar`は `enabled=false`にしました。

* 変更前

```build.gradle
    mainClassName = 'jp.co.hoge.fuga.App'
    bootRepackage {
        executable = true
    }

    jar {
      manifest {
          attributes 'GitHub-Branch-Name' : branchname
          attributes 'GitHub-Commit-Hash' : commithash
      }
    }
```

* 変更後

```build.gradle
    ext.mainClass = 'jp.co.hoge.fuga.App'
    bootJar {
        enabled = false
    }

    jar {
      enabled = true
      manifest {
          attributes 'GitHub-Branch-Name' : branchname
          attributes 'GitHub-Commit-Hash' : commithash
      }
    }
```

### gradlewのバージョンアップ
もともと使っていたgradlewは4.6でしたが、最新の4.7にあげておきます。

```build.gradle
task wrapper(type: Wrapper) {
    gradleVersion = "4.7"
}
```

## コネクションプール周りの変更
### HikariCP対応
以前まではtomcatのコネクションプールを使っていましたが、
HikariCPがデフォルトになったためそちらに変更します。

* 変更前

```DataSourceConfiguration.java
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.hoge")
public class DataSourceConfiguration {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private Boolean testOnBorrow;
    private String validationQuery;

    public DataSource dataSource() {
      DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
      ds.setDriverClassName(driverClassName);
      ds.setUrl(url);
      ds.setUsername(username);
      ds.setPassword(password);
      ds.setTestOnBorrow(testOnBorrow);
      ds.setValidationQuery(validationQuery);
      
      return ds;
    }
}
```

* 変更後

```DataSourceConfiguration.java
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.hoge")
public class DataSourceConfiguration {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private Integer maxPoolSize;
    private String validationQuery;

    public HikariDataSource dataSource() {
      HikariDataSource ds = new HikariDataSource();
      ds.setDriverClassName(driverClassName);
      ds.setJdbcUrl(url);
      ds.setUsername(username);
      ds.setPassword(password);
      ds.setConnectionInitSql(validationQuery);
      ds.setMaximumPoolSize(maxPoolSize);
      
      return ds;
    }
}
```
クエリタイムアウトなども設定するべきですが、長時間実行し続けるbatchからのsqlがあるので今回は設定しませんでした。


## 非推奨になったクラス、メソッドの修正
### SpringMvcのJavaConfig更新

spring5になった関係で`WebMvcConfigurerAdapter`が非推奨になりました。
`WebMvcConfigurer`を使えとあるのでそちらに変更します。
default method使うようになったからみたいですね。

* 変更前

```WebMvcConfig.java
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
       // 略
}
```

* 変更後

```WebMvcConfig.java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
       // 略
}
```

### Md5PasswordEncoderの廃止
もともと非推奨ですが、廃止になったため変更が必要なりました。

* 変更前

```PasswordEncoderConfig.java
@Bean
public PasswordEncoder md5PasswordEncoder() {
    return new Md5PasswordEncoder();
}
```

* 変更後

```PasswordEncoderConfig.java
@Bean
public PasswordEncoder md5PasswordEncoder() {
    return new MessageDigestPasswordEncoder("MD5");
}
```
MD5の利用自体をやめたいですが、長く続く案件だとなかなか難しいので非推奨ですが一旦これで回避します。


### DelegatingPasswordEncoderの使用
spring security5から追加されたので使用します。
パスワードのハッシュ化のアルゴリズムごとに適切な PasswordEncoderに処理を委譲してくれるようです。
デフォルトで設定してくれるクラスがあったので`PasswordEncoderFactories`を使用して生成させます。
デフォルトではbcryptを返してくれます。

```PasswordEncoderConfig.java
@Bean
public PasswordEncoder delegatingPasswordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
```

### org.hibernate.validator.constraints.NotBlankの変更

`org.hibernate.validator.constraints.NotBlank` が非推奨になりましたので変更します。
同一クラス名で`javax.validation.constraints.NotBlank` が実装されているのでimportの箇所だけ一括置換すればOKでした。


こんな感じの対応で問題なく動くようになりました。
おわり