皆さんこんにちは。しうへいと申します。
今回はIoT向けBaaSであるPubNubに、Apache Camelから接続する方法について書きます。
PubNubを知った経緯
昨日3/11になりますが、集まれMilkcocoaオジサン。 Milkcocoa Meetup vol 8 という勉強会に参加してきました。
IoT向けBaaSとしてMilkcocoa の名前を最近よく聞いていたのと、自分自身その分野のサービスに興味があったので参加しましたが、スピーカーの皆さんが話される内容としては、そのままズバリIoTというよりは、MilkcocoaのリアルタイムWebサーバーとしての機能を活用したものが多く(もちろんセンサー系のデモもありました)、期待してたものと少し違ったかなぁ…と思っていました。
そんな折、最後のスピーカーとして、Milkcocoaエバンジェリストであるのびすけ@n0bisukeさんが、おもむろに
「PubNubって知ってる?」
「PubNubってイケてるらしいよ?」
「Milkcocoaは正直負けてるかもしんない」
「でも同じBaaSとして一緒に盛り上がっていけたらいいと思うんだよね」
(※記憶力ないので、ニュアンスで書いてます)
(追記)
のびすけさんから実際のスライドのURLをいただきましたので、こちらに関してはスライドをご覧ください。
https://speakerdeck.com/n0bisuke/pubnubtomilkcocoa-milkcocoameetup-vol9-number-mlkcca-5fen
(追記ここまで)
みたいな話をされて、ロックなエバンジェリストだなぁと思いつつ、そこでPubNubを知ることになりました。
リアルタイムWebサーバーをBaaSに移譲するというトレンド
「Backend as a Service」 という言葉の響きからは、自分はもっと大仰なものをイメージしていたのですが、もっとカジュアルに、リアルタイムWebサーバーとして使えばいいんじゃないの、というメッセージをスピーカーの皆さんから受信しました。最初は「それならApache CamelのWebsocketコンポーネントがあるからいいかなぁ」と思っていましたが、Websocketを実際扱う際の泥臭さは知るところでしたので、その部分だけ定評のある外部サービスに移譲するのも良いのかと思うようになりました。
PubNubには、Apache Camel向けのコンポーネントがすでにあった
Apache Camelについて簡単に説明すると、Javaプラットフォームで動作する、ライブラリ / サービス / フォーマット / プロトコル統合フレームワークです。ライブラリ / サービス / フォーマット / プロトコル同士の、n対nの接続および変換コードを個々に書くのは大変だから、n-x-nになるようなxを作ろう、みたいな発想から生まれたフレームワークです。
ちなみにApache Camelでは、n-xの部分をコンポーネントと呼んでいます。
2016年3月現在、コンポーネントはプロジェクトの外部で作られたものも合わせて200以上に達しています。
Apache Camel: Components http://camel.apache.org/components.html
驚くことに、今日知ったばかりのPubNubは、外部で作られたコンポーネントとして、既に上記に掲載されていました。
Camelライダーとしては、これは試してみるっきゃありません。
PubNubを使う準備をする
PubNub https://www.pubnub.com/
登録に必要なのはメールアドレスくらいでした。
特につまづきポイントなく登録が完了したので割愛します。
PubNubアプリケーションを作成して、キーを入手
ログインして [CREATE NEW APP]ボタンからアプリケーションを作成して、適当な名前をつけます。自分は「myiot」としました。
アプリケーションの詳細に入っていくと、各種キー情報が表示されます。これでPubNub側は準備完了です。

Apache Camelを使う準備をする
IDE上でMavenプロジェクトを新規作成して、依存関係を記述します。
(自分は標準でビルドツールMavenが入っているNetBeans IDEを使ってます)
セントラル・リポジトリでcamel-pubnubと検索して、追加すれば良いです。
Apache Camel側のissueで、slf4j-simpleも追加します。これで標準出力にログが出力されます。
以下は自動生成されたpom.xmlです。
<?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>com.mycode</groupId>
<artifactId>myiot</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>io.rhiot</groupId>
<artifactId>camel-pubnub</artifactId>
<version>0.1.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.6</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
PubNubコンポーネントの使い方を確認する
以下にcamel-pubnubコンポーネントの使い方が書いてあります。
https://rhiot.gitbooks.io/rhiotdocumentation/content/cloudplatform/camel_components/camel_pubnub_component.html
Apache CamelではアクセスするリソースをURIとして記述する必要があります。この書き方が分かればよいので、General URI formatの辺りに目を通します。
基本は pubnub://pubsub:channel?options で、optionsにkeyが3種類設定されていれば使えそうです。
実行コードを書く
以下のコードサンプルでは、
送信側では一秒ごとにメッセージ"foo"をPubNubにポストします。
受信側ではPubNubから受信したメッセージを標準出力しています。
package com.mycode.myiot;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.main.Main;
public class App {
public static void main(String[] args) throws Exception{
Main main = new Main();
main.addRouteBuilder(new RouteBuilder(){
@Override
public void configure() throws Exception { // ここまでApache Camelの基本共通コード
String pubKey = "ゆ○式"; // 有効な値を設定されたし
String subKey = "一般"; // 有効な値を設定されたし
String secKey = "完売"; // 有効な値を設定されたし
String pubnubEndpointUri = String.format("pubnub://pubsub:channel?publisherKey=%s&subscriberKey=%s&secretKey=%s", pubKey,subKey,secKey);
// 送信側のルール定義
from("timer:foo") // 1秒ごとに実行
.setBody(constant("foo")) // 送信内容を文字列"foo"に設定
.to(pubnubEndpointUri); // PubNubへ送信
// 受信側のルール定義
from(pubnubEndpointUri) // PubNubから受信
.to("log:foo"); // 受信内容をログに出力する
} // ここからApache Camelの基本共通コード
});
main.run();
}
}
実行結果

受信側に1秒ごとにfooが流れてきていることがわかります。ただこれだけだといまいちPubNubサーバーを通している感がないので、
ためしに、受信部分をコメントアウトした状態でApp.javaを実行します。その次に今度は送信部分をコメントアウトして、いくつかApp.javaを実行します。これにより簡易的に1対多のPub/Subを作り出します。
その場合でもやはりそれぞれにログが出力されますので、めでたくPubNubサーバーをApache Camelから使うことが出来た、ということのようです。
感想
勝手アプリを作成する際に、自前でWebsocketサーバーを立てることはもうなくなったかもなぁ、と思いました。
逆にこれまで「Websocketを使えば何とか実装できるかなぁ」でとどまっていたアイデアは、だいぶ実装しやすくなったと思います。ユーザーを識別するあたりの機能を検証する必要がありますが。
ごくごく個人的な、感想…
最近はまっているGoogleトレンドのスクリーンショットを載せておきます。(実際のページは画像をクリック)
Apache Camelの規模感を知る自分視点では、PubNubもなかなかイケてる規模感のようです。
(Milkcocoaは同名の対象が多いそうなのでやめておきました。)
PubNubもApache Camelも、国内では「知る人ぞ知る」製品だと思います。でもその「比較的知られていない」者の間にすでにコンポーネントが用意されているのですから、海外の器のデカさや先進性を実感させられます。
Milkcocoaの人は、現状だとApache Camelへの対応とか考えてないでしょうし、自分も別に求めていませんが、「PubNubに追いつけ追い越せ」論で行くと、
結局こういう細か~な対応状況で海外の製品とは差がつくのかなぁとも思ってます。
Milkcocoaに限らず国産製品全般の話ですが。どうしたらいいんでしょう。(ふわっとした終わり方)