Apache Camel Spring Boot starters を使った単純なcamelアプリの作成手順

[**Apache Camel**](https://camel.apache.org/) で作られたアプリの動作検証のため、新たに単純なアプリを作りたかったが、Java系は1から作ったことがほとんど無くて勝手がわからない。

ひとまず公式ページの説明に従って、1秒毎にログを出すrouteが存在するcamelアプリを作ってみた。camelの起動などに関しては検証しないので、簡単に作れそうな [**Camel Spring Boot starters**](https://camel.apache.org/camel-spring-boot/latest/index.html) を使った。

## 環境

* Java: 1.8.0_191
* Maven: 3.6.3
* Camel: 3.2.0
	* Spring: 5.2.5.RELEASE
	* Spring Boot: 2.2.6.RELEASE

---

* OS: Ubuntu 18.04
* IDE: IntelliJ IDEA

## プロジェクトの用意
mavenの場合 `pom.xml` が必要なことは何となく知っているが、この時点で書き方がわからない。camelのページに出ているのは依存関係の書き方だけなので、外枠を用意しなければいけない。

仕方ないので、IDE（IntelliJ IDEA）で新しいプロジェクトを作る形で対応した。

0. File → New → Project...
0. 最初の画面
	0. 左の一覧から `Maven` を選択
	0. Project SDK はひとまず `1.8` のまま
	0. Create from archetype のチェックは外したまま
	0. 「Next」
0. 次の画面
	0. Name: `mycamelapp`
	0. Location: 適当な新規ディレクトリ
	0. Artifact Coordinates 内はひとまずそのまま
	0. 「Finish」

---

念のため、Gitの設定をして作業を保存しておく。 `.gitignore` はGitHubに[テンプレート集](https://github.com/github/gitignore)があったのでそれを使うことにした。

```bash:terminal
cd path/to/app

git init

for kind in Java Maven Global/JetBrains; do
  echo "###--- github/gitignore : ${kind}.gitignore ---###"
  curl https://raw.githubusercontent.com/github/gitignore/master/${kind}.gitignore
  echo
done >> .gitignore

git add .
git commit -m 'Create a Maven project'
```

## pom.xml
https://camel.apache.org/camel-spring-boot/latest/index.html に従って依存関係を書き足す。 `dependencies` は `dependencyManagement` の中と外で別々に書く必要があることに気付かず時間を取られた。

全体は以下のようになった。

```xml:pom.xml&#x20;(mycamelapp)
<?xml version="1.0" encoding="UTF-8"?>
<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>org.example</groupId>
	<artifactId>mycamelapp</artifactId>
	<version>1.0-SNAPSHOT</version>

	<!-- https://camel.apache.org/camel-spring-boot/latest/index.html -->
	<dependencyManagement>
		<dependencies>
			<!-- Camel BOM -->
			<dependency>
				<groupId>org.apache.camel.springboot</groupId>
				<artifactId>camel-spring-boot-dependencies</artifactId>
				<version>3.2.0</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<!-- ... other BOMs or dependencies ... -->
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<!-- Camel Starter -->
		<dependency>
			<groupId>org.apache.camel.springboot</groupId>
			<artifactId>camel-spring-boot-starter</artifactId>
		</dependency>
		<!-- ... other dependencies ... -->
	</dependencies>
</project>
```

other dependenciesに追加するコンポーネントの例として ActiveMQ が紹介されているが、こちらは使う予定が無いのでスキップ。

## route定義
ここは保守中のアプリでたくさん例を見てきたので、個人的に迷うところは無い。 https://camel.apache.org/camel-spring-boot/latest/spring-boot.html#SpringBoot-CamelSpringBootStarter にある短いrouteを定義する。

```bash:terminal
cd path/to/app

mkdir -p src/main/java/org/example/mycamelapp/routes
touch    src/main/java/org/example/mycamelapp/routes/SampleTimerRoute.java
```

```java:src/main/java/org/example/mycamelapp/routes/SampleTimerRoute.java
package org.example.mycamelapp.routes;

import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;

@Component
public class SampleTimerRoute extends RouteBuilder {

	@Override
	public void configure() throws Exception {
		from("timer:foo").to("log:bar");
	}
}
```

### routeとは？
大雑把に言えば**パイプライン**。Java8の [Stream API](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/package-summary.html) などを想像すればいいが、続々と流れてくるデータをどのように処理するかをDSLで書いている。

* `from(uri)` はデータの入口。
	* データは「exchange」と呼ばれる入れ物に入っている。
	* URIの形で様々な[コンポーネント](https://camel.apache.org/components/latest/index.html)（数百種類）とその詳細設定を指定できる。 `timer` で逐次生成したり `file` でファイルをポーリングしたり。
* `to(uri)` はデータの渡し先。
	* 終端というわけではなく、1回である必要も無い。
	* こちらもURIで色々できる。 `sql` でDBにクエリを投げたり `http` でHTTPリクエストを投げたり。
* データの処理方法も色々。
	* 条件分岐・ループ・例外処理などもDSLで構築できる。
	* 単純なexchange操作は方法が用意されているし、もっと複雑な処理なら「processor」を定義すればいい。

## SpringBootの設定
camelのドキュメントからは見つけられなかったが、さすがにアプリの開始地点は書かなければいけないみたい。書くとIDEで該当行に「Run」マークが表示される。

```java:src/main/java/org/example/mycamelapp/MyCamelApplication.java
package org.example.mycamelapp;

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

@SpringBootApplication
public class MyCamelApplication {

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

アプリが起動後すぐ終了しないようにする。こちらはパラメーターを与えれば済むようなので、yamlで書いておく（propertiesでもいい）。

```yaml:src/main/resources/application.yml
# to keep the JVM running
camel:
  springboot:
    main-run-controller: true
```

## 起動
IDE上なら前述の「Run」ボタンを押せばすぐ起動できる。

---

mavenのコマンドで起動するなら、pom.xmlに設定を加える。

```xml:pom.xml&#x20;(mycamelapp)
...
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<version>2.2.6.RELEASE</version>
			</plugin>
		</plugins>
	</build>
...
```

```bash:terminal
cd path/to/app

mvn spring-boot:run
```

## 参考

* Apache Camel 公式ドキュメント
	* [Spring Boot starters](https://camel.apache.org/camel-spring-boot/latest/index.html)
	* [Spring Boot](https://camel.apache.org/camel-spring-boot/latest/spring-boot.html) # Camel Spring Boot Starter
* Apache Camel サンプル
	* [Apache Camel examples](https://github.com/apache/camel-examples)
	* [Camel Example Spring Boot](https://github.com/apache/camel-spring-boot/tree/master/examples/camel-example-spring-boot)
* その他
	* [Getting Started | Building an Application with Spring Boot](https://spring.io/guides/gs/spring-boot/)
	* [Spring Boot Maven Plugin &#x2013; Usage](https://docs.spring.io/spring-boot/docs/current/maven-plugin/usage.html)
	* [github/gitignore: A collection of useful .gitignore templates](https://github.com/github/gitignore)