SlideShare a Scribd company logo
1 of 108
Download to read offline
Spring Bootをはじめる時に

やるべき10のこと

#bootきのこ
Shin Tanimoto

Acroquest Technology Co., LTD
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
皆さん

用意はいいですか?
2
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
鈴木会長は

こっちじゃないぞ?
3
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
では、始めましょう!
4
Copyright © Acroquest Technology Co., Ltd. All rights reserved.
自己紹介
5
• 谷本 心 (Shin Tanimoto)
- Acroquest Technology株式会社
- 開発&トラブルシュート教育
- JavaOneスピーカー
- JJUG / 関ジャバ / S2JSFコミッタ
- Twitter : @cero_t (日本語)
- Facebook : shin.tanimoto (英語)
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6
Struts + Hibernate
Seasar2 + S2JSF + S2Dao
Click + Guice + Mirage
Spring MVC + Hibernate
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
フレームワークに

求めていること
7
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
開発効率

生産性
8
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ではなくて
9
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ハマらない

ミスしない

ミスをリカバリできる
10
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ひとつハマれば

3人日が奪われ
11
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ひとつミスしていれば

商用障害が起き
12
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
リカバリできずに

今日も徹夜
13
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ハマらない

ミスしない

ミスをリカバリできる
14
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
そのための

Spring Boot
15
Spring Bootをはじめる時に

やるべき10のこと

#bootきのこ
Shin Tanimoto

Acroquest Technology Co., LTD
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
17
#1

SpringBootを知る
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
Spring Bootとは
複雑化したSpringプロジェクト群を使った開発を
シンプルに開始できる仕組み
18
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
19
Springベースの

フルスタック

プラットフォーム
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
フルスタックプラットフォーム
View層、コンテナ層、データアクセス層

監視、非同期メッセージング、クラウド対応など

様々な機能を「Spring Boot」という共通の

プラットフォーム上で利用できる。
20
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
フルスタックプラットフォームでないと
自分で様々なフレームワークを組み合わせると

もちろん自由に選べる反面、

設定の記述や、動作検証などが必要になる。
ここに「ハマり」要因がある。
21
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
あまり強調しない方が良いこと
Microservices向けフレームワーク
別にそれが目的ではない
Executable JAR ≠ Microservices
XMLを書かない
ymlや設定クラスを少し作る
22
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
23
#1
Spring Bootなら

組み合わせでハマらない!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
24
#2

はじめての

Spring Boot
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
2. はじめてのSpring Boot
新しいプロダクトの利用時あるある
ドキュメントがない。
ドキュメントが英語しかない。
ブログがない。ノウハウがない。
とりあえず少しずつググりながら

場当たり対応で何とか凌ぐ。
そんなことをしているから「設計ミス」をする。
25
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
2. はじめてのSpring Boot
はじめてのSpring Boot
26
@makingの力作
Spring Bootを用いた

開発、試験、デプロイなどを

まるっと習得できる
こっちの入門スライドもオススメ

http://www.slideshare.net/
makingx/grails-30-spring-boot
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
27
#2
はじめてのSpring Bootで

初期学習を効率化!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
28
#3

Spring Initializr
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
3. Spring Initializr
プロジェクト立ち上げ時あるある
pom.xmlを書いて、必要な依存ライブラリを列挙する。
・・・のは面倒だから、exampleプロジェクトを探して

不要なソースコードを削除する。
なんか不要なJARが混入している
なぜかバージョン違いのJARが混入する
頑張ってビルドファイルを書いたけど、なぜか動かない。
ここに「ミス」と「ハマり」要因がある。
29
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
3. Spring Initializr
Spring Initializrとは
https://start.spring.io/
Spring Bootプロジェクトの雛形を作る
Maven or Gradleのプロジェクト作成
利用するプロジェクトやライブラリを選択できる
Web、JDBC、Security、AOP、

JPA、Thymeleafなど
つまずかずにスタートできる!
30
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
3. Spring Initializr
使い方
https://start.spring.io/ に行く。
必要な情報と、利用するモジュールを選ぶ。
Actuatorおすすめ
Generate Projectをクリック。
ダウンロードしたzipを解凍する。
IDEにインポートする。
以下のいずれかで実行する。
mainメソッドを実行する
mvn spring-boot:run
31
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
32
#3
Spring Initializrなら

初期構築でミスしない!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
33
#4

pom.xmlの設計
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
4. pom.xmlの設計
pom.xmlあるある
複数モジュールを作る時、依存JARのバージョンを

複数のpom.xmlに重複して書いている。
そしてJARのバージョン違いが発生する
親子モジュールとか難しいから、

単一モジュールで行くぜー!
WebAPIとバッチがなぜか同じJARに入ってる
34
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
4. pom.xmlの設計
pom.xmlのグッドプラクティス
デプロイ単位、ライフサイクル単位で分割する
共通部分を切り出す
フレームワーク部分
自動生成したエンティティ
しかしそうすると、前述したJARの

バージョン違い問題が起きる・・・?
35
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
4. pom.xmlの設計
pom.xmlのグッドプラクティス
依存JARのバージョンは、親のpom.xmlに書く
<dependencyManagement> を使ってバージョンを定義する
Spring IO platformを使う
http://platform.spring.io/platform/
大げさな名前だが、ただのpom.xml
Spring関連モジュールだけでなく、

著名なプロダクトも含むバージョンを規定したpom.xml
commons-lang、guice、joda-time、jruby、、、
Version1.1.4では552個のモジュールのバージョンが規定されている
36
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
37
#4
Spring IO platformで

pom.xmlをシンプルに!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
38
#5

Controllerの共通設定
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
突然ですが、

JSR 310 Date and Time APIの

LocalDateクラスってご存じですか?
LocalDate : 日付のみ。時間なし。
LocalTime : 時間のみ。日付なし。
LocalDateTime : 日付も時間もあり。
39
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
java.util.DateやCalendarはハマりやすい
Dateを使って比較する際、日付だけで良いのに

余計な時分秒が入っているせいで、判定を誤る。
Calendarで時分秒に0を指定したけど

ミリ秒に余計な値が入っていて、判定を誤る。
SimpleDateFormatがスレッドセーフでないことを

知らずに、商用環境で問題が起きる。
40
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
JSR 310をSpring Bootでも使いたい
できること
yyyy-MM-dd形式の日付
JSONリクエスト → LocalDateフィールド
できないこと
yyyy/MM/dd形式の日付
LocalDateフィールド → JSONレスポンス
41
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
ControllerでLocalDateを使う
Controllerで利用するJacksonをカスタマイズする
Controllerの引数・戻り値のオブジェクトと

JSONリクエスト・レスポンスは、

Jacksonでシリアライズ・デシリアライズされる。
Jackson2ObjectMapperBuilderを

戻すメソッドに@Beanをつけることで

カスタマイズできる。
42
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
return Jackson2ObjectMapperBuilder.json()
.indentOutput(true)
.serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value.format(DATE_FORMATTER));
}
})
.deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonParser jp,
DeserializationContext ctxt) throws IOException, JsonProcessingException {
return LocalDate.parse(jp.getValueAsString(), DATE_PARSER);
}
})
.modules(new JSR310Module());
}
43
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
return Jackson2ObjectMapperBuilder.json()
.indentOutput(true)
.serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value.format(DATE_FORMATTER));
}
})
.deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonParser jp,
DeserializationContext ctxt) throws IOException, JsonProcessingException {
return LocalDate.parse(jp.getValueAsString(), DATE_PARSER);
}
})
.modules(new JSR310Module());
}
44
出力するJSONを
読みやすく
LocalDateの

シリアライズと

デシリアライズ
他のJSR 310クラスも

使えるようにしておく
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
/** 日付フォーマット */
protected static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
/** 日付パースフォーマット */
protected static final DateTimeFormatter DATE_PARSER =
DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d");
45
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
/** 日付フォーマット */
protected static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
/** 日付パースフォーマット */
protected static final DateTimeFormatter DATE_PARSER =
DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d");
入力は柔軟に、出力は厳格に。
46
フォーマット時は

0埋め、

ハイフン区切り
パース時は

