<commit_before>---
layout: page
title: Redirect Why do we have to learn Apache Camel
permalink: /article/why-do-we-have-to-learn-camel
---

<meta http-equiv="refresh" content="0; URL='https://github.com/tomonari-yamashita/japan-camel-user-group/wiki/なぜ今Apache Camelを学ぶ必要があるのか？'" />

Apache Camelの開発者である<NAME>氏は、Camelのことを「ツールボックス」と表現している。Camelは、プログラマの能力を一段と引き上げる洗練されたツールで、すべてのJavaプログラマが学ぶ価値のあるものだ。

いままでCamelは、大規模なシステムのメッセージングを前提としたシステム間統合のためのミドルウェアと思われがちだった。こうしたこともあってか、どうやら日本での導入はいくつかの例外を除いて一部の大企業が中心のようだ。一方、海外ではより広範囲への導入が確実に進んでいる。実はCamelはどのようなアプリケーションでも利用できる、とても汎用的で拡張可能なライブラリでもあるのだ。

Camelが提供する主な機能は、アダプタ、データ変換、ルーティング、エラーや障害時のハンドリングといったものだ。そして、これらは実際のコーディングの多くをしめ、複雑化しやすい部分でもある。初めてCamelで書かれたコードをみたら、シンプルで無駄がないことに驚くだろう。Camelでのプログラミングはコーディングであり、また設定であり、そしてそれらの調和によってプログラマの意図を直接反映させることができるものだ。

クラウド、マイクロサービス、イベントソーシング、リアクティブプログラミング、API管理、モバイル、IoTといった技術の普及により、分散したマシン間でイベントを協調させるシステムが多くなってきた。こうしたことが海外における広範囲なCamelの導入の背景となっている。私の所属しているRed Hatでもでもそうした技術を用いた各種のリファレンスアーキテクチャ[1]を提案しているが、これらの実装にはCamelを利用することが前提となっている。こうした技術の利用においてCamelは必要不可欠な薄いインフラとして確固たる地位を築き始めている。

今回はCamelの詳細には触れない。その代わりに、Camelは何ができ、そしてなぜ学ぶ必要があるのかを説明する。<commit_msg>Put the contents on the article for SEO<commit_after>---
layout: page
title: Redirect Why do we have to learn Apache Camel
permalink: /article/why-do-we-have-to-learn-camel
---

<meta http-equiv="refresh" content="0; URL='https://github.com/tomonari-yamashita/japan-camel-user-group/wiki/なぜ今Apache Camelを学ぶ必要があるのか？'" />



## はじめに
Apache Camelの開発者である<NAME>氏は、Camelのことを「ツールボックス」と表現している。Camelは、プログラマの能力を一段と引き上げる洗練されたツールで、すべてのJavaプログラマが学ぶ価値のあるものだ。

いままでCamelは、大規模なシステムのメッセージングを前提としたシステム間統合のためのミドルウェアと思われがちだった。こうしたこともあってか、どうやら日本での導入はいくつかの例外を除いて一部の大企業が中心のようだ。一方、海外ではより広範囲への導入が確実に進んでいる。実はCamelはどのようなアプリケーションでも利用できる、とても汎用的で拡張可能なライブラリでもあるのだ。

Camelが提供する主な機能は、アダプタ、データ変換、ルーティング、エラーや障害時のハンドリングといったものだ。そして、これらは実際のコーディングの多くをしめ、複雑化しやすい部分でもある。初めてCamelで書かれたコードをみたら、シンプルで無駄がないことに驚くだろう。Camelでのプログラミングはコーディングであり、また設定であり、そしてそれらの調和によってプログラマの意図を直接反映させることができるものだ。

クラウド、マイクロサービス、イベントソーシング、リアクティブプログラミング、API管理、モバイル、IoTといった技術の普及により、分散したマシン間でイベントを協調させるシステムが多くなってきた。こうしたことが海外における広範囲なCamelの導入の背景となっている。私の所属しているRed Hatでもでもそうした技術を用いた各種のリファレンスアーキテクチャ[1]を提案しているが、これらの実装にはCamelを利用することが前提となっている。こうした技術の利用においてCamelは必要不可欠な薄いインフラとして確固たる地位を築き始めている。

