Apache Camel+Spring Boot 2でHello World（REST API編）

# はじめに

Apache Camel+Spring Boot 2でHello Worldの「REST API編」です。
コンソールアプリ編は以下の投稿になります。

[Apache Camel+Spring Boot 2でHello World（コンソールアプリ編）](https://qiita.com/drafts/ff22e1c46a1d9cc78489/edit)

作成するREST APIですが、「/spring/hello」にアクセスすると「Hello World」とレスポンスを返します。また、非同期でサーバ側の標準出力にリクエストの内容を表示します。
※Apache Camelの良さを何も引き出していないサンプルになっています。

以下のフレームワーク等の組み合わせで作成しています。

- Apache Camel 2.3.0
- Spring Boot 2.1.1
- JDK8
- Eclipse Photon(4.8.0)
- Maven

# Apache Camelとは

Spring Bootは説明の必要はないと思いますので、Apache Camelだけ簡単に説明します。

Apache Camelは、システム間の統合のためのミドルウェア（フレームワーク）とよく説明されています。システム間の統合はEnterprise Integration Patternsというベストプラクティスがあり、Camelではそれを簡単に実現することができます。
このように書くと小難しいように聞こえてしまい、無駄に敷居が高くなっているような気がします。
実際には「別のシステムからリクエストを受けて、何らかの処理をして、どこかへ送信・格納（DBやキュー）する。」といったことが簡単にできるフレームワークと思えばよいです。
REST/SOAP、データベース(JDBC, MongoDB, DynamoDB, etc)、ファイル、メッセージキュー（ActiveMQ, Kafka, RabbitMQ, etc）、メール、MQTTなど、様々なものと連係することでき、それを実現するための部品がコンポーネントと呼ばれます。
コンポーネントは200近くにのぼり、繋げたい相手のコンポーネントは大抵見つけることができます。
「何らかの処理をして」の部分も、データ変換、フォーマット変換、ルーティング、エラー処理等の機能は網羅されており、あらゆるアプリケーションで利用できるフレームワークです。

# Eclipseでプロジェクトを作成する

まず、Mavenプロジェクトを新規に作成します。
「Mavenプロジェクト」を選択して「次へ」。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/179607/0d7b06ef-0ce3-742d-7bbe-ba14be7f690d.png)

特に変更せず、「次へ」。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/179607/8e7142a2-74ac-bf72-03b6-9d763fb127fc.png)

「maven-archetype-quickstart」を選択して、「次へ」。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/179607/a04073bb-250a-b076-da1b-5a962f11076e.png)


プロジェクトの情報を入力して、「完了」。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179607/d2490c04-e0e5-0e68-4631-c154c9b8795b.png)

これでプロジェクトの作成は完了。


# pom.xmlを修正

pom.xmlを以下のように修正する。

```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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>mkyz08.sample</groupId>
  <artifactId>camel-springboot-rest-test</artifactId>
  <packaging>jar</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>camel-springboot-rest-test Maven Webapp</name>
  <url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
		<maven.compiler.target>${java.version}</maven.compiler.target>
		<maven.compiler.source>${java.version}</maven.compiler.source>
		<camel-version>2.23.0</camel-version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.apache.camel</groupId>
				<artifactId>camel-parent</artifactId>
				<version>${camel-version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-stream</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

```

# プログラムを作成

以下のようにメインプログラムを作成する。