0埋め、区切りを

少し自由に
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
47
#5
ControllerでLocalDateを

使って日付判定ミスを防ぐ!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
48
#6

トランザクション

境界の設定
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
トランザクションあるある
Controllerをトランザクション境界にする
処理の途中で一度コミットしたいけどできない
非同期処理呼び出しの前にコミットとか
途中でコミットできるような仕組みを

無理に作ったら全体的な整合性が崩れた
性能改善のためのリードレプリカを作りたいが、

そもそもアクセスを振り分けられない
49
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
Service層をトランザクション境界にする
Controllerの次の層をトランザクション境界にする
処理の単位が明確になる
Service層からreturnすればコミット、

例外で戻ればロールバック。
Service層のクラスすべてに

@Transactionalアノテーションをつける
50
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
原則、Read Onlyトランザクションを使う
Service層のクラスすべてに

@Transactional(readOnly = true) をつける
Insert / Update / Deleteが発生する時だけ

メソッドに @Transactional(readOnly = false) を

つける
ReadOnlyトランザクションだけを

リードレプリカに振り分ける
51
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
@Service
@Transactional(readOnly = true)
public class EmployeeService {
@Autowired
protected EmployeeDao employeeDao;
public Employee getEmployee(Integer id) {
return employeeDao.selectById(id);
}
@Transactional(readOnly = false)
public int createEmployee(Employee employee) {
return employeeDao.insert(employee);
}
}
52
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
@Service
@Transactional(readOnly = true)
public class EmployeeService {
@Autowired
protected EmployeeDao employeeDao;
public Employee getEmployee(Integer id) {
return employeeDao.selectById(id);
}
@Transactional(readOnly = false)
public int createEmployee(Employee employee) {
return employeeDao.insert(employee);
}
}
53
クラスには

readOnly = true
更新系メソッドに

readOnly = false
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
54
#6
ServiceクラスにRead Onlyな

トランザクションを設けて

将来に備える!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
55
#7

O/Rマッパーの選択
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
O/Rマッパーあるある
とりあえずHibernate
思ったのと違うSQLが発行された
1リクエストでSQLが1万回発行された
selectしたタイミングで一意制約違反が出た
キャッシュが想定外の動きをした。
要するにハマる
56
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
O/Rマッパーあるある
じゃぁMyBatis
Spring Bootで標準対応していない
1.3で標準対応されるかも
https://github.com/spring-projects/spring-boot/pull/3692
SQLを書いたXMLをフォーマットしたら

インデントが全部消えた
> とか < のエスケープ
57
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
O/Rマッパーあるある
じゃぁJdbcTemplate
なんかAPIが古くさい(Spring 2.0時代のAPI)
publicフィールドが使えない
JSR 310に対応していない
58
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
59
そこで

Bootiful SQL Template
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
Bootiful SQL Template
JdbcTemplate / NamedParameterJdbcTemplateの

独自ラッパー
SQLファイルを書ける(FreeMarker形式も可)
モダンなAPI
publicフィールドが使える
JSR 310に対応(ZonedDateTimeにも)
https://github.com/cero-t/sqltemplate
60
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
@Autowired
protected SqlTemplate sqlTemplate;
public List<Employee> selectByCondition(EmployeeCondition condition) {
return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql",
Employee.class, condition);
}
61
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
@Autowired
protected SqlTemplate sqlTemplate;
public List<Employee> selectByCondition(EmployeeCondition condition) {
return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql",
Employee.class, condition);
}
62
モダンでサクっと

使えるAPI
IntelliJなら

Command(Ctrl) + クリックで

SQLファイルにジャンプ
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
SELECT
*
FROM
emp
WHERE
1 = 1
<#if name??>
AND ename like '%' || :name || '%'
</#if>
<#if hiredateFrom??>
AND :hiredateFrom < hiredate
</#if>
<#if hiredateTo??>
AND hiredate < :hiredateTo
</#if>
<#if deptno??>
AND deptno = :deptno
</#if>
63
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
SELECT
*
FROM
emp
WHERE
1 = 1
<#if name??>
AND ename like '%' || :name || '%'
</#if>
<#if hiredateFrom??>
AND :hiredateFrom < hiredate
</#if>
<#if hiredateTo??>
AND hiredate < :hiredateTo
</#if>
<#if deptno??>
AND deptno = :deptno
</#if>
64
FreeMarker形式の

テンプレートが利用可能



ANDを自動的に消す機能が

なくてごめんな
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
65
#7
Bootiful SQL Templateで

SQLを書いてハマり知らず
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
66
#8

例外処理の共通化
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
例外処理あるある
個別の開発者任せ
もちろん死ぬ
フレームワークが返す例外(バリデーションなど)と、

アプリケーションが返す例外でJSONの形式が違う
クライアント側で判別に失敗して死ぬ
個別のエラーコードを定義しておいたので

全部ソースコード内に書く
守らない人がいて死ぬ
67
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
例外処理は共通化する
ApplicationException extends RuntimeExceptionを
作って必ずこれを使う
エラー種別をenumに定義しておき、

ApplicationExceptionのコンストラクタの

第一引数に必ず渡す
エラー種別と、HTTPステータスやエラーコード、

エラーメッセージを紐付けて管理する
68
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public class ApplicationException extends RuntimeException {
Throwable cause;
Object[] args;
private HttpErrors error;
public AppException(HttpErrors error, Throwable cause, String... args) {
super();
this.error = error;
this.args = args;
this.cause = cause;
}
// その他のコンストラクタ、cause、args、errorのgetterは割愛
public String getMessage() {
if (args != null) {
return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args);
}
return "[" + error.name() + "]" + error.getMessage();
}
}
69
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public class ApplicationException extends RuntimeException {
Throwable cause;
Object[] args;
private HttpErrors error;
public AppException(HttpErrors error, Throwable cause, String... args) {
super();
this.error = error;
this.args = args;
this.cause = cause;
}
// その他のコンストラクタ、cause、args、errorのgetterは割愛
public String getMessage() {
if (args != null) {
return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args);
}
return "[" + error.name() + "]" + error.getMessage();
}
}
70
第一引数で

エラー種別を受け取る
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public interface HttpErrors {
/**
* HTTPステータスを取得します。
* @return HTTPステータス
*/
HttpStatus getStatus();
/**
* メッセージを取得します。
* @return メッセージ
*/
String getMessage();
/**
* エラー名を取得します。
* @return エラー名
*/
String name();
}
71
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public enum Errors implements HttpErrors {
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"),
UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}");
protected HttpStatus status;
protected String message;
Errors(HttpStatus status, String message) {
this.status = status;
this.message = message;
}
@Override
public HttpStatus getStatus() {
return status;
}
@Override
public String getMessage() {
return message;
}
}
72
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public enum Errors implements HttpErrors {
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"),
UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}");
protected HttpStatus status;
protected String message;
Errors(HttpStatus status, String message) {
this.status = status;
this.message = message;
}
@Override
public HttpStatus getStatus() {
return status;
}
@Override
public String getMessage() {
return message;
}
}
73
エラーを列挙
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
例外処理ハンドリングも共通化する
ApplicationExceptionと

RuntimeExceptionと

フレームワークが返す例外で

すべて同じ例外ハンドリングをする
74
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
/** ロガー */
protected final Log logger = LogFactory.getLog(getClass());
@ExceptionHandler(value = ApplicationException.class)
@ResponseBody
public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) {
return handleError(request, ex.getError(), ex, ex.getArgs());
}
@ExceptionHandler(value = RuntimeException.class)
@ResponseBody
public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) {
return handleError(request, Errors.UNEXPECTED, ex, ex.toString());
}
75
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
/** ロガー */
protected final Log logger = LogFactory.getLog(getClass());
@ExceptionHandler(value = ApplicationException.class)
@ResponseBody
public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) {
return handleError(request, ex.getError(), ex, ex.getArgs());
}
@ExceptionHandler(value = RuntimeException.class)
@ResponseBody
public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) {
return handleError(request, Errors.UNEXPECTED, ex, ex.toString());
}
76
独自のApplicationExceptionと

想定しないRuntimeExceptionの両方を

