spring-boot-devtoolsで開発効率上げようぜ、的な。 (Spring Boot 1.3)

# はじめに

Spring Boot 1.3で、`spring-boot-devtools`という開発補助モジュールが導入されるということで、
その概説([DevTools in Spring Boot 1.3](https://spring.io/blog/2015/06/17/devtools-in-spring-boot-1-3))の雑な訳と所感を書いてみました。
(一部、執筆時のReference Guideの記載に合わせて補足をしています)


# DevTools in Spring Boot 1.3
Spring Boot 1.3では、`spring-boot-devtools`っていう開発作業に便利なモジュールが使えるようになるよ！
使うためには、dependency追加してね。

```xml:pom.xml
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>
```

```:build.gradle
dependencies {
    compile("org.springframework.boot:spring-boot-devtools")
}
```

## ちょっとした前置き
以下、「開発段階では自動で○○するようになる」という記述がありますが、"開発段階 ≠ Production"の判断はアプリケーションの起動方法によって自動で判別されます。
具体的には、`java -jar`での起動であったり、他の特別なクラスローダを使用した場合には"Production"として扱われます。

## Property Defaults
Spring Boot 1.2でThymeleaf使ってるとき、`spring.thymeleaf.cache`の設定でテンプレートのキャッシュをoffにできるのはご存知の通り。
この設定はお手軽だけど、開発中に「cacheがon/offどっちか」を常に気にしてないのはメンドイよね。
というわけで、__開発段階ではテンプレートエンジン([Thymeleaf](http://www.thymeleaf.org/)、[Freemarker](http://freemarker.org/)、[Groovy Templates](http://docs.groovy-lang.org/docs/next/html/documentation/template-engines.html)、[Velocity](https://velocity.apache.org/engine/releases/velocity-1.5/user-guide.html)、あと[Mustache](https://mustache.github.io/))のcacheをデフォルトでoff__にするようにしたよ。


## Automatic Restart
[JRebel](http://zeroturnaround.com/software/jrebel/)や[Spring Loaded](https://github.com/spring-projects/spring-loaded)使ってる人は知ってると思うけど、自動リロード便利だよね。
でもこの辺のツール使おうと思うとIDEの設定いじったりしなきゃいけないし、ものによってはお金かかる！

それらの"instant reload"技術よりはちょっと遅いけど、似たようなことできるようにしたよ。
`spring-boot-devtools`をincludeしていたら、classpathで捕捉してるすべてのファイルを対象として、
__ファイルに変更があったら、アプリケーションを自動で再起動する__ようになるよ。

#### __補足__
デフォルトでは、Thymeleafのテンプレートやcss、jsなどのリコンパイル不要なstaticファイルなどが変更されても、Automatic Restartは実行されません。(そもそも再起動が不要だから)
ただし、次に記述するLiveReloadのトリガにはなります。
Automatic Restartのトリガ対象から外すためには、下記のプロパティが利用可能です。

- `spring.devtools.restart.exclude`
    - デフォルトの例外対象を無視して、完全に例外を指定しなおす場合に利用
        - e.g. `spring.devtools.restart.exclude=static/**,public/**`
- `spring.devtools.restart.additional-exclude`
    - デフォルトの例外対象(`/resource`や`/static`など)はそのままに、例外対象を追加する場合に利用

同じように、classpath外のファイルをAutomatic Restartの対象にしたい場合、`spring.devtools.restart.additional-paths`プロパティで指定が可能です。

## LiveReload
"cache properties"や"automatic restarts"の動作を画面に反映させるためには、ブラウザで更新ボタンをクリックする必要があって、面倒だよね。
`LiveReload`機能を使うと、ブラウザの更新を行うための通知を自動でしてくれるので、__アプリが再起動した直後にブラウザが自動更新される__ようになるよ！
そのためのBrowser Extensionは無料でインストールできるから、[livereload.com](http://livereload.com/extensions/)からGetしてね。
(Chrome、Firefox、Safariが対応してる)

#### __補足__
LiveReloadの機能は1アプリケーションに対してのみ有効です。
例えば複数のアプリケーションを起動している場合、最初に起動した1つのみがLiveReloadの対象になります。

## Remote Debug Tunneling
[Docker](http://docker.io/)や[Lattice](http://lattice.cf/)を使ったことがあると分かると思うけど、デバッグするのが凄く面倒だよね。
リモートデバッグするために、`-Xdebug`オプションつけて適切なportにフォワーディングして･･･っていう設定もやらなくちゃいけないし。

Spring Boot 1.3では、JDWP(the Java Debug Wire Protocol)を使って、
__「サーバ側では80と443portだけ空いてる」状態でも、シンプルな設定でリモートデバッグができるようになる__よ。

## Remote Update and Restart
リモートデバッグだけじゃなくて、リモートで動いているアプリの更新・再起動もできるよ！
つまり、__ローカルでファイルを変更したら、それがリモートサーバのアプリに反映される__ってこと。

#### __補足__
この機能はデフォルトでは無効になっています。
利用するためには、`spring.devtools.remote.secret`をsetする必要があります。

例えば、`my-app`というサービスをCloud Foundlyの`https://myapp.cfapps.io`に対してデプロイしている場合の設定手順は以下のようになります。

1. my-appのapplication.propertiesに`spring.devtools.remote.secret`をセットしたものをデプロイ。
    - (LocalとRemoteのマッチングのために利用されるだけなので、値は何でもOK。)
2. IDEのRun Configurationで、main classに`org.springframework.boot.devtools.RemoteSpringApplication`を指定
3. `Program arguments`に`https://myapp.cfapps.io`を指定

この設定で起動した場合、以下のようなコンソール出力となります。

```
  .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote :: 1.3.0.BUILD-SNAPSHOT

2015-06-10 18:25:06.632  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-boot-samples/spring-boot-sample-devtools)
2015-06-10 18:25:06.671  INFO 14938 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043  WARN 14938 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074  INFO 14938 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2015-06-10 18:25:07.130  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)
```


## Video Preview
詳しいことは[reference guide](http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-devtools)読んでね。
あと、videoも用意したよ。
[DevTools in Spring Boot 1.3(Demo)](https://www.youtube.com/watch?v=A70NMxV13TI)

# 所感
__Remote Update and Restart__が超強力。
これによって、

コード書く→コンパイルする→デプロイ(ファイルを配置して起動)する→ブラウザで更新する

って作業が、

__コード書く→ブラウザに自動で反映される__

だけになって、コーディング"だけ"してりゃいいって状態に持っていけそうです。


# 参考文献
[Getting Started with Spring Boot 1.3 & DevTools](https://blog.ik.am/#/entries/349)
[Spring Boot 1.3 News #渋谷Java](http://www.slideshare.net/makingx/spring-boot-13-news-java)