古いバージョンの Glassfish を使うのはどうなの?というのはあるかもしれませんが、大人の事情でサーバーのバージョンを変えられない場合の対処方法です。
glassfish-web.xml の同梱
Spring Initilizr(Packaging は war) で作成したままのプロジェクトを Glassfish 4.x にデプロイしようとすると以下のエラーが発生して失敗します。
Error occurred during deployment: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'formContentFilter' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.filter.OrderedFormContentFilter]: Factory method 'formContentFilter' threw exception; nested exception is java.lang.VerifyError: Cannot inherit from final class. Please see server.log for more details
これは、
などにある通り、Glassfish にデフォルトで付属している Jackson のバージョンが古くデプロイするパッケージに含まれるものより、先に読み込まれてしまうのが原因のようです。(前者のように Glassfish 側のライブラリを置き換えてしまうという手もあるようですが、以下はそれができない場合の説明です。)
そのため、デプロイするパッケージに 以下のような Glassfish 用の設定ファイル glassfish-web.xml を含める必要があります。
<!DOCTYPE glassfish-web-app PUBLIC
"-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN"
"http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
<class-loader delegate="false" />
</glassfish-web-app>
ソースでの配置場所は src\main\webapp\WEB-INF です。
なお、Eclipse 等で http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd が有効な URL ではないため、エラー扱いになってしまいますが、特に問題ありません。(気になるようであれば、glassfish.org は消滅したので DTD が読み込めなくなったのですケド - A Memorandum にある方法を試してみてください。)
参考文献
- java - Error while deploying spring boot app on glassfish 4.1 - Stack Overflow
- Class Loader Delegation (Oracle GlassFish Server 3.0.1 Application Development Guide)
- Interstage Application Server 運用ガイド 2.2.1 アプリケーションの定義
pom.xml の修正
前項の修正をしただけでは、デプロイ時に以下のエラーが発生します。
Error occurred during deployment: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.cfg.beanvalidation.IntegrationException: Error activating Bean Validation integration. Please see server.log for more details.
これは、validation-api 周りのバージョンが合わないためのようです。
これを回避するために pom.xml を修正します。
まず、spring-boot-starter-validation と spring-boot-starter-web の依存パッケージから、hibernate-validator を除外します。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
そして、hibernate-validator と validation-api の古いバージョンを依存関係に加えます。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.3.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
これらの修正を行い、 mvn package
を実行すれば、Glassfish 4.x にデプロイできるようになりました。