同じ方式でハンドリング
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex,
Object... args) {
String message = MessageFormat.format(error.getMessage(), args);
if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) {
logger.error(message, ex);
} else {
logger.debug(message, ex);
}
if (error.getStatus() == HttpStatus.UNAUTHORIZED) {
return new ResponseEntity<>(error.getStatus());
}
RestError restError = new RestError();
restError.path = request.getRequestURI();
restError.error = error.name();
restError.status = error.getStatus()
.value();
restError.message = message;
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, error.getStatus());
}
77
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex,
Object... args) {
String message = MessageFormat.format(error.getMessage(), args);
if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) {
logger.error(message, ex);
} else {
logger.debug(message, ex);
}
if (error.getStatus() == HttpStatus.UNAUTHORIZED) {
return new ResponseEntity<>(error.getStatus());
}
RestError restError = new RestError();
restError.path = request.getRequestURI();
restError.error = error.name();
restError.status = error.getStatus()
.value();
restError.message = message;
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, error.getStatus());
}
78
例外オブジェクトへの変換
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
HttpStatus status, WebRequest request) {
RestError restError = new RestError();
if (request instanceof ServletWebRequest) {
restError.path = ((ServletWebRequest) request).getRequest()
.getRequestURI();
} else {
restError.path = request.getContextPath();
}
restError.error = status.getReasonPhrase();
restError.status = status.value();
restError.message = ex.getMessage();
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, status);
}
}
79
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
HttpStatus status, WebRequest request) {
RestError restError = new RestError();
if (request instanceof ServletWebRequest) {
restError.path = ((ServletWebRequest) request).getRequest()
.getRequestURI();
} else {
restError.path = request.getContextPath();
}
restError.error = status.getReasonPhrase();
restError.status = status.value();
restError.message = ex.getMessage();
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, status);
}
}
80
このオーバーライドで

Spring MVCが投げる例外を

ハンドリングできる
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
81
#8
すべての例外を共通して

ハンドリングせよ!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
82
#9

AOPによるロギング
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
9. AOPによるロギング
AOPとは
アプリケーション横断的に行う処理
トランザクションのコミットやロールバックもAOPで実現されている
オススメは、AOPによる自動ロギング
Controller / Service / DaoのIn/Outでロギング
デバッグ時に、アプリケーションの挙動がとてもよく分かる
ログレベルに応じて引数、戻り値なども出す
SpringではXMLやアノテーションでAOPの対象を記述することができる
正直、アノテーションの記述はイマイチ。分かりづらい。
記述性はGuice > Seasar > Spring。
83
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
9. AOPによるロギング
@Aspect
@Component
public class DumpLogInterceptor {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))")
public Object dump(ProceedingJoinPoint joinPoint) throws Throwable {
try {
logger.debug("BEGIN - " + toCall(joinPoint));
logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(),
ToStringStyle.SHORT_PREFIX_STYLE));
Object retValue = joinPoint.proceed(joinPoint.getArgs());
logger.debug("END - " + toCall(joinPoint));
logger.trace(
"with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE));
return retValue;
} catch (Throwable th) {
logger.debug("END throw - " + toCall(joinPoint));
logger.debug("Exception: " + th);
throw th;
}
}
}
84
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
9. AOPによるロギング
@Aspect
@Component
public class DumpLogInterceptor {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))")
public Object dump(ProceedingJoinPoint joinPoint) throws Throwable {
try {
logger.debug("BEGIN - " + toCall(joinPoint));
logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(),
ToStringStyle.SHORT_PREFIX_STYLE));
Object retValue = joinPoint.proceed(joinPoint.getArgs());
logger.debug("END - " + toCall(joinPoint));
logger.trace(
"with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE));
return retValue;
} catch (Throwable th) {
logger.debug("END throw - " + toCall(joinPoint));
logger.debug("Exception: " + th);
throw th;
}
}
}
85
この記述でController / Service

Daoの実行前後に処理を差し込む
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
86
#9
AOPによるロギングで

問題発生時のリカバリを

高速化しよう
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
87
#10

テスト設計
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストあるある
とりあえず、手動でテストしようぜ!

 → 回帰試験で死ぬ。
ロジックがあるControllerからテストすればOK!

 → バリデーションの設定ミスで死ぬ。
通常使うComponentとモックのComponentは

@Profileで切り替えるのがSpring流!

 → 管理できなくなってきて死ぬ。
Spring Bootはend-to-endでテストしやすいから

end-to-endのテストでカバレッジ80%を目指そう!

 → そして死ぬ。
88
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのグッドプラクティス
Controller以降をJUnitでテストする。
カバレッジは最低60%、できれば80%を目指す。
外部サービス呼び出し部分は、モック化する(後述)
例外を任意で発生させたい場合も、モック化すると良い。
無名クラスを活用したモックを作れるようになろう。
end-to-endのJUnitを書いて、

正常系1本とバリデーション部分をテストする。
JUnitのテストクラスに @IntegrationTest(“server.port=0”) をつけ、
RestTemplateを用いてテストする。
バリデーションの試験は、end-to-endでしかできない。
89
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
90
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
91
テストの時に必ずつけるアノテーション。
トランザクションを有効にして

試験が終わったら自動でロールバック。
TestContextConfigはあとで。
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@WebAppConfiguration
@IntegrationTest("server.port=0")
@Transactional
public class EmployeesTest {
@Value("http://localhost:${local.server.port}/employees")
String baseUrl;
@Autowired
RestTemplate restTemplate;
@Test
public void testGetList() {
ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class);
// TODO: assert
}
92
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@WebAppConfiguration
@IntegrationTest("server.port=0")
@Transactional
public class EmployeesTest {
@Value("http://localhost:${local.server.port}/employees")
String baseUrl;
@Autowired
RestTemplate restTemplate;
@Test
public void testGetList() {
ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class);
// TODO: assert
}
93
@WebAppConfigurationと

@IntegrationTestをつけて

Tomcatを起動
RestTemplateでアクセス
URLを設定
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのTips
schema.sqlとdata.sqlでデータ投入する
/src/test/resources にschema.sqlとdata.sqlを

置いておけば、JUnitの起動前にのみ実行される。
/src/main/resources に置いておけば

通常起動時に実行される(動作確認向け)
事故ってproduction環境で動かさないように!
Controllerのテストと、end-to-endのテストは同じapplication.ymlでテストする
end-to-endの試験も自動化するため。
end-to-endのテストは、ついつい範囲を広げたくなるが

自動化する試験と、そうでない試験は分けるべき。
94
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのTips
@Componentのモックは、

@Profileよりも@Primaryをつけた方が良い
外部サービスの呼び出しなどをモック化する場合、

モック化したい部分を @Autowired にしておく。
モッククラスを /src/test/java 以下で作成し、

@Component (@Bean) と@Primaryアノテーションを

つければ、JUnit実行時のみ利用される。
95
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
public interface Context {
/**
* セッションIDを取得します。
* @return セッションID
*/
String getSessionId();
}
96
本体コード側にある

インタフェース。
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
public class RequestContext implements Context {
protected HttpServletRequest request;
public RequestContext(HttpServletRequest request) {
this.request = request;
}
@Override
public String getSessionId() {
return request.getSession().getId();
}
}
97
本体コード側にある実装。

HttpServletRequestを使っているので

JUnit時にはエラーが起きる
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@Configuration
public class TestContextConfig {
@Bean
@Primary
public Context context() {
return new Context() {
@Override
public String getSessionId() {
return "JUNIT";
}
};
}
}
98
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@Configuration
public class TestContextConfig {
@Bean
@Primary
public Context context() {
return new Context() {
@Override
public String getSessionId() {
return "JUNIT";
}
};
}
}
99
テスト側の設定クラス。
ここに@Primaryを書けば

このコンポーネントが

優先して使われる。
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
100
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
101
テスト側で、先ほど書いた

Configurationを明示的に読み込む
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのTips
/src/test/java 側に作ったテスト用の

@Primary つき@Component (@Bean) は

end-to-endのサーバ側にも適用されるので

