Dropwizardで簡単なWebアプリケーションを作成する

# Dropwizardで簡単なWebアプリケーションを作成する

## 今回の目標
- 単純なWebアプリを作成する
 - 画面より入力を行なったら入力内容を返してくれる

## 開発環境
- OS：Windows7
- 言語：Java8
- フレームワーク：Dropwizard9.2
- IDE：Eclipse 4.4.2

## 今回実装したファイル
1. DropTestApplication.java
2. DropTestConfiguration.java
3. SampleResource.java
4. index.html
5. index.js
6. config.yml
7. pom.xml

## 実行手順
1. mavenプロジェクト作成
2. 設定ファイル作成
    1. pom.xml作成
    2. config.yml作成
3. Dropwizardの中核クラス作成
    1. Configurationクラス作成
    2. Applicationクラス作成
4. サーバー側受け口作成
    1. SampleResource.java作成
5. 画面作成
    1. index.html作成
    2. index.js作成
6. ビルド
7. 実行

### 1. mavenプロジェクト作成
eclipseを利用し、プロジェクトエクスプローラー内で右クリック→新規→プロジェジェクトをクリック
Maven→Mavenプロジェクト→次へをクリック
今回はシンプルなプロジェクトの作成にチェックを入れ次へをクリック
任意のグループId(組織のID),アーティファクトId(識別ID。プロジェクト名になります)をいれ、パッケージングがjarになっていることを確認し、完了をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/139291/36a973b0-d473-87d1-bd39-ab4d88f7a34f.png)

eclipseの設定にもよりますが、下記のようなパッケージ構成ができあがります

