Cloud9 + Gradle + GroovyでSpring Bootアプリケーションをビルドするまで

## はじめに
[前回](https://qiita.com/pideoh/items/f9a4883cd46eb2b07f07)はIDE環境のセットアップを行いました。
今回はセットアップした環境を用いて、Spring BootアプリケーションをGradle + Kotlinで動かすところまでをやってみます。

[Spring Bootのドキュメント](https://guides.gradle.org/building-spring-boot-2-projects-with-gradle/)を参考に実施し、ライブラリ類は最新バージョンを使ってみます。

なお、実行環境は以下の通りです。

```bash
$ gradle -v

------------------------------------------------------------
Gradle 6.0.1
------------------------------------------------------------

Build time:   2019-11-18 20:25:01 UTC
Revision:     fad121066a68c4701acd362daf4287a7c309a0f5

Kotlin:       1.3.50
Groovy:       2.5.8
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          11.0.3 (Amazon.com Inc. 11.0.3+7-LTS)
OS:           Linux 4.14.152-98.182.amzn1.x86_64 amd64
```


## 1. Gradleプロジェクトの作成
まずは、プロジェクトのディレクトリに移動し、
以下のコマンドを実行します。

今回はビルドスクリプトのDSLはGroovy、テストフレームワークは任意で作っていきます。

```bash
$ gradle init  --type java-application

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4] 1

Project name (default: test-app): test-app
Source package (default: test.app): test 

> Task :init
Get more help with your project: https://docs.gradle.org/6.0.1/userguide/tutorial_java_projects.html

BUILD SUCCESSFUL in 4m 9s
2 actionable tasks: 2 executed
```

## 2. build.gradleの編集
ガイドに従って書き換えます。
build scanは使わないので、不要なものは削除します。

- Plugin 

```groovy
plugins {
    // Apply the java plugin to add support for Java
    id 'java'
    id 'org.springframework.boot' version '2.2.2.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
}
````

- Dependencies

```groovy
dependencies {
    // This dependency is used by the application.
    implementation 'org.springframework.boot:spring-boot-dependencies:2.2.2.RELEASE'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    
    // Use JUnit test framework
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    components {
        withModule('org.springframework:spring-beans') {
            allVariants {
                withDependencyConstraints {
                    // Need to patch constraints because snakeyaml is an optional dependency
                    it.findAll { it.name == 'snakeyaml' }.each { it.version { strictly '1.19' } }
                }
            }
        }
    }
}
```

- application
不要なため、削除します。
 
- bootJar
最終行に追加します。

```groovy
bootJar {
    mainClassName = 'test.App'
}
```

## 3. Spring Bootアプリケーションへの書き換え
- App.java

```java
package test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}
```


- HelloGradleController.java

```java
package test;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController("/")
public class HelloGradleController {

    @GetMapping
    public String helloGradle() {
        return "Hello Gradle!";
    }

}
```

- AppTest.java

```java
package test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
@AutoConfigureMockMvc
public class AppTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void helloGradle() throws Exception {
        mvc.perform(get("/"))
            .andExpect(status().isOk())
            .andExpect(content().string("Hello Gradle!"));
    }

}
```

## 4. アプリケーションのビルド
以下のコマンドでビルドします。依存関係のあるライブラリが集まってくるまでに少し時間がかかります。

```bash
$ ./gradlew bootJar
```

## 5. アプリケーションの起動・動作確認
`$ gradlew boorRun`で起動するとアプリケーションが起動します。

```bash
$ ./gradlew bootRun

> Task :bootRun

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)
～
```


この状態で別のターミナルを開いて`localhost:8080`にアクセスすると、
`HelloGradleController.java`に定義したメソッドが呼び出されました！

```bash
$ curl http://localhost:8080
Hello Gradle!
```

## 最後に
本記事では、Cloud9環境でGroovyを使いSpring Bootまで動作させることを試しました。
書いてる途中に気づきましたが、自分で書くくらいなら、[Spring Initializr](https://start.spring.io/)を使ったほうが簡単でしたね。。
Cloud9でSpring Tool Suiteが使えるとももっと簡単になるのですが、、、今後の発展を祈るばかりです。