今回はCamelの詳細には触れない。その代わりに、Camelは何ができ、そしてなぜ学ぶ必要があるのかを説明する。

# ダイレクトに意図を表現できるCamel
Camelには様々な機能があるが基本的な動きはシンプルだ。Camelでの処理は、データを自身で取りに行ったり、誰かから受け取ることで開始される。例えば、CSVファイルを読み取ったり、HTTPでJSONによるリクエストを受け取ったりした場合だ。そして、受け取ったデータを加工し、次の転送先を判断して、そこへデータを送る。基本的にはこれだけだ。データの受信元/送信先としてRESTやSOAP通信、メッセージキュー、データベース、ファイル送信、メール送信など様々なものと連携できる。

Camelの強力さを実感するために、早速実際のコード例を見てみよう。この例は次のようなJSONを受け付けるRESTサービスを公開する場合のサンプルコードだ。
- RESTサービスがユーザを登録用のJSONリクエストを受けつける
- DBにユーザデータを登録する
- テンプレートエンジンでメールの文面を作成して、ユーザにメールを送信する(非同期で処理)
- ユーザの追加を他システムに通知するためのイベント(XML)をキューに登録する
- エラーハンドリング
  - 10秒以内に終了しなかったら、タイムアウトエラーにする
  - 何らかのエラーが15秒以内に2回以上発生したら本サービスを120秒間クローズする
  - サービスがクローズ状態の間は、リクエストに対して即座にエラー応答を返す

~~~java
// usersのパスにpostが送信されたら処理を開始
// 次のようなリクエストを想定 {name:"username_1", email:"<EMAIL>"}
rest("/users")
  .post()
    .route()
        .hystrix()
          // サーキットブレーカーの設定
          // 10秒以内に処理が終了しなかったらタイムアウトエラーにする
          // 何らかのエラーが15秒以内に2回以上発生したら本サービスを120秒間クローズする
          .hystrixConfiguration()
            .executionTimeoutInMilliseconds(10000)
            .metricsRollingPercentileWindowInMilliseconds(15000)
            .circuitBreakerRequestVolumeThreshold(2)
            .circuitBreakerSleepWindowInMilliseconds(120000)
          .end()
          // JSONをMapオブジェクトに変換
          .unmarshal().json(JsonLibrary.Jackson, Map.class)
          // DBにUserデータを保存 
          .to("sql:insert into users(name, email) values(:#name, :#email)")
          // [サブルート呼び出し(非同期)] ユーザへメールを送信 
          .wireTap("direct:userCreatedNotificationMail").end()
          // ユーザの追加を他システムに通知するためのイベント(XML)をキューに登録する
          .transform(new Map2XML("user-created")).to("jms:UserCreated")
          // 成功を応答する
          .transform().constant("{result:\"true\"}")
        // エラーやサービスがクローズされている場合には、失敗を応答する
        .onFallback()
          .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(503))
          .transform().constant("{result:\"false\"}")
        .end();

// [サブルート] メールの文面をテンプレートを用いて作成し、ユーザへメールを送信
from("direct:userCreatedNotificationMail")
  .setHeader("to", simple("${body[email]}"))
  .to("velocity:template/velocity/createdUserNotification.vm")
  .to("smtp://smtpserver?password={{smtp_password}}&username={{smtp_user}}");
  
~~~

流れるようにプログラミングが行われており、コーディングとも設定ともつかない。ここでその詳細は説明しないが、それでも何が行われるのかは想像できると思う。これはやりたいことがダイレクトに表現できているということだ。

これだけのことを各種の個別ライブラリを直接扱いながら実装するのは大変な労力が必要だし、そもそも同じだけのことを実装できるプログラマはプロジェクト内に何人もいないだろう。Camelなら接続先に応じた個別の実装や、データ型の調整、高度なエラーハンドリングなど、様々な詳細を隠蔽して、設定を中心とした宣言的なプログラミングを行うことができる。

特に、マイクロサービスのようなダイナミックに成長していくシステムにおいては、このように使い捨てできるレベルの高い生産性でプログラミングできなければ、勝負の土俵にすら上がれない。