サーバ側でもモックを使いやすい
たぶんこれ相当便利。
102
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
103
まとめ
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
104
スライド読み直せ!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
105
One more thing…
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
106
今日紹介したソースは

GitHubで公開中!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
107
https://github.com/cero-t/
spring-boot-kinoko-2015
Copyright © Acroquest Technology Co., Ltd. All rights reserved.
108
Enjoy Spring Boot!

More Related Content

What's hot

Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccPivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccMasatoshi Tada
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところY Watanabe
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ増田 亨
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugMasatoshi Tada
 
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービューMasatoshi Tada
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Taku Miyakawa
 
ストリーム処理を支えるキューイングシステムの選び方
ストリーム処理を支えるキューイングシステムの選び方ストリーム処理を支えるキューイングシステムの選び方
ストリーム処理を支えるキューイングシステムの選び方Yoshiyasu SAEKI
 
Springを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイントSpringを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント土岐 孝平
 
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDayマイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay都元ダイスケ Miyamoto
 
決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話Ryosuke Uchitate
 
今さら聞けないDiとspring
今さら聞けないDiとspring今さら聞けないDiとspring
今さら聞けないDiとspring土岐 孝平
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Kohei Tokunaga
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法についてYuji Otani
 
OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)
OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)
OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)NTT DATA Technology & Innovation
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法Tetsutaro Watanabe
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティスAmazon Web Services Japan
 
SQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するかSQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するかShogo Wakayama
 

What's hot (20)

Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccPivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
ストリーム処理を支えるキューイングシステムの選び方
ストリーム処理を支えるキューイングシステムの選び方ストリーム処理を支えるキューイングシステムの選び方
ストリーム処理を支えるキューイングシステムの選び方
 
Springを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイントSpringを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント
 
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDayマイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
 
決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話
 
今さら聞けないDiとspring
今さら聞けないDiとspring今さら聞けないDiとspring
今さら聞けないDiとspring
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
 
OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)
OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)
OpenJDKのコミッタってどんなことしたらなったの?解決してきた技術課題の事例から見えてくる必要な知識と技術(JJUG CCC 2023 Spring)
 
Maven基礎
Maven基礎Maven基礎
Maven基礎
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
 
GraphQL入門 (AWS AppSync)
GraphQL入門 (AWS AppSync)GraphQL入門 (AWS AppSync)
GraphQL入門 (AWS AppSync)
 
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajpAt least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
 
SQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するかSQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するか
 

Viewers also liked

イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情takezoe
 
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!心 谷本
 
JJUG CCC 2015 Fall keynote
JJUG CCC 2015 Fall keynoteJJUG CCC 2015 Fall keynote
JJUG CCC 2015 Fall keynote心 谷本
 
Spring Boot + Netflix Eureka
Spring Boot + Netflix EurekaSpring Boot + Netflix Eureka
Spring Boot + Netflix Eureka心 谷本
 
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜Masaru Kurahayashi
 
Microserviceなんて最初からやるもんじゃ無かった
Microserviceなんて最初からやるもんじゃ無かったMicroserviceなんて最初からやるもんじゃ無かった
Microserviceなんて最初からやるもんじゃ無かったAkira Miki
 
Beginning Java EE 6 勉強会(6) #bje_study
Beginning Java EE 6 勉強会(6) #bje_studyBeginning Java EE 6 勉強会(6) #bje_study
Beginning Java EE 6 勉強会(6) #bje_studyMasato Kawamura
 
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawawsOAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawawsTatsuo Kudo
 
WebAPIのこれまでとこれから
WebAPIのこれまでとこれからWebAPIのこれまでとこれから
WebAPIのこれまでとこれからYohei Yamamoto
 
OpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンスOpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンスOpenID Foundation Japan
 
Java でつくる 低レイテンシ実装の技巧
Java でつくる低レイテンシ実装の技巧Java でつくる低レイテンシ実装の技巧
Java でつくる 低レイテンシ実装の技巧 Ryosuke Yamazaki
 
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WGNat Sakimura
 
今更聞けないOAuth2.0
今更聞けないOAuth2.0今更聞けないOAuth2.0
今更聞けないOAuth2.0Takahiro Sato
 
Office365のIdentity管理
Office365のIdentity管理Office365のIdentity管理
Office365のIdentity管理Naohiro Fujie
 
なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景Tatsuo Kudo
 
エンタープライズITでのOpenID Connect利用ガイドライン
エンタープライズITでのOpenID Connect利用ガイドラインエンタープライズITでのOpenID Connect利用ガイドライン
エンタープライズITでのOpenID Connect利用ガイドラインTatsuo Kudo
 
SAML / OpenID Connect / OAuth / SCIM 技術解説 - ID&IT 2014 #idit2014
SAML / OpenID Connect / OAuth / SCIM 技術解説  - ID&IT 2014 #idit2014SAML / OpenID Connect / OAuth / SCIM 技術解説  - ID&IT 2014 #idit2014
SAML / OpenID Connect / OAuth / SCIM 技術解説 - ID&IT 2014 #idit2014Nov Matake
 
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜Masaru Kurahayashi
 

Viewers also liked (20)

イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情
 
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
 
JJUG CCC 2015 Fall keynote
JJUG CCC 2015 Fall keynoteJJUG CCC 2015 Fall keynote
JJUG CCC 2015 Fall keynote
 
Spring Boot + Netflix Eureka
Spring Boot + Netflix EurekaSpring Boot + Netflix Eureka
Spring Boot + Netflix Eureka
 
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
 
Microserviceなんて最初からやるもんじゃ無かった
Microserviceなんて最初からやるもんじゃ無かったMicroserviceなんて最初からやるもんじゃ無かった
Microserviceなんて最初からやるもんじゃ無かった
 
Beginning Java EE 6 勉強会(6) #bje_study
Beginning Java EE 6 勉強会(6) #bje_studyBeginning Java EE 6 勉強会(6) #bje_study
Beginning Java EE 6 勉強会(6) #bje_study
 
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawawsOAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws
 
WebAPIのこれまでとこれから
WebAPIのこれまでとこれからWebAPIのこれまでとこれから
WebAPIのこれまでとこれから
 
OpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンスOpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンス
 
Java でつくる 低レイテンシ実装の技巧
Java でつくる低レイテンシ実装の技巧Java でつくる低レイテンシ実装の技巧
Java でつくる 低レイテンシ実装の技巧
 
REST 入門
REST 入門REST 入門
REST 入門
 
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG
 
今更聞けないOAuth2.0
今更聞けないOAuth2.0今更聞けないOAuth2.0
今更聞けないOAuth2.0
 
Office365のIdentity管理
Office365のIdentity管理Office365のIdentity管理
Office365のIdentity管理
 
なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景
 
エンタープライズITでのOpenID Connect利用ガイドライン
エンタープライズITでのOpenID Connect利用ガイドラインエンタープライズITでのOpenID Connect利用ガイドライン
エンタープライズITでのOpenID Connect利用ガイドライン
 
SAML / OpenID Connect / OAuth / SCIM 技術解説 - ID&IT 2014 #idit2014
SAML / OpenID Connect / OAuth / SCIM 技術解説  - ID&IT 2014 #idit2014SAML / OpenID Connect / OAuth / SCIM 技術解説  - ID&IT 2014 #idit2014
SAML / OpenID Connect / OAuth / SCIM 技術解説 - ID&IT 2014 #idit2014
 
Uberご紹介(髙橋正巳)
Uberご紹介(髙橋正巳)Uberご紹介(髙橋正巳)
Uberご紹介(髙橋正巳)
 
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
 

Similar to Spring Bootをはじめる時にやるべき10のこと

人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記心 谷本
 
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜gree_tech
 
ドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkinsドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkinsGo Sueyoshi (a.k.a sue445)
 
Spring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作るSpring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作るGo Miyasaka
 
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」aitc_jp
 
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップShigeki Morizane
 
iPhoneアプリ開発を楽に楽しくするサイトまとめ
iPhoneアプリ開発を楽に楽しくするサイトまとめiPhoneアプリ開発を楽に楽しくするサイトまとめ
iPhoneアプリ開発を楽に楽しくするサイトまとめHiramatsu Ryosuke
 
