Spring Cloud Streamを試す(redis)

# はじめに
最近新しくなったSpring Cloud Streamを試してみる。
まずはサンプルをつかってredisから。
[Spring Cloud Stream](http://cloud.spring.io/spring-cloud-stream/#quick-start)のQuick Startだとうまくいかなかったので、IntelliJのSpring Initializrを使ってみた。

# 環境
- Mac
- IntelliJ
- redis(適当にインストールしておく)

# 手順
## IntelliJからプロジェクトを作成する
昨日紹介したIntelliJの[Spring Initializr](http://qiita.com/gosshys/items/fdf614d7301d01022a47)の機能を利用する

### プロジェクトを作成メニューを開く
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/7ecdb077-ea82-45f1-3e9f-0869402a82b0.png)
### 左のペインから「Spring Initializr」を選択して、「Next」ボタンをクリック
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/9e5c51ef-f72a-3836-5b5d-fe8d82f57cf1.png)
### 「Name」に適当に名前をつけて「Next」ボタンをクリック
「Type」は`Gradle Project`を選択したが、`Maven`でもOK。
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/c7266552-6d7b-5b14-38e7-641d818b567a.png)
### 「Dependencies」から``を選択して、「Next」ボタンをクリック
わかりやすさのために余計なメニューはたたんでいます。
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/cfef7bf4-898d-59e7-8266-3c4238148bff.png)
### 「Project Name」に適当に名前をいれて、「Next」ボタンをクリック
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/3fbb4051-4db2-141a-3b21-366248b1d668.png)
### しばらくして`Gradle`の設定画面がでてきたら、「OK」ボタンをクリック
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/13f3895f-9c84-9396-710a-246eff2ee8a6.png)
### プロジェクトができあがる
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/19655d0d-e100-ac73-5877-19ad1df73559.png)

## デフォルトの状態で起動してみる
### redisを起動
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/9eee07e6-ae87-85aa-ca5f-08bea63696dd.png)
### IntelliJから自動生成された「SpringCloudDemoApplication」を起動
Javaのクラス名は、自分で設定した名前+`Application`になっているので読み替えてください。
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/8c6d06b1-7b14-3c9f-a352-97a3190bbdf8.png)
### 起動してエラーがでなければOK
正しく起動すれば停止する
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/987a8768-9e12-d5a1-f2e1-426ed508b14c.png)

# サンプルを動かす
[spring-cloud-stream](https://github.com/spring-cloud/spring-cloud-stream/tree/master/spring-cloud-stream-samples)のgithubのsampleから利用できそうなソースをもってくる

## Sourceのサンプルを持ってくる
Spring Cloud StreamのSourceは、情報のinputにあたる役割になる。要するにredisに情報を入力する役割。
sourceのサンプルを以下の３つを自動生成された`SpringCloudDemoApplication.java`と同じパッケージにコピーする。

- DateFormat.java
- TimeSource.java
- TimeSourceOptionsMetadata

### githubからcloneする

```
cd /tmp
git clone https://github.com/spring-cloud/spring-cloud-stream.git
```

### Finderを使って、３つのファイルをコピーして、IntelliJの`SpringCloudDemoApplication.java`と同じパッケージにコピーする

![image](https://qiita-image-store.s3.amazonaws.com/0/38174/02325129-46c8-1f33-6f47-79622c1dfe9e.png)

### IntelliJにコピーする
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/b4cc16a6-230e-a82a-e076-3c226ec6427f.png)

### application.propertiesをymlへrename
サンプルがyml形式になっているので、自動生成された`application.properties`を`application.yml`へ変更する
#### ファイルを右クリックして「Refactor」「Rename」を選択
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/0d0c32ab-df09-5508-c3eb-ee0f32354a1d.png)
#### 名前を`application.yml`に変更して、「Refactor」ボタンをクリック
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/4daab19d-5501-b02b-4789-87ba8f0b7f23.png)
### サンプルの`application.yml`の内容をコピーして、renameした自分のプロジェクトの`application.yml`に貼り付ける

```
server:
  port: 8080
fixedDelay: 5000
spring:
  cloud:
    stream:
      bindings:
        output:
          destination: testtock
          contentType: text/plain
        # uncomment below to use the last digit of the seconds as a partition key
        # hashcode(key) % N is then applied with N being the partitionCount value
        # thus, even seconds should go to the 0 queue, odd seconds to the 1 queue
        #producerProperties:
        #  partitionKeyExpression: payload.charAt(payload.length()-1)
        #  partitionCount: 2

---
spring:
  profiles: extended
  cloud:
    stream:
      bindings:
        output: xformed
```

### コンパイルエラーを解消する
Sourceのサンプルを単純にコピーするだけだと`ConfigurationProperties`が利用できない旨のエラーが発生する。Intelljのエディタの上部に`Spring Boot Configuration Annotation Processor not in classpath...`のようなエラーとともに[Open Documentation](http://docs.spring.io/spring-boot/docs/1.3.0.RELEASE/reference/html/configuration-metadata.html#configuration-metadata-annotation-processor)のリンクが表示されるのでそれをクリックする。

#### `spring-boot-configuration-processor`の指定
エラーの原因が独自のアノテーションを利用するのに`configuration-processor`が必要ということで、ページ内の[propdeps-plugin](https://github.com/spring-projects/gradle-plugins/tree/master/propdeps-plugin)リンクの情報と共に以下のように`build.gradle`ファイルを変更した。

変更ポイント

- buildscript.repositoriesに`maven { url 'http://repo.spring.io/plugins-release' }`を追加
- buildscript.dependenciesに`classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")`を追加
- `configure(allprojects)`を追加
- `compileJava.dependsOn(processResources)`を追加
- dependenciesに`optional("org.springframework.boot:spring-boot-configuration-processor")`を追加

```
buildscript {
    ext {
        springBootVersion = '1.3.0.RELEASE'
    }
    repositories {
        mavenCentral()
        maven { url 'http://repo.spring.io/plugins-release' }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot' 

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

configure(allprojects) {
    apply plugin: 'propdeps'
    apply plugin: 'propdeps-maven'
    apply plugin: 'propdeps-idea'
    apply plugin: 'propdeps-eclipse'
}

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
    maven { url "https://repo.spring.io/milestone" }
}

compileJava.dependsOn(processResources)

dependencies {
    compile('org.springframework.cloud:spring-cloud-starter-stream-redis')
    optional("org.springframework.boot:spring-boot-configuration-processor")
    testCompile('org.springframework.boot:spring-boot-starter-test')
}


dependencyManagement {
	imports { 
		mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Brixton.M3" 
	}
}


eclipse {
    classpath {
         containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
         containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.7'
}

```

この状態で、gradleをbuildしなおせばエラーは解消されるはず。

### IntelliJから「SpringCloudDemoApplication」を起動
起動してエラーがでなければ、fixedDelayに設定した5秒おきに時間の内容がredisに記録されている。ことになる。が、ログにでないのでわかりづらい。
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/ee4420cc-1911-350a-bdba-e66266a83cf2.png)

## Sink側も作成する
Sourceでredisに書きだした時間の情報をSinkのサンプルも動かして受け取るようにする。

今までの手順を繰り返して、Sink用のプロジェクトを作成し、Sinkのサンプルをコピーして使えるようにする。
※同じ手順になるのであえて説明は繰り返さない。

こんな感じで`Received: 2015-11-29 21:01:27`が5秒ごとに出力されればOK
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/ffcfa9e5-684f-ef70-7921-8104205a3b19.png)