# Camelの基本的な機能
Camelが提供する基本的な機能には以下のようなものがある。
  ※より高度な機能については別途後述する。

## 様々なものとの相互接続を可能にするアダプタ
Camelは、REST/SOAP、ファイル、データベース(JDBCやJPAなど)、各種メッセージキュー、メール、MQTT、そして当然Javaプログラムなど、様々なものと相互に接続して連携させることができる。それらを使用するために個別ライブラリを直接扱う必要はなく、そしてその詳細を知る必要もない。URIによる設定を行うだけで利用できるようになる。いまではコミュニティのものを含めると200以上ものコンポーネントが存在する。

## 型変換
Camelは接続先に応じて自動的にデータ内容の型変換を行う。接続先ごとに好みのデータ型は異なり、例えばファイルならストリーム、データベースはResultSet、JMSならTextMessageなど数え上げればキリがない。普段のプログラミングでもこれらを連携させる場合には、地道で厄介な型変換のコーディングを行っているはずだ。しかしCamelを使えば必要な型変換を自動的に行ってくれる。

## データ変換/フォーマット変換
Camelはデータの種類を選ばない。JSON、XML、CSV、Javaオブジェクトなど、そのままCamel内で扱える。そしてその内容を書き換えたり相互に変換できる。変換にはXPATHやXStreamやJAXBなど様々な方法が可能だ。また各種テンプレートエンジンを利用してメールなどへの定型的な文面を作成することもできる。そしてもちろん直接自分でコーディングしてしまうことも可能だ。こうしたデータ変換処理にあまり馴染みがないと感じる方がいるかもしれないが、DBから取り出したデータをJSPによるテンプレートよってHTMLに変換する処理なども立派なデータ変換処理といえる。普段のプログラミングでよく行われている作業の１つだ。

## ルーティング
受け取ったデータは、分岐やフィルタリングさせたり、分割して並列処理させたり、それらを集約したりすることができる。Camelでは普段コーディングしているif文のようにこれらを指定できる。

## これらは普段のプログラミングで行っていること
これらの機能を振り返ってみれば、実はCamelは普段のプログラミングの多くの側面に対応し、身近な問題を解決していることがわかる。Camelは簡単な処理から複雑な問題まで対応することができ、誤解を恐れずに言えば、Camelはあらゆるアプリケーションで利用可能だとさえいえる。特にJEEアプリケーションサーバやフレームワークなどによる包括的なプログラミングへのサポートが期待できなかったり、それでは不足している機能があればCamelの利用を検討するべきだ。

# Camelのアーキテクチャ(簡易版)
Camelには高度な機能がたくさんあるが、それら機能をよりよく理解するためには、いくらかCamelのアーキテクチャについて知らなけばならない。ここでは簡単ながら説明する。

![Camelのアーキテクチャ](https://user-images.githubusercontent.com/27920264/30095144-a0f1735e-930b-11e7-9b4b-0bbfc70aba09.png)

~~~
// Consumer
from("jetty:http://localhost:8080/orders?httpMethodRestrict=POST") 
    .process().body(this::process1)) // Processor 1
    .process().body(this::process2)) // Processor 2
    .to("jms:queue:order?timeToLive=86400000"); // Producer
~~~

Camelの汎用性は、シンプルだが強力な構造によって支えられている。データを運ぶ袋としての「メÃÂングを行う「プロセッサ」、外側とをつなぐアダプタとしての「エンドポイント」、そしてエンドポイントとプロセッサを組み合わせた一連のフローである「ルート」だ。上の図はそれを模式化したのもので、サンプルコードはCamelで記述した場合の例だ。Camelのアプリケーションは、このルートを単位として組み合わせていくことで、全体としてサービスやシステムを形作っていく。この構造は、システム間統合の叡智を集約したEnterprise Integration Patterns(EIP)[2]に基いている。

