概要
- Google App Engine Java 11 スタンダード環境 + Spring Boot の構成でシンプルな Hello World 表示 Web アプリケーションを作る
- Google App Engine Java 11 スタンダード環境の正式版リリースは2019年10月30日にアナウンスされている
- Java 11 リリースは2018年9月25日にアナウンスされている
環境
- Google App Engine Java 11 スタンダード環境
- Spring Boot 2.2.0
- Gradle 6.0
- JUnit 5
- Thymeleaf 3
Java 8 スタンダード環境から Java 11 への基本的な箇所の変更点
- インスタンスクラスのメモリが2倍に増えた (例えば F1 は 128MB が 256MB になった)
- アプリケーション設定ファイルが appengine-web.xml から app.yaml に変更された
- war ファイルではなく、実行可能な jar ファイルをデプロイする必要がある
ソースコード
ソースコード一覧
├── build.gradle
├── settings.gradle
└── src
├── main
│ ├── appengine
│ │ └── app.yaml
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── helloworld
│ │ ├── HelloworldApplication.java
│ │ ├── HelloworldController.java
│ │ └── HelloworldErrorController.java
│ └── resources
│ ├── application.yml
│ ├── static
│ │ └── assets
│ │ └── helloworld.png
│ └── templates
│ ├── error.html
│ └── helloworld.html
└── test
└── java
└── com
└── example
└── helloworld
└── HelloworldApplicationTests.java
build.gradle
Gradle でビルドに関する処理を記述するファイル。
Google App Engine Gradle plugin はバージョン2系を使用。
buildscript {
repositories {
mavenCentral()
}
dependencies {
// Spring Boot Gradle Plugin を使用
classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.2.0.RELEASE'
// Google App Engine Gradle plugin を使用
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.2.0'
}
}
plugins {
// Java プラグインを導入
id 'java'
// https://plugins.gradle.org/plugin/org.springframework.boot
id 'org.springframework.boot' version '2.2.0.RELEASE'
// https://plugins.gradle.org/plugin/io.spring.dependency-management
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
}
// App Engine プラグインを導入
apply plugin: 'com.google.cloud.tools.appengine'
repositories {
mavenCentral()
}
dependencies {
// App Engine API の最新版
implementation 'com.google.appengine:appengine-api-1.0-sdk:+'
// Thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// Spring Web
implementation 'org.springframework.boot:spring-boot-starter-web'
// Test
testImplementation('org.springframework.boot:spring-boot-starter-test') {
// JUnit 4 のサポートを除外する
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
// JUnit 5 のサポートを有効にする
useJUnitPlatform()
testLogging {
// テスト時の標準出力と標準エラー出力を表示する
showStandardStreams true
// イベントを出力する (TestLogEvent)
events 'started', 'skipped', 'passed', 'failed'
}
}
// Web アプリケーションのグループIDとバージョン
group = "com.example.helloworld"
version = "0.0.1"
// Java 11 を使用
sourceCompatibility = '11'
targetCompatibility = '11'
// Google App Engine タスクの設定
appengine {
// デプロイ時の設定
// GCLOUD_CONFIG を指定しておくと
// gcloud config で設定しているプロジェクト情報がセットされる
deploy {
// デプロイ先の Google Cloud Project ID
projectId = "GCLOUD_CONFIG"
// デプロイによって反映される Web アプリのバージョン
// 指定しなければ新しく生成される
version = "GCLOUD_CONFIG"
}
}
// デプロイ前にテストを実行
appengineDeploy.dependsOn test
appengineStage.dependsOn test
参考:
- Using Gradle and the App Engine Plugin | App Engine standard environment for Java 11 docs | Google Cloud
- GitHub - GoogleCloudPlatform/app-gradle-plugin: Gradle plugin to build and deploy Google App Engine applications.
- app-gradle-plugin/USER_GUIDE.md at master · GoogleCloudPlatform/app-gradle-plugin · GitHub
- Spring Boot Gradle Plugin Reference Guide
- Test - Gradle DSL Version 6.0
- TestLogEvent (Gradle API 6.0)
settings.gradle
setting.gradle を設置しないと親ディレクトリを辿って setting.gradle を探しにいってしまうのでシングルプロジェクトでも置いておく。
rootProject.name = 'helloworld'
app.yaml
Google App Engine 用の設定ファイル。Web アプリケーションの情報を記述する。
# Java 11 を使う
runtime: java11
# Java 8 ランタイムの F1 ではメモリが 128MB だったが Java 11 では 256MB
instance_class: F1
# インスタンス数のオートスケール設定
automatic_scaling:
max_instances: 1 # 最大インスタンス数
min_instances: 0 # 最小インスタンス数。0にすると使われていないときはインスタンス数が0になる
target_cpu_utilization: 0.95 # 新しいインスタンスを立ち上げるトリガーとなるCPU負荷率(0.5から0.95の間で指定)
max_concurrent_requests: 80 # 許容する同時リクエスト数(指定できる最大値は80)
# 環境変数を設定
env_variables:
JAVA_TOOL_OPTIONS: "-XX:MaxRAM=256m -XX:ActiveProcessorCount=2 -Xmx32m"
参考:
- Defining Runtime Settings | App Engine standard environment for Java 11 docs | Google Cloud
- app.yaml Configuration File | App Engine standard environment for Java 11 docs | Google Cloud
HelloworldApplication.java
アプリケーションクラス。Spring Boot を使うための定型的な処理だけを書いている。
package com.example.helloworld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}
HelloworldController.java
コントローラークラス。
package com.example.helloworld;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloworldController {
/**
* application.yml から取得したメッセージ。
*/
@Value("${application.message}")
private String applicationYamlMessage;
/**
* トップページのレスポンスを返す。
*
* @return ページ表示情報
*/
@GetMapping("/")
public ModelAndView index() {
System.out.println("HelloworldController#index");
// 表示するデータをセット
ModelAndView mav = new ModelAndView();
mav.addObject("applicationYamlMessage", applicationYamlMessage);
mav.setViewName("helloworld"); // ビュー名。Thymeleaf テンプレートファイルを指定
return mav;
}
/**
* エラーページを表示するテスト用メソッド。
*/
@GetMapping("/exception/")
public void exception() {
System.out.println("HelloworldController#exception");
throw new RuntimeException("This is a sample exception.");
}
}
HelloworldErrorController.java
Web アプリケーション全体のエラーコントローラークラス。
一般的なコントローラクラスでは捕捉できない Not Found などを処理している。
ここでは最低限の処理しか書いていないが、必要に応じてカスタマイズする。
package com.example.helloworld;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
* Web アプリケーション全体のエラーコントローラー。
* ErrorController インターフェースの実装クラス。
*/
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}") // エラーページへのマッピング
public class HelloworldErrorController implements ErrorController {
/**
* エラーページのパス。
*/
@Value("${server.error.path:${error.path:/error}}")
private String errorPath;
/**
* エラーページのパスを返す。
*
* @return エラーページのパス
*/
@Override
public String getErrorPath() {
return errorPath;
}
/**
* レスポンス用の ModelAndView オブジェクトを返す。
*
* @param req リクエスト情報
* @param mav レスポンス情報
* @return HTML レスポンス用の ModelAndView オブジェクト
*/
@RequestMapping
public ModelAndView error(HttpServletRequest req, ModelAndView mav) {
System.out.println("HelloWorldErrorController#error");
// どのエラーでも 404 Not Found にする
// 必要に応じてステータコードや出力内容をカスタマイズ可能
mav.setStatus(HttpStatus.NOT_FOUND);
mav.setViewName("error"); // error.html
return mav;
}
}
application.yml
Web アプリケーション設定情報を記述するファイル。application.properties でも良い。
今回は、アプリケーション独自の情報だけ設定している。
application:
message: Hello, application yaml.
helloworld.png
静的ファイル置き場を示すサンプルとして置いている画像。
静的ファイルは src/main/resources/static に置くと、http://hostname/ にマッピングされる。
今回は http://hostname/assets/helloworld.png にアクセスしたときに src/main/resources/static/assets/helloworld.png のファイルを配信するような構成になっている。
error.html
エラーが発生する際に表示する HTML の Thymeleaf テンプレートファイル。
今回は動的な値を埋め込んでいないが、必要に応じてエラーコントローラークラスで値をセットして、テンプレート側で表示するようにカスタマイズすることが可能。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>404 Not Found</title>
</head>
<body>
<h1>404 Not Found</h1>
</body>
</html>
helloworld.html
コントローラークラスがセットした値を表示するための HTML の Thymeleaf テンプレートファイル。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello, world.</title>
</head>
<body>
<h1>Hello, world.</h1>
<div th:text="'application.yml: ' + ${applicationYamlMessage}"></div>
<div><img src="./assets/helloworld.png"></div>
</body>
</html>
HelloworldApplicationTests.java
最低限のテストクラス。形式的なことだけ記述している。実際には何もテストしない。
package com.example.helloworld;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class HelloworldApplicationTests {
@Test
void contextLoads() {
}
}
オペレーション
gradle test でテストを実行
gradle の test タスクでテストを実行できる。
$ gradle test
gradle bootRun でローカルにサーバを起動
gradle bootRun でローカルサーバ http://localhost:8080/ を起動できる。
$ gradle bootRun
bootRun タスクは Spring Boot Gradle Plugin の機能のため、Google App Engine 用の設定ファイルである app.yaml は読み込まない。
gradle appengineDeploy で Google App Engine にデプロイ
gradle appengineDeploy で Google App Engine にデプロイできる。
$ gradle appengineDeploy
Gradle で利用可能なタスク
gradle tasks で利用可能なタスク一覧を見ることができる。
$ gradle tasks
> Task :tasks
------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------
App Engine app.yaml based projects tasks
----------------------------------------
appengineCloudSdkLogin - Login and set the Cloud SDK common configuration user
appengineDeploy - Deploy an App Engine application
appengineDeployAll - Deploy an App Engine application and all of its config files
appengineDeployCron - Deploy Cron configuration
appengineDeployDispatch - Deploy Dispatch configuration
appengineDeployDos - Deploy Dos configuration
appengineDeployIndex - Deploy Index configuration
appengineDeployQueue - Deploy Queue configuration
appengineShowConfiguration - Show current App Engine plugin configuration
appengineStage - Stage an App Engine app.yaml based project for deployment
checkCloudSdk - Validates the Cloud SDK
downloadCloudSdk - Download the Cloud SDK
Application tasks
-----------------
bootRun - Runs this project as a Spring Boot application.
(以下略)
参考資料
- Java 11 runtimes come to App Engine | Google Cloud Blog
- Turn it up to eleven: Java 11 runtime comes to App Engine | Google Cloud Blog
- Google App Engine Java 11 Standard Environment documentation | App Engine standard environment for Java 11 docs | Google Cloud
- Migrating your App Engine app from Java 8 to Java 11 | App Engine standard environment for Java 11 docs | Google Cloud
- java-docs-samples/appengine-java11 at master · GoogleCloudPlatform/java-docs-samples · GitHub
- Spring Boot Reference Documentation
- Google App EngineのJava 11アプリをGradleでビルドする(Spring Boot + Kotlin + Gradle Kotlin DSL) - Qiita