どうする!?これからのCto c(仮)
どうする!?これからのCto c(仮)どうする!?これからのCto c(仮)
どうする!?これからのCto c(仮)Junya Tanaka
 
スタートアップ向け!1人日でできるサービスの高速化方法と成果
スタートアップ向け!1人日でできるサービスの高速化方法と成果スタートアップ向け!1人日でできるサービスの高速化方法と成果
スタートアップ向け!1人日でできるサービスの高速化方法と成果Koichiro Sumi
 
おすすめインフラ! for スタートアップ
おすすめインフラ! for スタートアップおすすめインフラ! for スタートアップ
おすすめインフラ! for スタートアップKoichiro Sumi
 
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告Haruka Yamashita
 
Google apps scriptを使って業務改善
Google apps scriptを使って業務改善Google apps scriptを使って業務改善
Google apps scriptを使って業務改善dcubeio
 
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」softlayerjp
 
Whomor spine勉強会 遠藤加筆_150114
Whomor spine勉強会 遠藤加筆_150114Whomor spine勉強会 遠藤加筆_150114
Whomor spine勉強会 遠藤加筆_150114幹也 芝辻
 
IETF90 IoT関連WG報告 #isocjp
IETF90 IoT関連WG報告 #isocjpIETF90 IoT関連WG報告 #isocjp
IETF90 IoT関連WG報告 #isocjpKaoru Maeda
 
技術選択とアーキテクトの役割 (要約版)
技術選択とアーキテクトの役割 (要約版)技術選択とアーキテクトの役割 (要約版)
技術選択とアーキテクトの役割 (要約版)Toru Yamaguchi
 
ああ、素晴らしきTDD ~アプリとエンジニアの心に安寧を~
ああ、素晴らしきTDD  ~アプリとエンジニアの心に安寧を~ああ、素晴らしきTDD  ~アプリとエンジニアの心に安寧を~
ああ、素晴らしきTDD ~アプリとエンジニアの心に安寧を~Saiki Iijima
 
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶ
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶColdfusionを活かすシステム企画をリーンスタートアップに学ぶ
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶmasashi takehara
 

Similar to Spring Bootをはじめる時にやるべき10のこと (20)

人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
 
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
 
ドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkinsドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkins
 
Spring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作るSpring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作る
 
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
 
RPAって何、どんなことできるの
RPAって何、どんなことできるのRPAって何、どんなことできるの
RPAって何、どんなことできるの
 
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
 
iPhoneアプリ開発を楽に楽しくするサイトまとめ
iPhoneアプリ開発を楽に楽しくするサイトまとめiPhoneアプリ開発を楽に楽しくするサイトまとめ
iPhoneアプリ開発を楽に楽しくするサイトまとめ
 
どうする!?これからのCto c(仮)
どうする!?これからのCto c(仮)どうする!?これからのCto c(仮)
どうする!?これからのCto c(仮)
 
スタートアップ向け!1人日でできるサービスの高速化方法と成果
スタートアップ向け!1人日でできるサービスの高速化方法と成果スタートアップ向け!1人日でできるサービスの高速化方法と成果
スタートアップ向け!1人日でできるサービスの高速化方法と成果
 
おすすめインフラ! for スタートアップ
おすすめインフラ! for スタートアップおすすめインフラ! for スタートアップ
おすすめインフラ! for スタートアップ
 
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告
 
Google apps scriptを使って業務改善
Google apps scriptを使って業務改善Google apps scriptを使って業務改善
Google apps scriptを使って業務改善
 
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」
 
Whomor spine勉強会 遠藤加筆_150114
Whomor spine勉強会 遠藤加筆_150114Whomor spine勉強会 遠藤加筆_150114
Whomor spine勉強会 遠藤加筆_150114
 
IETF90 IoT関連WG報告 #isocjp
IETF90 IoT関連WG報告 #isocjpIETF90 IoT関連WG報告 #isocjp
IETF90 IoT関連WG報告 #isocjp
 
技術選択とアーキテクトの役割 (要約版)
技術選択とアーキテクトの役割 (要約版)技術選択とアーキテクトの役割 (要約版)
技術選択とアーキテクトの役割 (要約版)
 
Ladder of cqrs+es
Ladder of cqrs+esLadder of cqrs+es
Ladder of cqrs+es
 
ああ、素晴らしきTDD ~アプリとエンジニアの心に安寧を~
ああ、素晴らしきTDD  ~アプリとエンジニアの心に安寧を~ああ、素晴らしきTDD  ~アプリとエンジニアの心に安寧を~
ああ、素晴らしきTDD ~アプリとエンジニアの心に安寧を~
 
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶ
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶColdfusionを活かすシステム企画をリーンスタートアップに学ぶ
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶ
 

More from 心 谷本

プレゼンの技術 2 実践編
プレゼンの技術 2 実践編プレゼンの技術 2 実践編
プレゼンの技術 2 実践編心 谷本
 
プレゼンの技術 1 考え方
プレゼンの技術 1 考え方プレゼンの技術 1 考え方
プレゼンの技術 1 考え方心 谷本
 
プレゼンの技術
プレゼンの技術プレゼンの技術
プレゼンの技術心 谷本
 
from old java to java8 - KanJava Edition
from old java to java8 - KanJava Editionfrom old java to java8 - KanJava Edition
from old java to java8 - KanJava Edition心 谷本
 
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡心 谷本
 
from old Java to modern Java
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java心 谷本
 
日本一細かいJavaOne2011報告
日本一細かいJavaOne2011報告日本一細かいJavaOne2011報告
日本一細かいJavaOne2011報告心 谷本
 
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話心 谷本
 
日本で二番目に「細かい」JavaOne2011報告
日本で二番目に「細かい」JavaOne2011報告日本で二番目に「細かい」JavaOne2011報告
日本で二番目に「細かい」JavaOne2011報告心 谷本
 
[関ジャバ]Java News 2011 Mar
[関ジャバ]Java News 2011 Mar[関ジャバ]Java News 2011 Mar
[関ジャバ]Java News 2011 Mar心 谷本
 

More from 心 谷本 (10)

プレゼンの技術 2 実践編
プレゼンの技術 2 実践編プレゼンの技術 2 実践編
プレゼンの技術 2 実践編
 
プレゼンの技術 1 考え方
プレゼンの技術 1 考え方プレゼンの技術 1 考え方
プレゼンの技術 1 考え方
 
プレゼンの技術
プレゼンの技術プレゼンの技術
プレゼンの技術
 
from old java to java8 - KanJava Edition
from old java to java8 - KanJava Editionfrom old java to java8 - KanJava Edition
from old java to java8 - KanJava Edition
 
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
 
from old Java to modern Java
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java
 
日本一細かいJavaOne2011報告
日本一細かいJavaOne2011報告日本一細かいJavaOne2011報告
日本一細かいJavaOne2011報告
 
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
 
日本で二番目に「細かい」JavaOne2011報告
日本で二番目に「細かい」JavaOne2011報告日本で二番目に「細かい」JavaOne2011報告
日本で二番目に「細かい」JavaOne2011報告
 
[関ジャバ]Java News 2011 Mar
[関ジャバ]Java News 2011 Mar[関ジャバ]Java News 2011 Mar
[関ジャバ]Java News 2011 Mar
 

Recently uploaded

TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 

Recently uploaded (8)

TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 