```Application.java
package mkyz08.example;

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

@SpringBootApplication
public class Application {

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

以下は、普通のSpring Bootのアプリケーションの起動ですね。

```java
SpringApplication.run(Application.class, args);
```


設定ファイルは以下のとおり作成しましたが、アプリケーション名だけなので作成しないでも大丈夫です。

```src/main/resources/application.properties
camel.springboot.name = MyCamelRestApp
```

次はコントローラクラス（HelloRestController）を作成します。
コントローラクラス（HelloRestController）にRestControllerアノテーションを付けます。

```HelloRestController.java
@RestController
@RequestMapping("/spring")
public class HelloRestController {
```

RequestMappingアノテーションにより、クライアントからのリクエストに対してGETメソッドをマッピングしています。

```HelloRestController.java
    @RequestMapping(method = RequestMethod.GET, value = "/hello",
                    produces = "text/plain")
```

helloメソッドでは、受信したmsgパラメータの値を「seda:hello_world」の非同期キューに格納しています。同期にする場合は、「direct:hello_world」にするだけで変更できます。
そして、"Hello World"の文字列をレスポンスとして返しています。

```HelloRestController.java
    public String hello(String msg) {
    	Endpoint end = context.getEndpoint("seda:hello_world");
		producer.sendBody(end, msg);
        return "Hello World";
```

コントローラクラス（HelloRestController）のソースコードの全体は以下のようになります。

```HelloRestController.java
package mkyz08.example;

import javax.annotation.Resource;

import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.ProducerTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/spring")
public class HelloRestController {

	@Resource
	private ProducerTemplate producer = null;

	@Resource
	private CamelContext context;

    @RequestMapping(method = RequestMethod.GET, value = "/hello",
                    produces = "text/plain")
    public String hello(String msg) {
    	Endpoint end = context.getEndpoint("seda:hello_world");
		producer.sendBody(end, msg);
        return "Hello World";
    }
}
```

最後にCamelのrouteを作成します。
Camelのroute定義のため、クラスにComponentアノテーションを付与し、RouteBuilderクラスを継承しています。
そして、configureメソッドをオーバーライドして、routeの内容をコーディングします。

```HelloWorldRoute.java
package mkyz08.example;

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

@Component
public class HelloWorldRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {
		from("seda:hello_world")
				.routeId("hello world route")
				.setBody(simple("Hello World : ${body}"))
				.to("stream:out");
    }
}

```

以下がrouteの内容で、

- 「from("seda:hello_world")」で、受信したリクエストを非同期で処理を開始
- 「.routeId("hello world route")」、これはルートIDを指定しているだけ
- 「.setBody(simple("Hello World : ${body}"))」、ExchangeのBODYに受信したパラメータ（msg）の値を設定
- 「.to("stream:out")」でExchangeのBODYに入っている、パラメータ（msg）の値をコンソールに出力しています。

```java
		from("seda:hello_world")
				.routeId("hello world route")
				.setBody(simple("Hello World : ${body}"))
				.to("stream:out");
```


# Hello World Webアプリケーションを実行する

作成したプログラムを実行し、以下のURLにアクセスします。

http://localhost:8080/spring/hello?msg=hoge

「Hello World」が返ってきて、サーバ側の標準出力にも以下のように表示されます。

```
Hello World : hoge
```


# 実行可能なjarファイルを作成する

実行可能なjarファイルを作成するため、以下のように「実行構成」でゴールに「clean install spring-boot:repackage」と入力し、実行します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/179607/0fc180d3-ff0c-0c53-cc95-f2c928f89b0a.png)

実行に成功すると以下のようなログが出力されます。


```
[INFO] --- spring-boot-maven-plugin:2.1.0.RELEASE:repackage (default-cli) @ camel-springboot-rest-test ---
[INFO] Replacing main artifact C:\pleiades\workspace\camel-springboot-rest-test\target\camel-springboot-rest-test-0.0.1-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.017 s
[INFO] Finished at: 2018-12-06T18:39:38+09:00
[INFO] ------------------------------------------------------------------------```
```

実行可能なjarファイルはプロジェクトの「target」とディレクトリに作成されており、以下のコマンドで実行できます。

```
java -jar camel-springboot-rest-test-0.0.1-SNAPSHOT.jar
```



# 参考

- [Apache Camel公式サイト　Spring Boot](https://camel.apache.org/components/latest/spring-boot.html)

- [Apache Camel with Spring Boot](https://medium.com/@mzimecki/spring-boot-apache-camel-web-service-a90696d8ac36)

- [Apache Camel公式サイト　Spring Bootサンプル](https://github.com/apache/camel/tree/master/components/camel-spring-boot)