エンドポイントは、REST/SOAP、ファイル、データベース(JDBCやJPAなど)、各種メッセージキューといった接続対象とルートを結びつけるためのアダプタだ。なお本来EIPはメッセージングを対象としたパターンであり、エンドポイントをメッセージブローカーとの接点としてのみ扱っていた。その考えをCamelでは拡張して、あらゆる接続対象をエンドポイントとして取り扱い、またデータをすべてメッセージとして扱えるようにしている。これによりCamelは、メッセージングに限らず、あらゆる接続先とデータを統一的に取り扱いながら相互に接続させることを実現している。

また、エンドポイントへの設定はURI形式になっており、こうした設ÃÂって、多くのアプリケーションのニーズに対応できる強力な柔軟性を持っている。また新しい技術が誕生しても、それに対応したエンドポイントを提供することで、この普遍的な構造の中でもCamelは常に進化を続けている。

# Camelの高度な機能
簡単にCamelのアーキテクチャを見たところで、高度なCamelの機能を説明する。これらの機能のすべてを理解するのは尻込みしてしまうが、必要な機能から少しづつ学んで利用していけばいい。実際のところコンポーネントが多すぎて、すべての機能を把握できる人はいない。すべての機能を知らなくてもCamelを利用できるし、十分に恩恵をうけることができる。

## 高度なルーティング
受け取ったメッセージは、分岐やフィルタリングしたり、分割して並列処理させたり、それらを集約したりすることができる。またHTTP通信のような同期処理から、その応答を待たずに処理を続ける非同期処理へと切り替えることも簡単だ。さらには単体のマシン内だけでなく、マシンをまたぎ複数のキューを経由させながら、応答メッセージを受け取るようなダイナミックで高度なルーティングも利用できÃÂちろんのこと、中長期にわたる障害がシÃÂを実現することも可能だ。さらにファイルなどのトランザクションが提供されないリソースに対しては、エラー発生時に実行すべき補償トランザクションを定義することもできる。

トランザクションに関連して、冪等性(Idempotency)をサポートするIdempotent Consumer機能もある。例えばKafkaやAWS Kinesisなどのイベントソーシングに特化したメッセージブローカーなどでは同じデータが複数回送られることがあるが、この機能で補完すれば、同じデータが複数回送信されたことを検出して、*ただ１回のみ*の処理を実現することができる。

## ノンブロッキング対応
Camelはノンブロッキングによる非同期処理に対応する。例えば背後のWEBサービスの処理にÃeages.githubusercontent.com/27920264/30097989-1371fbf6-931b-11e7-8009-23ab60506655.png" height="300"></p>

さらにCamel内部の各種イベントを購読できる仕組みも用意され、それこそCamelの持つ連携のための機能を組み合わせれば、監視専用サーバへの連携も簡単に実現できる。

## 開発ツールの提供
JBossからEclipseベースのグラフィカルエディタが提供されている。これを利用すればグラフィカルÃÂと連携させることも容易だ。このため必要な部分でだけCamelを利用することができる。連携するJavaのコードはPOJOやラムダ式を利用でき、CamelのAPIに依存させないままにコーディングが可能だ。また、RxJavaなどのReactive Streams APIを使って相互に連携することもできる。

## 様々な表現でルートを定義できる
今回紹介したのは、Javaコードの中にルートを定義する、JavaDSLを利用したものだ。その他にも、XML DSLやScala DSLやGroovy DSLにも対応している。

## 様々な環境で動作する
Camel自体はライブラリであるので様々な環境で動作する。各種のWEBサーバ、アプリケーションサーバ、KarafなどのOSGI環境でも動作させられるし、Camelをスタンドアロンで動作させることも可能だ。

## EIPを実現したCamel
これまで何度か触れているようにCamelはEIPに基づきそのパターンを実現したものだ。しかし残念ながらEIPは邦訳されておらず、ページ数も多いため、忙しいエンジニアはなかなか学習する機会が得られないと思う。Camelを使えば、自然とEIPに基づくアーキテクチャにそった構成でプログラミングを行うことになり、明に暗にEIPから多くの恩恵を受け、そしてその知識も少しづつ身につけることができる。初めのうちはCamelを使い、必要に応じてEIPを学んでいくというスタンスで良いのではないかと思う。EIP自体の知識がなくても多くのCamelを機能を利用して恩恵をうけることができる。もちろんEIPにはシステム間統合の設計する上でとても有用な情報が詰め込まれているので時間があれば勉強したいところだ。