![image.png](https://qiita-image-store.s3.amazonaws.com/0/139291/57d75582-b842-90ac-0895-ab34d4808744.png)

### 2.設定ファイル作成
ここでは、mavenにて利用するパッケージの指定をpom.xmlで行い、アプリの設定をconfig.ymlで行います

#### 2-1. pom.xml作成
プロジェクト直下に作成されているpom.xmlを選択し編集していきます。
ここでdropwizardを利用すること記載する必要があり、今回は必要なライブラリの指定とメインクラスの指定、ビルド時のfat-jar化を想定した`maven-shade`の指定を行っておきます。

```xml:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>priv.jp.y.suzuki</groupId>
  <artifactId>dropTest</artifactId>
  <version>0.0.1-SNAPSHOT</version>

<properties>
    <dropwizard.version>0.9.2</dropwizard.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>


  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <createDependencyReducedPom>true</createDependencyReducedPom>
          <filters>
            <filter>
              <artifact>*:*</artifact>
              <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
              </excludes>
            </filter>
          </filters>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer
                  implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                <transformer
                  implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>dropTest.priv.jp.y.suzuki.DropTestApplication</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>io.dropwizard</groupId>
      <artifactId>dropwizard-core</artifactId>
      <version>${dropwizard.version}</version>
    </dependency>
    <dependency>
      <groupId>io.dropwizard</groupId>
      <artifactId>dropwizard-auth</artifactId>
      <version>${dropwizard.version}</version>
    </dependency>
    <dependency>
      <groupId>io.dropwizard</groupId>
      <artifactId>dropwizard-assets</artifactId>
      <version>${dropwizard.version}</version>
    </dependency>
  </dependencies>
</project>
```

#### 2-2. config.yml作成
アプリで利用する設定を記載します。
今回は、プロジェクトのルート直下(pom.xmlと同じ位置)にymlファイル(名称は任意)を作成し、
アプリ起動時のポートの指定とルートパスの設定を行っておきます。
下記設定では`8090`ポートでアプリが立ち上がり、ルートパスに`/api/`を設定しています。

```yaml:config.yml
# Application server setting.
server:
  applicationConnectors:
    - type: http
      port: 8090

  rootPath: '/api/*'
```

### 3. Dropwizardの中核クラス作成
Dropwizardにて必要なファイル群を作成していきます。
今回は`src/main/java`以下に`dropTest.priv.jp.y.suzuki`というパッケージを作成してその下に中核クラスを作成しています。

#### 3-1. Configurationクラス作成
ここでは、環境毎のパラメータを設定します。
前手順にて記載したyamlファイルの情報がこのクラスにロードされます。
例えば先ほどのyamlファイルに下記のような設定(記載)をしておいたとします。

```yaml:config.yml
～中略～

# template sentence
template: Hello!!
```

そして下記のようにConfigurationクラスを作成します

```java:DropTestConfiguration.java
package priv.jp.y.suzuki;

import io.dropwizard.Configuration;

public class DropTestConfiguration extends Configuration {

    /** 設定ファイルより読み込み */
    private String template;

    public String getTemplate() {
        return template;
    }

}
```

このようにしておくことでApplicationクラス等でこれを読みこみ、利用することができます。

#### 3-2. Applicationクラス作成
Javaにおけるメインクラスとなるような位置づけにあたるApplicationクラスを作成します。
ここでは、main関数、バンドルの設定、リソースクラスの登録を行います。
一旦、リソースクラスに関してはまだ作成していないのでコメントアウトしておきます。

```java:DropTestApplication.java
package dropTest.priv.jp.y.suzuki;

import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;

public class DropTestApplication extends Application<DropTestConfiguration> {
  // メイン設定
  public static void main(String[] args) throws Exception {
    new DropTestApplication().run(args);
  }

  // バンドル設定
  @Override
  public void initialize(Bootstrap<DropTestConfiguration> bootstrap) {
    bootstrap.addBundle(new AssetsBundle("/assets", "/", "index.html"));
    bootstrap.addBundle(new AssetsBundle("/assets/css", "/css", null, "css"));
    bootstrap.addBundle(new AssetsBundle("/assets/js", "/js", null, "js"));
  }

  // リソースクラス登録
  @Override
  public void run(DropTestConfiguration conf, Environment env) throws Exception {
    
    // 設定ファイルより読み込んだ情報を取得
    String template = conf.getTemplate();
    System.out.println(template); //読み込めたかどうか
    // env.jersey().register(new SampleResource());
  }

}

```

### 4. サーバー側受け口作成
画面側より値を受け取る役割を持つリソースクラスを作成します。
作成場所は以下としています。

作成場所：`dropTest.priv.jp.y.suzuki.resource`

今回は、値を受け取りその値に「"入力ワード："」をつけて返します

```java:SampleResource.java
package dropTest.priv.jp.y.suzuki.resource;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/message")
public class SampleResource {

	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.TEXT_PLAIN)
	@Path("/response/{sentence}")
	public String responseMessage(@PathParam("sentence") String sentence) {
		String message = "入力ワード： " + sentence;
		return message;
	}
}

```

上記のポイントとしては各種アノテーションです。

- `@POST`はPOST通信のときのみに呼び出しが行われるように指定しています
- `@Consumes`・`@Produces`は入力・出力の形式を指定しています。今回はJSON形式・TEXT形式を指定しています
- `@PathParam`は画面からの値の受け取りを行うために指定していて、{sentence}の部分を指定した型(今回はString)で取得しています
- `@Path`はREST通信時の呼び出し対象をURLで指定しています

今回の場合、このリソースクラスが`/message`で、実行したいメソッドが`/response/{sentence}`です。
そのため、ymlファイルで指定したルートパスを含めて下記のようなURLでの実行を想定しています。

POST通信：`/api/message/response/"入力文"`

最後にここまでで作成済みのApplicationクラスにてリソースクラスの登録を行なえば完了です。

```java:DropTestApplication.java
import dropTest.priv.jp.y.suzuki.resource.SampleResource;

  // ~ 中略 ~

  // リソースクラス登録
  @Override
  public void run(DropTestConfiguration conf, Environment env) throws Exception {
    
    // 設定ファイルより読み込んだ情報を取得
    String template = conf.getTemplate();
    System.out.println(template); //読み込めたかどうか
    env.jersey().register(new SampleResource()); // 先ほどはコメントアウトしていたものを有効に
  }

}

```

### 5. 画面作成
ここでは、画面の作成としてhtmlとjavascriptを記載します。
まずは、`src/main/resources`以下に`assets`というフォルダを作成します。
作成した`assets`以下に`index.html`ファイルと`js`フォルダを作成し、
作成した`js`フォルダ以下に`index.html`の動きを記載するjavascriptファイルを作成します(今回は`index.js`)。

パッケージ例:
src/main/resources
　　|__ assets
　　　　|__ index.html
　　　　|__ js
　　　　　　|__ index.js

#### 5-1. index.html作成
今回は、入力欄と送信ボタンとサーバーから返ってきた文字を表示するだけの単純なものを作成します。
画面の表示やREST通信はjQueryの利用を想定します。
そのため、jQueryを[ダウンロード](https://code.jquery.com/jquery-3.2.1.min.js)し、`js`ファイル内に配置しておきます。

```
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DropwizardTEST</title>
  <script src="js/jquery-3.2.1.min.js"></script>
  <script src="js/index.js"></script>
</head>
<body>
<input type="text" id="inputSentence"><br>
<input type="button" id="start" value="REST通信"><br>

<div><span id="result">ここに応答内容が書かれます</span></div>

</body>
</html>
```

#### 5-2. index.js作成
ここではボタンが押されたときにREST通信を実行し、結果を出力する処理を行います。
今回はjQueryのajaxを用いて行います。

```js:index.js

/** ボタン押下に反応 */
$(document).on('click', '#start', function() {
  var SendData = $("#inputSentence").val();
  Request("/api/message/response/" + SendData, "POST", null, resultOpen, FailAnon);
  return false;
});

/** ajax用 */
function Request(Uri, Method, Data, CallbackFunc, ErrorCallbackFunc) {
  $.ajax({
    url:  Uri,
    type: Method,
    data: Data,
    contentType: "application/json; charset=utf-8",
    cache: false
  }).done(function(response){
    CallbackFunc(response);
    return false;
  }).fail(function(XMLHttpRequest, textStatus, errorThrown) {
    ErrorCallbackFunc();
    return false;
  });
  return false;
}

/** ajax失敗時に呼ばれます */
function FailAnon() {
  $("#result").html("<b>ERROR!</b> 通信に失敗しました");
  return false;
}

/** 結果を表示します */
function resultOpen(response) {
  $("#result").html(response + "<br>");
  return false;
}
```

### 6. ビルド
できあがったアプリケーションのビルドを行います。
ビルドはMavenで行います。プロジェクトのディレクトリから下記コマンドでビルドを行います。「BUILD SUCCESS」が表示されれば成功です。
targetディレクトリ以下にjarファイルが作成されているはずです。

ビルドコマンド：`maven package`

### 7. 実行
実行に必要なファイルは二つです。
ビルドによって作成されたjarファイルと設定ファイルとなるyamlファイルの二つです。

実行コマンドとしては下記のようになります。

実行コマンド例：`java -jar target/droptest-0.0.1-SNAPSHOT.jar server config.yml`


※実行時の注意として、今回はヘルスチェッククラスを実装していないため実装するように警告がでます。
ヘルスチェッククラスとは、Dropwizardが提供する一機能でDB等が正常に起動しているかをチェックしてくれる機能です。
なくても動作しますが、設定しておくことが推奨されています。
今回は他のモジュールと接続することもないため作成を省いています。

## 終わりに

無事起動が完了したら実際にWebを開いて確かめてみましょう。
もしも接続できない場合は、出力されるログやF12等の開発者モードを利用すると原因がわかりやすいです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/139291/85b2d0cc-a8a7-1b1d-dd56-4edd42096a54.png)



ちなみに起動したアプリは、多くのアプリと同様に`Ctrl + c`コマンドにより停止させることができます。