27
23

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 5 years have passed since last update.

Spring Boot 1.5からSpring Boot 2.0にマイグレーションしたときの変更点

Last updated at Posted at 2018-06-13

はじめに

Spring Boot 1.5のアプリケーション(約7KL、SPAのサーバ部分)をSpring Boot 2.0にマイグレーションしてみたときの修正ポイントを書いておきます。
クラス・パッケージが変わったり、Deprecatedになったりと、結構な量の修正が必要でした。

余談

最初はSpring Bootを2.0にするつもりはなく、Elasticsearch 6にアクセスしたかっただけなのですが、Elasticsearch 6にアクセスするためにはspring-boot-starter-data-elasticsearchを2.0台に上げなければならず、仕方なしにSpring Boot自体を2.0に上げることにしました。

Spring Bootの修正箇所

Maven

今回マイグレーションしたアプリケーションは、次のようなライブラリに依存しています。

pom.xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.ldap</groupId>
  <artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.ldap</groupId>
  <artifactId>spring-ldap-core-tiger</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-ldap</artifactId>
</dependency>

もともとはSpring IO platformを使用していたのですが、EOLが2019年9月となっており、「spring-boot-starter-parentを使用するか、spring-boot-dependencies bomをインポートするのを推奨」と書かれていました。
推奨に従い、Spring IO platformからspring-boot-starter-parentに変えることに。

SpringBoot1.5
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.spring.platform</groupId>
      <artifactId>platform-bom</artifactId>
      <version>Brussels-SR3</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
SpringBoot2.0
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.2.RELEASE</version>
</parent>

application.ymlのプロパティ変更

context-pathの階層が変わりました。元のままでも動作するようですが、変えておいた方が無難です。

SpringBoot1.5
server:
  context-path: /sample
SpringBoot2.0
server:
  servlet:
    context-path: /sample

Adapterクラスの廃止

Spring Boot 2.0はJava 8対応となったため、インタフェースを空実装したAdapterクラスは廃止され、代わりにインタフェース自体にメソッドのデフォルト実装が追加されています。
そのため、Adapterのextendsではなく、直接インタフェースをimplementsするように変更となります。

