Spring Bootでgroovyを使う

# はじめに
Spring Bootでgroovyを使うときのGradleの設定を紹介します。

# 手順

まず[Spring BootをHerokuにデプロイするのが劇的に簡単になっている件](http://qiita.com/gosshys/items/6d409a245a108ad25202)で紹介した、SpringInitializrを使ったプロジェクトを流用します。

- build.gradleに以下を設定
  - pluginにgroovyを追加する
  - dependenciesにgroovy-allを追加する
- groovyのパッケージを作成
- groovyのクラスを作成
- 起動確認

# build.gradleの内容

auto importをONにしていない場合は、build.gradleファイルを修正した後に、refreshしないと追加したパッケージが読み込まれません。

```
buildscript {
	ext {
		springBootVersion = '1.4.2.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

apply plugin: 'java'
apply plugin: 'groovy' // ココを追加
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

jar {
	baseName = 'demo'
	version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
	mavenCentral()
}


dependencies {
	compile('org.codehaus.groovy:groovy-all') // ココを追加
	compile('org.springframework.boot:spring-boot-starter-actuator')
	compile('org.springframework.boot:spring-boot-starter-web')
	runtime('org.postgresql:postgresql')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}
```

## groovyのパッケージを作成

### Projectペインのmainフォルダを右クリックして、「New」->「Directory」を選択
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/6ccb79c7-a4f2-fdb8-4e30-085402cb40ef.png)
### 「New Directory」ダイアログに`groovy`と入力
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/64cdf85a-4d04-e6de-f437-58c833472460.png)
### 作成した`groovy`フォルダを右クリックして、「Mark Directory as」メニューから「Sources Root」を選択
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/4b75ba49-7d75-cf22-4b20-d5a201bd2f15.png)
`groovy`フォルダが青色に変わる
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/dfa0c6c0-0a2e-a8b6-e8cc-c99ddc8a45bb.png)
### `groovy`フォルダを右クリックして、「New」->「package」
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/c0be6fb5-2cbe-09e6-0f64-6da20bc0dbf3.png)
### 「New Package」ダイアログに`com.example.controller`を入力
※パッケージ名はなんでもよいがSpringBootのmainクラスと同階層、または配下の階層を作成する。(ComponentScanの対象にするため)
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/f89b751b-e8f1-2b7c-eca7-1572a52626b8.png)
### 作成したパッケージを右クリックして、「New」->「Groovy Class」を選択
※この時点でこの「Groovy Class」の選択肢がでてこない場合は、build.gradleの設定ミスか、build.gradleを更新していない可能性があります。
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/0016aa12-3d39-6352-e45e-af92b1190293.png)
### 「New Groovy Class」ダイアログに適当なクラス名を追加
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/16d81a77-1315-2445-adf7-aaf8d710e7e0.png)
Groovyのクラスが作成される
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/b9edbfe6-8d6b-3cf7-c12a-aac41257e645.png)

### 作成したGroovyクラスを以下のとおり編集する（クラス名は変えない）

```
package com.example.controller

import org.springframework.stereotype.Component
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.ResponseBody

/**
 *
 */
@Component
@RequestMapping("/demo")
class DemoController {
  @GetMapping("hello")
  @ResponseBody
  def hello() {
    return "Hello"
  }
}
```

### JavaのほうのSpringBootのmainクラスを右クリックして、「Run DemoApplication」を選択
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/a2471a6e-aae7-6280-2bb6-79c78045ad58.png)

コンソールに起動ログが表示される

```
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.2.RELEASE)

2016-11-19 23:43:43.459  INFO 29071 --- [           main] com.example.DemoApplication              : Starting DemoApplication on MBP-15UAC-184.local with PID 29071 (/Users/tgoto/Develop/git/demo/build/classes/main started by tgoto in /Users/tgoto/Develop/git/demo)
2016-11-19 23:43:43.463  INFO 29071 --- [           main] com.example.DemoApplication              : No active profile set, falling back to default profiles: default
2016-11-19 23:43:43.900  INFO 29071 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7722c3c3: startup date [Sat Nov 19 23:43:43 JST 2016]; root of context hierarchy
2016-11-19 23:43:45.222  INFO 29071 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-11-19 23:43:45.235  INFO 29071 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-11-19 23:43:45.236  INFO 29071 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.6
2016-11-19 23:43:45.339  INFO 29071 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-11-19 23:43:45.339  INFO 29071 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1441 ms
2016-11-19 23:43:45.565  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2016-11-19 23:43:45.570  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'metricsFilter' to: [/*]
2016-11-19 23:43:45.570  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-11-19 23:43:45.570  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-11-19 23:43:45.570  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-11-19 23:43:45.570  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2016-11-19 23:43:45.570  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'webRequestLoggingFilter' to: [/*]
2016-11-19 23:43:45.570  INFO 29071 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'applicationContextIdFilter' to: [/*]
2016-11-19 23:43:45.891  INFO 29071 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7722c3c3: startup date [Sat Nov 19 23:43:43 JST 2016]; root of context hierarchy
2016-11-19 23:43:45.956  INFO 29071 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/demo/hello],methods=[GET]}" onto public java.lang.Object com.example.controller.DemoController.hello()
2016-11-19 23:43:45.958  INFO 29071 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
・・・中略・・・
org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19 23:43:46.827  INFO 29071 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-11-19 23:43:46.835  INFO 29071 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
2016-11-19 23:43:46.940  INFO 29071 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-11-19 23:43:46.944  INFO 29071 --- [           main] com.example.DemoApplication              : Started DemoApplication in 4.224 seconds (JVM running for 4.732)
```

以下のような`/demo/hello`のリクエストマップが表示されるとOK

```
2016-11-19 23:43:45.956  INFO 29071 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/demo/hello],methods=[GET]}" onto public java.lang.Object com.example.controller.DemoController.hello()
```

### curlで確認

```
~/D/g/demo ❯❯❯ curl -X GET localhost:8080/demo/hello                                                                                                                                    [master]
Hello%                                                                                                                                                                                           ~/D/g/demo ❯❯❯    
```

できた