Spring Bootをはじめる時にやるべき10のこと

  • 2. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 皆さん
 用意はいいですか? 2
  • 3. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 鈴木会長は
 こっちじゃないぞ? 3
  • 4. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. では、始めましょう! 4
  • 5. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 自己紹介 5 • 谷本 心 (Shin Tanimoto) - Acroquest Technology株式会社 - 開発&トラブルシュート教育 - JavaOneスピーカー - JJUG / 関ジャバ / S2JSFコミッタ - Twitter : @cero_t (日本語) - Facebook : shin.tanimoto (英語)
  • 6. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6 Struts + Hibernate Seasar2 + S2JSF + S2Dao Click + Guice + Mirage Spring MVC + Hibernate
  • 7. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. フレームワークに
 求めていること 7
  • 8. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 開発効率
 生産性 8
  • 9. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ではなくて 9
  • 10. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ハマらない
 ミスしない
 ミスをリカバリできる 10
  • 11. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ひとつハマれば
 3人日が奪われ 11
  • 12. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ひとつミスしていれば
 商用障害が起き 12
  • 13. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. リカバリできずに
 今日も徹夜 13
  • 14. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ハマらない
 ミスしない
 ミスをリカバリできる 14
  • 15. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. そのための
 Spring Boot 15
  • 17. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 17 #1
 SpringBootを知る
  • 18. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る Spring Bootとは 複雑化したSpringプロジェクト群を使った開発を シンプルに開始できる仕組み 18
  • 19. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 19 Springベースの
 フルスタック
 プラットフォーム
  • 20. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る フルスタックプラットフォーム View層、コンテナ層、データアクセス層
 監視、非同期メッセージング、クラウド対応など
 様々な機能を「Spring Boot」という共通の
 プラットフォーム上で利用できる。 20
  • 21. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る フルスタックプラットフォームでないと 自分で様々なフレームワークを組み合わせると
 もちろん自由に選べる反面、
 設定の記述や、動作検証などが必要になる。 ここに「ハマり」要因がある。 21
  • 22. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る あまり強調しない方が良いこと Microservices向けフレームワーク 別にそれが目的ではない Executable JAR ≠ Microservices XMLを書かない ymlや設定クラスを少し作る 22
  • 23. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 23 #1 Spring Bootなら
 組み合わせでハマらない!
  • 24. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 24 #2
 はじめての
 Spring Boot
  • 25. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 2. はじめてのSpring Boot 新しいプロダクトの利用時あるある ドキュメントがない。 ドキュメントが英語しかない。 ブログがない。ノウハウがない。 とりあえず少しずつググりながら
 場当たり対応で何とか凌ぐ。 そんなことをしているから「設計ミス」をする。 25
  • 26. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 2. はじめてのSpring Boot はじめてのSpring Boot 26 @makingの力作 Spring Bootを用いた
 開発、試験、デプロイなどを
 まるっと習得できる こっちの入門スライドもオススメ
 http://www.slideshare.net/ makingx/grails-30-spring-boot
  • 27. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 27 #2 はじめてのSpring Bootで
 初期学習を効率化!
  • 28. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 28 #3
 Spring Initializr
  • 29. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 3. Spring Initializr プロジェクト立ち上げ時あるある pom.xmlを書いて、必要な依存ライブラリを列挙する。 ・・・のは面倒だから、exampleプロジェクトを探して
 不要なソースコードを削除する。 なんか不要なJARが混入している なぜかバージョン違いのJARが混入する 頑張ってビルドファイルを書いたけど、なぜか動かない。 ここに「ミス」と「ハマり」要因がある。 29
  • 30. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 3. Spring Initializr Spring Initializrとは https://start.spring.io/ Spring Bootプロジェクトの雛形を作る Maven or Gradleのプロジェクト作成 利用するプロジェクトやライブラリを選択できる Web、JDBC、Security、AOP、
 JPA、Thymeleafなど つまずかずにスタートできる! 30
  • 31. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 3. Spring Initializr 使い方 https://start.spring.io/ に行く。 必要な情報と、利用するモジュールを選ぶ。 Actuatorおすすめ Generate Projectをクリック。 ダウンロードしたzipを解凍する。 IDEにインポートする。 以下のいずれかで実行する。 mainメソッドを実行する mvn spring-boot:run 31
  • 32. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 32 #3 Spring Initializrなら
 初期構築でミスしない!
  • 33. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 33 #4
 pom.xmlの設計
  • 34. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4. pom.xmlの設計 pom.xmlあるある 複数モジュールを作る時、依存JARのバージョンを
 複数のpom.xmlに重複して書いている。 そしてJARのバージョン違いが発生する 親子モジュールとか難しいから、
 単一モジュールで行くぜー! WebAPIとバッチがなぜか同じJARに入ってる 34
  • 35. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4. pom.xmlの設計 pom.xmlのグッドプラクティス デプロイ単位、ライフサイクル単位で分割する 共通部分を切り出す フレームワーク部分 自動生成したエンティティ しかしそうすると、前述したJARの
 バージョン違い問題が起きる・・・? 35
  • 36. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4. pom.xmlの設計 pom.xmlのグッドプラクティス 依存JARのバージョンは、親のpom.xmlに書く <dependencyManagement> を使ってバージョンを定義する Spring IO platformを使う http://platform.spring.io/platform/ 大げさな名前だが、ただのpom.xml Spring関連モジュールだけでなく、
 著名なプロダクトも含むバージョンを規定したpom.xml commons-lang、guice、joda-time、jruby、、、 Version1.1.4では552個のモジュールのバージョンが規定されている 36
  • 37. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 37 #4 Spring IO platformで
 pom.xmlをシンプルに!
  • 38. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 38 #5
 Controllerの共通設定
  • 39. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 突然ですが、
 JSR 310 Date and Time APIの
 LocalDateクラスってご存じですか? LocalDate : 日付のみ。時間なし。 LocalTime : 時間のみ。日付なし。 LocalDateTime : 日付も時間もあり。 39
  • 40. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 java.util.DateやCalendarはハマりやすい Dateを使って比較する際、日付だけで良いのに
 余計な時分秒が入っているせいで、判定を誤る。 Calendarで時分秒に0を指定したけど
 ミリ秒に余計な値が入っていて、判定を誤る。 SimpleDateFormatがスレッドセーフでないことを
 知らずに、商用環境で問題が起きる。 40
  • 41. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 JSR 310をSpring Bootでも使いたい できること yyyy-MM-dd形式の日付 JSONリクエスト → LocalDateフィールド できないこと yyyy/MM/dd形式の日付 LocalDateフィールド → JSONレスポンス 41
  • 42. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 ControllerでLocalDateを使う Controllerで利用するJacksonをカスタマイズする Controllerの引数・戻り値のオブジェクトと
 JSONリクエスト・レスポンスは、
 Jacksonでシリアライズ・デシリアライズされる。 Jackson2ObjectMapperBuilderを
 戻すメソッドに@Beanをつけることで
 カスタマイズできる。 42
  • 43. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 @Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { return Jackson2ObjectMapperBuilder.json() .indentOutput(true) .serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() { @Override public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(value.format(DATE_FORMATTER)); } }) .deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() { @Override public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return LocalDate.parse(jp.getValueAsString(), DATE_PARSER); } }) .modules(new JSR310Module()); } 43
  • 44. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 @Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { return Jackson2ObjectMapperBuilder.json() .indentOutput(true) .serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() { @Override public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(value.format(DATE_FORMATTER)); } }) .deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() { @Override public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return LocalDate.parse(jp.getValueAsString(), DATE_PARSER); } }) .modules(new JSR310Module()); } 44 出力するJSONを 読みやすく LocalDateの
 シリアライズと
 デシリアライズ 他のJSR 310クラスも
 使えるようにしておく
  • 45. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 /** 日付フォーマット */ protected static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); /** 日付パースフォーマット */ protected static final DateTimeFormatter DATE_PARSER = DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d"); 45
  • 46. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 /** 日付フォーマット */ protected static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); /** 日付パースフォーマット */ protected static final DateTimeFormatter DATE_PARSER = DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d"); 入力は柔軟に、出力は厳格に。 46 フォーマット時は
 0埋め、
 ハイフン区切り パース時は
 0埋め、区切りを
 少し自由に
  • 47. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 47 #5 ControllerでLocalDateを
 使って日付判定ミスを防ぐ!
  • 48. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 48 #6
 トランザクション
 境界の設定
  • 49. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 トランザクションあるある Controllerをトランザクション境界にする 処理の途中で一度コミットしたいけどできない 非同期処理呼び出しの前にコミットとか 途中でコミットできるような仕組みを
 無理に作ったら全体的な整合性が崩れた 性能改善のためのリードレプリカを作りたいが、
 そもそもアクセスを振り分けられない 49
  • 50. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 Service層をトランザクション境界にする Controllerの次の層をトランザクション境界にする 処理の単位が明確になる Service層からreturnすればコミット、
 例外で戻ればロールバック。 Service層のクラスすべてに
 @Transactionalアノテーションをつける 50
  • 51. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 原則、Read Onlyトランザクションを使う Service層のクラスすべてに
 @Transactional(readOnly = true) をつける Insert / Update / Deleteが発生する時だけ
 メソッドに @Transactional(readOnly = false) を
 つける ReadOnlyトランザクションだけを
 リードレプリカに振り分ける 51
  • 52. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 @Service @Transactional(readOnly = true) public class EmployeeService { @Autowired protected EmployeeDao employeeDao; public Employee getEmployee(Integer id) { return employeeDao.selectById(id); } @Transactional(readOnly = false) public int createEmployee(Employee employee) { return employeeDao.insert(employee); } } 52
  • 53. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 @Service @Transactional(readOnly = true) public class EmployeeService { @Autowired protected EmployeeDao employeeDao; public Employee getEmployee(Integer id) { return employeeDao.selectById(id); } @Transactional(readOnly = false) public int createEmployee(Employee employee) { return employeeDao.insert(employee); } } 53 クラスには
 readOnly = true 更新系メソッドに
 readOnly = false
  • 54. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 54 #6 ServiceクラスにRead Onlyな
 トランザクションを設けて
 将来に備える!
  • 55. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 55 #7
 O/Rマッパーの選択
  • 56. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 O/Rマッパーあるある とりあえずHibernate 思ったのと違うSQLが発行された 1リクエストでSQLが1万回発行された selectしたタイミングで一意制約違反が出た キャッシュが想定外の動きをした。 要するにハマる 56
  • 57. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 O/Rマッパーあるある じゃぁMyBatis Spring Bootで標準対応していない 1.3で標準対応されるかも https://github.com/spring-projects/spring-boot/pull/3692 SQLを書いたXMLをフォーマットしたら
 インデントが全部消えた > とか < のエスケープ 57
  • 58. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 O/Rマッパーあるある じゃぁJdbcTemplate なんかAPIが古くさい(Spring 2.0時代のAPI) publicフィールドが使えない JSR 310に対応していない 58
  • 59. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 59 そこで
 Bootiful SQL Template
  • 60. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 Bootiful SQL Template JdbcTemplate / NamedParameterJdbcTemplateの
 独自ラッパー SQLファイルを書ける(FreeMarker形式も可) モダンなAPI publicフィールドが使える JSR 310に対応(ZonedDateTimeにも) https://github.com/cero-t/sqltemplate 60
  • 61. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 @Autowired protected SqlTemplate sqlTemplate; public List<Employee> selectByCondition(EmployeeCondition condition) { return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql", Employee.class, condition); } 61
  • 62. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 @Autowired protected SqlTemplate sqlTemplate; public List<Employee> selectByCondition(EmployeeCondition condition) { return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql", Employee.class, condition); } 62 モダンでサクっと
 使えるAPI IntelliJなら
 Command(Ctrl) + クリックで
 SQLファイルにジャンプ
  • 63. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 SELECT * FROM emp WHERE 1 = 1 <#if name??> AND ename like '%' || :name || '%' </#if> <#if hiredateFrom??> AND :hiredateFrom < hiredate </#if> <#if hiredateTo??> AND hiredate < :hiredateTo </#if> <#if deptno??> AND deptno = :deptno </#if> 63
  • 64. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 SELECT * FROM emp WHERE 1 = 1 <#if name??> AND ename like '%' || :name || '%' </#if> <#if hiredateFrom??> AND :hiredateFrom < hiredate </#if> <#if hiredateTo??> AND hiredate < :hiredateTo </#if> <#if deptno??> AND deptno = :deptno </#if> 64 FreeMarker形式の
 テンプレートが利用可能
 
 ANDを自動的に消す機能が
 なくてごめんな
  • 65. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 65 #7 Bootiful SQL Templateで
 SQLを書いてハマり知らず
  • 66. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 66 #8
 例外処理の共通化
  • 67. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 例外処理あるある 個別の開発者任せ もちろん死ぬ フレームワークが返す例外(バリデーションなど)と、
 アプリケーションが返す例外でJSONの形式が違う クライアント側で判別に失敗して死ぬ 個別のエラーコードを定義しておいたので
 全部ソースコード内に書く 守らない人がいて死ぬ 67
  • 68. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 例外処理は共通化する ApplicationException extends RuntimeExceptionを 作って必ずこれを使う エラー種別をenumに定義しておき、
 ApplicationExceptionのコンストラクタの
 第一引数に必ず渡す エラー種別と、HTTPステータスやエラーコード、
 エラーメッセージを紐付けて管理する 68
  • 69. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public class ApplicationException extends RuntimeException { Throwable cause; Object[] args; private HttpErrors error; public AppException(HttpErrors error, Throwable cause, String... args) { super(); this.error = error; this.args = args; this.cause = cause; } // その他のコンストラクタ、cause、args、errorのgetterは割愛 public String getMessage() { if (args != null) { return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args); } return "[" + error.name() + "]" + error.getMessage(); } } 69
  • 70. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public class ApplicationException extends RuntimeException { Throwable cause; Object[] args; private HttpErrors error; public AppException(HttpErrors error, Throwable cause, String... args) { super(); this.error = error; this.args = args; this.cause = cause; } // その他のコンストラクタ、cause、args、errorのgetterは割愛 public String getMessage() { if (args != null) { return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args); } return "[" + error.name() + "]" + error.getMessage(); } } 70 第一引数で
 エラー種別を受け取る
  • 71. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public interface HttpErrors { /** * HTTPステータスを取得します。 * @return HTTPステータス */ HttpStatus getStatus(); /** * メッセージを取得します。 * @return メッセージ */ String getMessage(); /** * エラー名を取得します。 * @return エラー名 */ String name(); } 71
  • 72. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public enum Errors implements HttpErrors { USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"), UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}"); protected HttpStatus status; protected String message; Errors(HttpStatus status, String message) { this.status = status; this.message = message; } @Override public HttpStatus getStatus() { return status; } @Override public String getMessage() { return message; } } 72
  • 73. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public enum Errors implements HttpErrors { USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"), UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}"); protected HttpStatus status; protected String message; Errors(HttpStatus status, String message) { this.status = status; this.message = message; } @Override public HttpStatus getStatus() { return status; } @Override public String getMessage() { return message; } } 73 エラーを列挙
  • 74. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 例外処理ハンドリングも共通化する ApplicationExceptionと
 RuntimeExceptionと
 フレームワークが返す例外で
 すべて同じ例外ハンドリングをする 74
  • 75. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @ControllerAdvice public class ControllerExceptionHandler extends ResponseEntityExceptionHandler { /** ロガー */ protected final Log logger = LogFactory.getLog(getClass()); @ExceptionHandler(value = ApplicationException.class) @ResponseBody public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) { return handleError(request, ex.getError(), ex, ex.getArgs()); } @ExceptionHandler(value = RuntimeException.class) @ResponseBody public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) { return handleError(request, Errors.UNEXPECTED, ex, ex.toString()); } 75
  • 76. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @ControllerAdvice public class ControllerExceptionHandler extends ResponseEntityExceptionHandler { /** ロガー */ protected final Log logger = LogFactory.getLog(getClass()); @ExceptionHandler(value = ApplicationException.class) @ResponseBody public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) { return handleError(request, ex.getError(), ex, ex.getArgs()); } @ExceptionHandler(value = RuntimeException.class) @ResponseBody public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) { return handleError(request, Errors.UNEXPECTED, ex, ex.toString()); } 76 独自のApplicationExceptionと
 想定しないRuntimeExceptionの両方を
 同じ方式でハンドリング
  • 77. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex, Object... args) { String message = MessageFormat.format(error.getMessage(), args); if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) { logger.error(message, ex); } else { logger.debug(message, ex); } if (error.getStatus() == HttpStatus.UNAUTHORIZED) { return new ResponseEntity<>(error.getStatus()); } RestError restError = new RestError(); restError.path = request.getRequestURI(); restError.error = error.name(); restError.status = error.getStatus() .value(); restError.message = message; restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, error.getStatus()); } 77
  • 78. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex, Object... args) { String message = MessageFormat.format(error.getMessage(), args); if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) { logger.error(message, ex); } else { logger.debug(message, ex); } if (error.getStatus() == HttpStatus.UNAUTHORIZED) { return new ResponseEntity<>(error.getStatus()); } RestError restError = new RestError(); restError.path = request.getRequestURI(); restError.error = error.name(); restError.status = error.getStatus() .value(); restError.message = message; restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, error.getStatus()); } 78 例外オブジェクトへの変換
  • 79. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @Override protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { RestError restError = new RestError(); if (request instanceof ServletWebRequest) { restError.path = ((ServletWebRequest) request).getRequest() .getRequestURI(); } else { restError.path = request.getContextPath(); } restError.error = status.getReasonPhrase(); restError.status = status.value(); restError.message = ex.getMessage(); restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, status); } } 79
  • 80. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @Override protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { RestError restError = new RestError(); if (request instanceof ServletWebRequest) { restError.path = ((ServletWebRequest) request).getRequest() .getRequestURI(); } else { restError.path = request.getContextPath(); } restError.error = status.getReasonPhrase(); restError.status = status.value(); restError.message = ex.getMessage(); restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, status); } } 80 このオーバーライドで
 Spring MVCが投げる例外を
 ハンドリングできる
  • 81. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 81 #8 すべての例外を共通して
 ハンドリングせよ!
  • 82. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 82 #9
 AOPによるロギング
  • 83. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9. AOPによるロギング AOPとは アプリケーション横断的に行う処理 トランザクションのコミットやロールバックもAOPで実現されている オススメは、AOPによる自動ロギング Controller / Service / DaoのIn/Outでロギング デバッグ時に、アプリケーションの挙動がとてもよく分かる ログレベルに応じて引数、戻り値なども出す SpringではXMLやアノテーションでAOPの対象を記述することができる 正直、アノテーションの記述はイマイチ。分かりづらい。 記述性はGuice > Seasar > Spring。 83
  • 84. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9. AOPによるロギング @Aspect @Component public class DumpLogInterceptor { protected Logger logger = LoggerFactory.getLogger(getClass()); @Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))") public Object dump(ProceedingJoinPoint joinPoint) throws Throwable { try { logger.debug("BEGIN - " + toCall(joinPoint)); logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE)); Object retValue = joinPoint.proceed(joinPoint.getArgs()); logger.debug("END - " + toCall(joinPoint)); logger.trace( "with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE)); return retValue; } catch (Throwable th) { logger.debug("END throw - " + toCall(joinPoint)); logger.debug("Exception: " + th); throw th; } } } 84
  • 85. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9. AOPによるロギング @Aspect @Component public class DumpLogInterceptor { protected Logger logger = LoggerFactory.getLogger(getClass()); @Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))") public Object dump(ProceedingJoinPoint joinPoint) throws Throwable { try { logger.debug("BEGIN - " + toCall(joinPoint)); logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE)); Object retValue = joinPoint.proceed(joinPoint.getArgs()); logger.debug("END - " + toCall(joinPoint)); logger.trace( "with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE)); return retValue; } catch (Throwable th) { logger.debug("END throw - " + toCall(joinPoint)); logger.debug("Exception: " + th); throw th; } } } 85 この記述でController / Service
 Daoの実行前後に処理を差し込む
  • 86. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 86 #9 AOPによるロギングで
 問題発生時のリカバリを
 高速化しよう
  • 87. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 87 #10
 テスト設計
  • 88. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストあるある とりあえず、手動でテストしようぜ!
  → 回帰試験で死ぬ。 ロジックがあるControllerからテストすればOK!
  → バリデーションの設定ミスで死ぬ。 通常使うComponentとモックのComponentは
 @Profileで切り替えるのがSpring流!
  → 管理できなくなってきて死ぬ。 Spring Bootはend-to-endでテストしやすいから
 end-to-endのテストでカバレッジ80%を目指そう!
  → そして死ぬ。 88
  • 89. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのグッドプラクティス Controller以降をJUnitでテストする。 カバレッジは最低60%、できれば80%を目指す。 外部サービス呼び出し部分は、モック化する(後述) 例外を任意で発生させたい場合も、モック化すると良い。 無名クラスを活用したモックを作れるようになろう。 end-to-endのJUnitを書いて、
 正常系1本とバリデーション部分をテストする。 JUnitのテストクラスに @IntegrationTest(“server.port=0”) をつけ、 RestTemplateを用いてテストする。 バリデーションの試験は、end-to-endでしかできない。 89
  • 90. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 90
  • 91. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 91 テストの時に必ずつけるアノテーション。 トランザクションを有効にして
 試験が終わったら自動でロールバック。 TestContextConfigはあとで。
  • 92. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @WebAppConfiguration @IntegrationTest("server.port=0") @Transactional public class EmployeesTest { @Value("http://localhost:${local.server.port}/employees") String baseUrl; @Autowired RestTemplate restTemplate; @Test public void testGetList() { ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class); // TODO: assert } 92
  • 93. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @WebAppConfiguration @IntegrationTest("server.port=0") @Transactional public class EmployeesTest { @Value("http://localhost:${local.server.port}/employees") String baseUrl; @Autowired RestTemplate restTemplate; @Test public void testGetList() { ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class); // TODO: assert } 93 @WebAppConfigurationと
 @IntegrationTestをつけて
 Tomcatを起動 RestTemplateでアクセス URLを設定
  • 94. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのTips schema.sqlとdata.sqlでデータ投入する /src/test/resources にschema.sqlとdata.sqlを
 置いておけば、JUnitの起動前にのみ実行される。 /src/main/resources に置いておけば
 通常起動時に実行される(動作確認向け) 事故ってproduction環境で動かさないように! Controllerのテストと、end-to-endのテストは同じapplication.ymlでテストする end-to-endの試験も自動化するため。 end-to-endのテストは、ついつい範囲を広げたくなるが
 自動化する試験と、そうでない試験は分けるべき。 94
  • 95. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのTips @Componentのモックは、
 @Profileよりも@Primaryをつけた方が良い 外部サービスの呼び出しなどをモック化する場合、
 モック化したい部分を @Autowired にしておく。 モッククラスを /src/test/java 以下で作成し、
 @Component (@Bean) と@Primaryアノテーションを
 つければ、JUnit実行時のみ利用される。 95
  • 96. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 public interface Context { /** * セッションIDを取得します。 * @return セッションID */ String getSessionId(); } 96 本体コード側にある
 インタフェース。
  • 97. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 public class RequestContext implements Context { protected HttpServletRequest request; public RequestContext(HttpServletRequest request) { this.request = request; } @Override public String getSessionId() { return request.getSession().getId(); } } 97 本体コード側にある実装。
 HttpServletRequestを使っているので
 JUnit時にはエラーが起きる
  • 98. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @Configuration public class TestContextConfig { @Bean @Primary public Context context() { return new Context() { @Override public String getSessionId() { return "JUNIT"; } }; } } 98
  • 99. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @Configuration public class TestContextConfig { @Bean @Primary public Context context() { return new Context() { @Override public String getSessionId() { return "JUNIT"; } }; } } 99 テスト側の設定クラス。 ここに@Primaryを書けば
 このコンポーネントが
 優先して使われる。
  • 100. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 100
  • 101. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 101 テスト側で、先ほど書いた
 Configurationを明示的に読み込む
  • 102. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのTips /src/test/java 側に作ったテスト用の
 @Primary つき@Component (@Bean) は
 end-to-endのサーバ側にも適用されるので
 サーバ側でもモックを使いやすい たぶんこれ相当便利。 102
  • 103. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 103 まとめ
  • 104. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 104 スライド読み直せ!
  • 105. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 105 One more thing…
  • 106. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 106 今日紹介したソースは
 GitHubで公開中!
  • 107. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 107 https://github.com/cero-t/ spring-boot-kinoko-2015
  • 108. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 108 Enjoy Spring Boot!