SpringBoot1.5
public class WebMvcConfig extends WebMvcConfigurerAdapter {
SpringBoot2.0
public class WebMvcConfig implements WebMvcConfigurer {

Auto-configurationのパッケージ変更

プロファイルによってセキュリティ設定を切り替えるために、セキュリティのAuto-configurationであるSecurityAutoConfigurationを除外していましたが、このSecurityAutoConfigurationのパッケージが変更となっています。

SpringBoot1.5
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;

@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
SpringBoot2.0
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;

@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)

securityパッケージ配下のさらにservletパッケージの中に移動したようです。

PasswordEncoder関連クラスの構成変更

内部キャッシュ用にShaPasswordEncoderを使っていましたが、クラス自体がなくなりました。
PasswordEncoder関連のクラス構成が見直されています。それに合わせて、脆弱なアルゴリズムを使ったShaPasswordEncoderクラスやMd5PasswordEncoderクラスは姿を消しています(アルゴリズム自体は残っているようですが、非推奨とのこと)。

Spring Boot 2.0からは、PasswordEncoderFactoriesを使ってPasswordEncoderを生成することになります。

SpringBoot1.5
MessageDigestPasswordEncoder encoder = new ShaPasswordEncoder(256);
return encoder.encodePassword(password);
SpringBoot2.0
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
return encoder.encode(password);

メソッドも、encodePassword()からencode()に変わっています。

Repositoryのメソッド名称/型変更

今回の修正で最も大変だったのがコレです(数が多かったので・・・)。
CrudRepositoryのfindOne()メソッドがfindById()に名称変更となり、さらに戻り値がEntity型ではなくOptional型になりました。

SpringBoot1.5
Employee employee = employeeRepository.findOne(employeeId);
SpringBoot2.0
Optional<Employee> employee = employeeRepository.findById(employeeId);

Repositoryのページングの生成方法変更

PageRequestのnewが非推奨になりました。代わりにof()を使います。

SpringBoot1.5
employeeRepository.findAll(specifications,
        new PageRequest(page, size, new Sort(
                Sort.Direction.fromString(sortDirection), sortColumn)));
SpringBoot2.0
employeeRepository.findAll(specifications,
        PageRequest.of(page, size, new Sort(
                Sort.Direction.fromString(sortDirection), sortColumn)));

PageRequestをof()に変えるなら、Sortもof()に変えた方がスタイルが統一されてよいですね。

SpringBoot2.0
employeeRepository.findAll(specifications,
        PageRequest.of(page, size, Sort.of(
                Sort.Direction.fromString(sortDirection), sortColumn)));

Specificationsの非推奨化

Java 8になり、Specificationインタフェースにデフォルト実装が追加されたため、Specificationインタフェースを実装したSpecificationsクラスの直接利用は非推奨となりました。
(Specificationインタフェースのデフォルト実装は、Specificationsクラスを使っていますが。)

SpringBoot1.5
employeeRepository.findAll(
        Specifications.where((root, query, cb) -> cb.equal(property, value)));
SpringBoot2.0
employeeRepository.findAll(
        Specification.where((root, query, cb) -> cb.equal(property, value)));

Hibernateの変更箇所

Spring Bootを2.0にしたことに伴いHibernateのバージョンが5.2.17に上がったことによる変更もありました。

Hibernateのパッケージ変更

HibernateのNativeQueryを使って、明示的にNULLを指定したいときにExplicitParameterInfoクラスを使っていましたが、このクラスのパッケージが org.hibernate.jpa.criteria.compile.ExplicitParameterInfo から org.hibernate.query.criteria.internal.compile.ExplicitParameterInfo に変わりました。

2018/07/12追記・更新
PostgreSQL 10の場合は少なくとも、NULLを指定する際にExplicitParameterInfoが指定できなくなりました。
ExplicitParameterInfoを使うと「 org.postgresql.util.PSQLException: ERROR: 演算子が存在しません: text = bytea 」のようなエラーが発生します。
そのため、NULLの型を指定したい場合は、ExplicitParameterInfoの代わりにTypedParameterValueを使います。

SpringBoot1.5
import org.hibernate.jpa.criteria.compile.ExplicitParameterInfo;

// 中略

Query query = entityManager.createNativeQuery(query);
query.setParameter(new ExplicitParameterInfo<>("employeeName", null, String.class), null);
List<Employee> employeeList = query.getResultList();
SpringBoot2.0
import org.hibernate.jpa.TypedParameterValue;
import org.hibernate.type.StringType;

// 中略

Query query = entityManager.createNativeQuery(query);
query.setParameter("employeeName", new TypedParameterValue(new StringType(), null));
List<Employee> employeeList = query.getResultList();

UserTypeのメソッド引数変更

今回のアプリケーションには、PostgreSQLのJSONBカラムとJavaのStringを相互変換する、UserTypeの実装クラスがありました。
Spring Boot 2.0(Hibernate 5.2.17)では、nullSafeGet/nullSafeSetの引数のSessionImplementorクラスがなくなっており、代わりにSharedSessionContractImplementorになりました。

SpringBoot1.5
public class PostgresJsonType implements UserType {
    @Override
    public Object nullSafeGet(ResultSet rs, String[] names,
            SessionImplementor session, Object owner)
            throws HibernateException, SQLException {
        // ・・・
    }

    public void nullSafeSet(PreparedStatement st, Object value,
            int index, SessionImplementor session)
            throws HibernateException, SQLException {
        // ・・・
    }

    // ・・・
}
SpringBoot2.0
public class PostgresJsonType implements UserType {
    @Override
    public Object nullSafeGet(ResultSet rs, String[] names,
            SharedSessionContractImplementor session, Object owner)
            throws HibernateException, SQLException {
        // ・・・
    }

    public void nullSafeSet(PreparedStatement st, Object value,
            int index, SharedSessionContractImplementor session)
            throws HibernateException, SQLException {
        // ・・・
    }

    // ・・・
}

その他

これは元から実装が悪かったのですが、application.ymlに

app:
  function:
    message-type:
      AAA: xxx
      BBB: yyy

という定義があり、ConfigurationPropertiesで値をバインドする際に

@ConfigurationProperties(prefix = "app.function.messageType")

のように、チェインケースをキャメルケースで参照してバインドが可能でした。

Spring Boot 2.0では、チェックが厳しくなり、上の状態だとエラーになってしまいます。(本来はエラーになるのが当然ですが。。)

ちゃんと定義に合わせてチェインケースで書きましょう。。

@ConfigurationProperties(prefix = "app.function.message-type")

まとめ

今回のマイグレーションで遭遇しなかった変更点もたくさんあります。
公式サイトに Spring Boot 2.0 Migration Guide がありますので、こちらも参考にしてみてください。

27
23
2

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
27
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?