## テストキットの充実
Camelはテストのしやすさが考慮されている。エンドポイントは各種のアサーション機能を持ったモックに入れ替えることができる。またメッセージのインターセプトやルートの一部置換も可能だ。これらを使えばあらゆる箇所を様々な状況でテストできる。またCitrusやArquillianなどのシステムテストを対象としたツールと組み合わせることもできる。

# [PR] 日本でのCamelコミュニティ ~ Camel コミュニティ関係者より ~

> Camelの人気は、海外と比べると日本では残念ながら今ひとつという感触です。これにはEIPの学習ハードルの高さや、いままでファイル連携や共有データベースによって連携を行ってきた実績に対する強い信頼感があるのかもしれません。しかし、日本でもクラウドやマイクロサービスの採用が進み、またファイル連携や共有データベースも、ActiveMQやKafkaなどによるメッセージブローカーへ置き換わってきています。Camelの出番です。
>
> この度、少しでもCamelのよさを知ってもらうために、Red Hat社の有志社員を中心として、Camelのユーザグループを作成する運びとなりました。（Red Hat社としての活動ではありません。参加者全員の自主的な活動により成り立っています。）ゆくゆくは日本でのCamelのオープンソースコミュニティを成熟させて、利用者を増やすことはもちろんのこと、機能追加の提案やプルリクエストなどの貢献が行なえるようなメンバーがでてくることも目指しています。Camelはコーディング規約やドキュメントも用意されているため開発に参加するハードルも低く、今後も新技術に対応したコンポーネント作りが求められていくはずです。実際にコンポーネント作りを通してCamelのコミッターになった方もいます。さらに幸運なことにCamelの開発に携わる日本人技術者さえいます。日本におけるCamelコミュニティの場から、お互いの貢献を通して、そしてお互いに還元できればと思っています。
>
> Camelに興味を持った方は、「Camal In Action」の読書会を定期的に実施しておりますので、是非ご参加ください。
> -https://github.com/tomonari-yamashita/japan-camel-user-group/wiki

# まとめ
Camelが提供する機能や特徴を見てきた。現在の新技術にあわせてApache Camelは今も進化が続いている。特にクラウド、マイクロサービスといった技術を用いたシステム開発の浸透につれ、これらに必須の様々な機能を提供しているCamelは、必要不可欠な薄いインフラとして確固たる地位を築き始めている。

Camelは普段のプログラミングの多くの側面に対応し、簡単な処理から複雑な問題にまで対応した、とても汎用的で拡張可能なライブラリだ。これはEIPに基づいたシンプルで強力な構造に支えられている。Camelでのプログラミングは驚くほどにシンプルで無駄がない。Camelでのプログラミングはコーディングであり、また設定であり、そしてそれらの調和によってプログラマの意図を直接反映させることができるものだ。

Apache Camelの開発者である<NAME>氏は、Camelのことを「ツールボックス」と表現しているが、この意図するところがいくらかでも伝わったなら幸いだ。Camelは、プログラマの能力を一段と引き上げる洗練されたツールで、すべてのJavaプログラマが学ぶ価値がある。


- [1] 
  - Organizing Microservices – Modern Integration
    - https://developers.redhat.com/blog/2017/08/02/organizing-microservices-modern-integration/
  - Reference Architecture for Agile Integration
    - https://developers.redhat.com/blog/2017/07/27/reference-architecture-for-agile-integration/ (英語) 
    - http://playintegration.blogspot.jp/2017/09/reference-architecture-for-agile.html (邦訳) 

- [2] Enterprise Integration Patterns
  - http://www.enterpriseintegrationpatterns.com

- [3] Netflix Hystrix
  - https://github.com/Netflix/Hystrix/wiki

{'fraction_non_alphanumeric': 0.08319709355131698, 'fraction_numerical': 0.01516802906448683, 'mean_word_length': 11.302793296089385, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 17, 'https://': 7, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3818919', 'n_tokens_mistral': 8970, 'n_tokens_neox': 8321, 'n_words': 224}