Posted at

Google App Engine で Spring Boot を動かす

More than 3 years have passed since last update.

注意点は 5 つです。


spring-boot-legacy を使う

AppEngine は Servlet 2.5 なので、Servlet 3.0 を前提とした Spring Boot は動きません。

ですので、2.5 に対応している spring-boot-legacy を使います。

compile 'org.springframework.boot:spring-boot-legacy'

あとは通常通り webactuator に依存します。

compile 'org.springframework.boot:spring-boot-starter-web'

compile 'org.springframework.boot:spring-boot-starter-actuator'


web.xml で SpringBootContextLoaderListener を置く

Spring 公式の Servlet 2.5 ガイド 通りです。ただし、後述の 2 点は変更する必要があります。

(contextConfigLocation は自身の Application クラスと置き換えてください。)

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.kaiinui.appenginetest.Application</param-value>
</context-param>
<listener>
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>


metricFilter では filter しないようにする

Spring の公式ガイド では DelegatingFilterProxy で filter するようにしていますが、次の項と同じ理由で動かなくなるので外します。

先ほど記載した web.xml 通りになっていれば問題有りません。


DispatcherServletpublishEventsfalse にしておく

Spring 4.1 以降では DispatcherServletpublishEvents によって HttpServletResponsegetStatus が呼ばれますが、この API は 2.5 では実装されていないのでエラーが起こります。

以下の init-param を DispatcherServlet に追加して無効にします。

<init-param>

<param-name>publishEvents</param-name>
<param-value>false</param-value>
</init-param>


以上、ちゃんと動く web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.kaiinui.appenginetest.Application</param-value>
</context-param>
<listener>
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
<init-param>
<param-name>publishEvents</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>


multipartResolvergmultipart を使う

標準の CommonsMultipartResolver が一時保存先としてファイルシステムを使ってしまうので、置き換えます。

メモリに全て読んでくれれば何でも良いのですが、イイ感じに実装してくれてるっぽい gmultipart を使います。

repositories {

maven {
url 'http://gmultipart.googlecode.com/svn/repo/m2'
}
}

dependencies {
compile 'gmultipart:gmultipart:0.4'
}

// @Configuration なクラスで

@Bean(name = "multipartResolver")
public GMultipartResolver multipartResolver() {
GMultipartResolver resolver = new GMultipartResolver();
resolver.setMaxUploadSize(100000);

return resolver;
}


まとめ

Spring MVC (+ Spring Boot) はいろいろ充実してるし、AppEngine にも載りやすいのでイイ感じかなーと。

Java の Web フレームワークでは Play Framework の人気が高いですが、載せるのに魔改造が必要なのであまりオススメできません…


References