まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:ibm

IBM Bluemix からも提供されている、スケーラブルな NoSQL DBaaS である Cloudant 。データの読み書きには REST API が提供されており、ウェブアプリケーションだけでなく、スマホのネイティブアプリなど色々なアプリケーションから利用することができます。
2017032101


この Cloudant はいわゆる「JSON ドキュメント」を格納するデータベースなのですが、バイナリデータ(というかファイル)を扱う機能("attachement")も持っています。

以下にバイナリデータを格納する方法を紹介します。まずは JSON データを無視して「バイナリデータだけを新たに格納する場合」は以下のような JSON データを新規作成します(赤字はコメント):
{
  "_id": "D001",  Cloudant 上でのドキュメントID、省略した場合は作成時に自動的に割り振られる
  "_attachments": { この _attachments オブジェクトがバイナリ保存時の肝
    "A001": {     任意に付ける Attachment 名、取り出し時のURLに指定する
      "content_type": "image/jpeg",  バイナリデータの Content-Type
      "data": (バイナリデータを Base64 エンコードしたテキストデータ)
    }
  }
}

上記のデータを(普通の JSON ドキュメントと同様に)以下の URL に対して POST リクエストすると、このバイナリデータを含むドキュメント(と attachment )が新規に Cloudant 内に作成されます:
https://(Cloudant のホスト名)/(データベース名)


また、作成したバイナリデータを取り出す場合は、以下の URL に対して GET リクエストを実行します:
https://(Cloudant のホスト名)/(データベース名)/(ドキュメント ID)/(Attachment 名)


バイナリデータだけのドキュメントを作成する場合は上記の方法でした。一方、バイナリデータも含む JSON データを保存する場合は、以下のような JSON データを用意して、同様に POST します:
{
  "_id": "D001",
  "myname": "abc",   この2つの値が普通の JSON データとして扱われる部分
  "myvalue": 123,
  "_attachments": {
    "A001": { 
      "content_type": "image/jpeg",  
      "data": (バイナリデータを Base64 エンコードしたテキストデータ)
    }
  }
}

取得時には content_type で指定したデータ型が有効になってレスポンスが返ってきます。なので、例えばバイナリデータとして JPEG 画像データを格納し、その際の cotent_type 値に "image/jpeg" などの正しい型が指定されていれば、取得 URL にブラウザでアクセスすればそのまま画像を表示することができます:
2017032102

(↑ Cloudant 上に格納した画像データを直接 URL 指定で表示している様子)


一般的にはファイルなどのバイナリデータをネット上のストレージに格納する場合は Object Storage などを使うことが多いと思っています。が、Content-Type を意識して取り出したり、「(添付ファイルなどの)JSON ドキュメントに紐付いたバイナリデータ」として利用する場合に便利な機能だと思っています。


なお、Cloudant の Attachment 関連 API についてはこちらを参照ください:
https://docs.cloudant.com/attachments.html
 

IBM InterConnect 2017 の期間中に IBM Bluemix Platform にドイツリージョン(eu-de)が追加されました。記念に早速ランタイムアプリを1つデプロイして公開してみました:
http://spen.eu-de.mybluemix.net/


このアプリはスマホ用(正確にはジャイロセンサーを搭載したスマホ用)なので、試しに使ってみる場合は上記 URL にスマホのブラウザでアクセスしてみてください。以下のような画面が表示されます:
IMG_0430


画面の下半分あたりを指でタップし、離さずにそのまま空中でスマホを振って、文字等を一筆書で書いてみてください。書き終わったらタップした指を離してください:
IMG_0430


指でタップしていた間にスマホの先端が動いた軌跡が画面内に表示されます。また画面上部の表にはタップしていた間のスマホの左右(LR)や前後(FB)の動きが数値として表示されます(ちなみに DIR は向いている方向角で、今回の軌跡描画では使っていません):
IMG_0431


これだけのアプリですが、全て1つの HTML だけで実現しています。スマホの動きは JavaScript でジャイロセンサーにアクセスしてその値を取得し、軌跡の描画には HTML5 の Canvas を利用しています。また HTML 自体では Canvas は非表示としており、画面に表示されているのはこの Canvas を描き終えたタイミングで動的に画像データを生成して、その画像を <img> タグで動的に表示しています。

スマホのジャイロデータを JavaScript だけで取得するとか、Canvas データから画像データを生成するとか、それなりに凝った処理を行っているこの HTML を Github で公開しました:
https://github.com/dotnsf/SPen/


MIT ライセンスで公開しています。勉強目的なり、取得データを使って別の処理を行うよう改造するなり、いろんな応用はできると思うので、よかったら遊んでみてください。

IBM Bluemix の提供サービスの1つに WAS(WebSphere Application Server) があります:
2017031901
(https://console.ng.bluemix.net/docs/services/ApplicationServeronCloud/index.html)


この IBM Bluemix の WAS サービスを利用する場合、サービスインスタンスのダッシュボード画面から VPN に必要なモジュールや設定ファイルをダウンロードして、VPN で WAS ホスティングサーバーに接続した上で管理コンソールにアクセスしたり、アプリケーションをデプロイしたり、といった手順で管理・利用することが可能になります。

そして必要な設定を変更したり、アプリケーションをデプロイした後に(URL を通知したりして)ユーザーへ公開するわけですが、ユーザーが利用する段階では管理者のように VPN などの利用を条件にしたりはせず、パブリックネットワークから直接アクセスさせるという使い方も少なくないと思います。そのための設定方法を紹介します:
2017031900



まず、IBM Bluemix の WAS サービスをパブリックネットワーク上に公開するには、WAS の HTTP サーバーを 80(http)/443(https) 番ポートで起動させる必要があります(少なくともユーザーにアクセスさせるアプリケーションは 80/443 番ポートで listen している必要があります)。そのため事前に VPN 接続をした状態で WAS 側の設定変更を済ませておく必要があります。WAS Liberty / WAS それぞれの起動ポート番号変更手順については以下を参照ください:
WAS Liberty Core を 80/443 番ポートで動かす
WAS を 80/443 番ポートで動かす


なお、以下は WAS Liberty Core 版の図を使ったりして紹介しますが、WAS フルプロファイル版でも同様だとお考えください。

まずは 80/443 番への起動ポート番号の変更を行った WAS(Liberty) のダッシュボードを IBM Bluemix 上で開きます。以下のようにホストの IP アドレスが確認できる状態になっているはずです(この IP アドレスはプライベートアドレスなので、アクセスするには VPN 接続が必要です):
2017031901


VPN 接続が確立していれば、このアドレスをウェブブラウザで開くと、WAS(Liberty) のトップページが表示されます。他にデプロイ済みのアプリケーションがある場合も同様です:
2017031902


ではこのページに VPN なしでパブリックネットワークからアクセスできるようにするための設定を行います。上記のダッシュボードページに戻り、「パブリック IP へのアクセスを管理」ボタンをクリックします:
2017031903


最初の段階ではまだパブリック IP アドレスが割り振られていないので、「パブリック IP アドレスを要求」します:
2017031904


しばらく処理を待つと先程の画面に戻ります。この時点ではパブリック IP アドレスが割り振られていますが、まだ VPN 内のホストへの転送がクローズされています。再度「パブリック IP へのアクセスを管理」をクリックします:
2017031906


割り振られた IP アドレスからの利用ができるよう、「アクセスのオープン」をクリックします:
2017031907


三度元の画面に戻ってきました。今回は IP がオープンされて、この段階でパブリックアクセスが可能になりました:
2017031908


最後に、(接続済みであれば VPN 接続を切断してから)パブリック IP アドレスにウェブブラウザでアクセスし、元の画面が表示できていることを確認します:
2017031909


なお、この仕組の説明などは以下のドキュメントを参照ください:
https://console.ng.bluemix.net/docs/services/ApplicationServeronCloud/networkEnvironment.html#configureLibertyForPublicAccess


IBM Notes 9.0.1 の FP(Feature Pack) 8 がリリースされました。有効なサポート契約をお持ちであれば、以下の FixCentral サイトからダウンロードして適用いただくことが可能です:
http://www-01.ibm.com/support/docview.wss?uid=swg24037141


適用後にメニューから ヘルプ - IBM Notes について を実行すると、リリースバージョンが変更できていることが確認できます。自分の環境にも早速適用してみました:
2017030901


実は以前にこのブログの中で、「ノーツでワトソン」というエントリを紹介したことがありました(比較的アクセス数の多い、人気エントリの1つです):
http://dotnsf.blog.jp/archives/1062359514.html

↑この中でも触れているのですが、Watson API のセキュリティ仕様変更があり、JDK 1.8 未満の環境から Watson の REST API へ https リクエストを実行するとエラーが返されるようになってしまっていました(ノーツは JDK 1.6 を使っていたのでエラーが発生していました。上記エントリはその回避方法も含めて紹介しているものです)。

が、今回の 9.0.1 FP8 では、内蔵 JDK バージョンが 1.8 に変更される、という大きな変更が含まれていることになっています。これによって Watson API のセキュリティ要件を満たすことになるので上記エントリのような回避策も不要になることが期待できます。

というわけで、IBM Notes 9.0.1 FP8 の実際の JDK バージョンを確かめるためのプログラムを作って実行してみることにします。まずは Domino Designer で適当なデータベースアプリケーションを作り、その中に Java のエージェントを新規に作成します(エージェントの名称は FP8 としました):
2017030902


Java エージェントの中身を記述します:
2017030903


具体的には以下のようなコードを記述しています(初期状態の内容と比較して、青字部分を追記しています):
import java.util.Properties;

import lotus.domino.AgentBase;
import lotus.domino.AgentContext;
import lotus.domino.Session;

public class JavaAgent extends AgentBase {
  public void NotesMain() {

    try {
      Session session = getSession();
      AgentContext agentContext = session.getAgentContext();

      // (Your code goes here)
      Properties props = System.getProperties();
      props.list(System.out);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}

↑システム内の全プロパティを取得して、標準出力(System.out)にプロパティ名とその値を表示する、という内容です。Java のバージョンもプロパティの1つなので、この出力結果の中に含まれているはずです。

このエージェントをメニューから実行できるよう、基本プロパティのトリガーはイベントで「アクションメニューの選択」、対象は「データベースの全ての文書」とした上で、このエージェントを保存します:
2017030904


では作成したエージェントを実行してみます。結果は標準出力に出されるので、あらかじめメニューのツールから、Java デバッグコンソールの表示 を選択して、出力画面を表示しておきます:
2017030905


改めてメニューから アクション - FP8 を実行します:
2017030906


するとエージェントの実行結果が Java デバッグコンソールに追加記載される様子が確認できます:
2017030907


画面を少しずつ下にスクロールしていくと、"java.version" というプロパティの値が "1.8.0" になっていることが確認できました。ちゃんと(?) 1.8 が使われているようです:
2017030908


 というわけで、IBM Notes 9.0.1 FP8 からは JRE/JDK 1.8 が使えるようになりました。これで Java プログラミング時に互換性を心配しながらコーディングする必要はなくなりました。


前2回の続きです:
IBM Bluemix にカスタムサービスを追加する(1/3)
IBM Bluemix にカスタムサービスを追加する(2/3)


前回作成した REST API を実際に IBM Bluemix のカスタムサービスとして登録し、利用するまで(正確には使用を終えてカスタムサービスから削除するところまで)の手順を紹介します。なおこの手順はコマンドラインツールである cf が必要になるので、インストールしていない場合は各自の環境にあった cf をあらかじめダウンロード&インストールしておいてください:
https://github.com/cloudfoundry/cli/releases


また、今回カスタムサービスとして登録する REST API は前回紹介した app.js が https://dotnsf-operation.mybluemix.net/ にデプロイされて動いているものとします。以下の説明でのこのホスト名部分を実際にみなさんがデプロイしたホスト名に合わせて読み替えてください:
2017021401

2017021401


まず最初に、以下で登録するカスタムサービスをバインドして動作確認するためのランタイムを用意しておきます。動作確認用のアプリケーション(後述)を PHP で用意したので、IBM Bluemix 上に PHP のランタイムを1つ作成します(以下の例では teyande-php-env という名前で作成しています)、なおこの段階ではサービスは何もバインドしないでください:
2017021402


このランタイムに以下の内容の PHP アプリケーションをプッシュします:
https://github.com/dotnsf/phpEnv


上記アプリケーション(index.php)はシンプルに「ランタイムサーバー上の全環境変数とその値を表示する」というアプリケーションです。プッシュ後にサーバーにアクセスすると以下のような画面になります。この時点ではサービスを1つもバインドしていないので、環境変数 VCAP_SERVICES の値は空オブジェクトを示す "{}" となっていることが確認できるはずです:
2017021403


ここまでで準備は完了です。では前回紹介したサービスを IBM Bluemix のカスタムサービスとして登録した上でインスタンス化し、このランタイムにバインドした上で、この環境変数がどのように変わるかを確認してみます。

コマンドプロンプトかターミナルを起動し、上記の PHP ランタイムと同じデータセンター(この場合は US-SOUTH)の自分の組織に cf コマンドでログインします:
2017021404


カスタムサービスを利用するにためには Cloud Foundry の「サービスブローカー」(カスタムカタログのように理解してください)に登録しておく必要があります。まず現在のサービスブローカー一覧を確認するため "cf service-brokers" コマンドを実行して、この時点では何も登録されていないことを確認します:
2017021301
 ↑"No service brokers found"(何も登録されていません)です


ではサービスブローカーを新規に1つ作成します。以下のパラメータを付けてコマンドを実行します:
> cf create-service-broker サービスブローカー名 認証ユーザー名 認証パスワード サービスの基本URL --space-scoped
2017021302


今回、サービスブローカー名は "dotnsf-operation" とします。認証のユーザー名とパスワードは dotnsf-operation の Catalog API などが実行される時用に指定した auth_user / auth_pass の値を指定します(詳しくは前回の記事参照)。サービスの基本 URL は今回 "https://dotnsf-operation.mybluemix.net" です。そして最後にオプションの "--space-scoped"(同一組織内のユーザーが使えるサービスとするための指定)を加えています。

コマンドが成功したことを確認し、再度 "cf service-brokers" を実行してみます。先程は結果に何も含まれていませんでしたが、今度は直前に作成したばかりの "dotnsf-operation" サービスブローカーが、指定した URL で登録されていることを確認してください:
2017021303


これで dotnsf-operation API がカスタムカタログに登録された状態になりました。ただ IBM Bluemix のウェブ UI ではカスタムカタログを表示する画面が存在していないので、この時点ではまだウェブ UI には現れませんが、cf からは同様にインスタンスを作成することができるようになっています。

というわけで、続けて cf でこのサービスをインスタンス化してみます:
> cf create-service サービスブローカー名 プラン名 サービス名

サービスブローカー名は dotnsf-operation の Catalog API(GET /v2/catalog) 内で定義したもの(今回の場合は dotnsf-operation-service)を指定します。プランも同様に Catalog API 内で定義したもの(今回は "free" と "enterprise" の2つ)の中から指定できますが、今回は "free" を指定しています。最後に IBM Bluemix 内でのサービス名として "dotnsf-operation-1" と指定しています:
2017021304


ここまでの手続きが完了すると、dotnsf-operation サービスがインスタンス化され、ウェブ UI の利用中サービス一覧の中にも表示されるようになります:
2017021301


この時点でサービスを選択し、管理タブを開くと Dashboard API で定義した内容が表示されるはずです(https で Dashboard API にアクセスできることが条件です):
2017021000


ではこのサービスを最初に作成した PHP ランタイムにバインドしてみましょう。PHP ランタイムの画面に移動し、接続タブの「既存に接続」をクリックします:
2017021302


現在利用中のサービスインスタンスの一覧が表示されます。その中に "dotnsf-operation-1" という名前のサービスが含まれているはずなので、これを選択して「接続」をクリックします。そしてこの内容をランタイムの環境変数にも反映させるため「再ステージング」します:
2017021303


改めて同ランタイムの接続タブを参照すると、"dotnsf-operation-1" サービスが追加されていることを確認できます。ここで「資格情報の表示」をクリックします:
2017021304


今回の dotnsf-service の Bind API では credentials 情報として uri だけを追加していました。そのためこのサービスインスタンスの資格情報にも uri 1つだけが credentials 情報として表示されていることが確認できるはずです:
2017021305


改めてランタイムのトップ画面にアクセス(リロード)します。今回は先程と異なり dotnsf-operation-1 サービスがバインドされているので、環境変数 VCAP_SERVICES は空オブジェクトではなく、dotnsf-operation-1 の情報が表示されているはずです。credentials 情報も先程確認したものと同じものが表示されています:
2017021306



・・・というわけで、IBM Bluemix のカスタムサービスを作成して、登録して、インスタンス化して、ランタイムとバインドして環境変数に反映させる、という一連の作業ができることを確認できました!

最後に使い終わったサービスブローカーを削除する手順を紹介しておきます。まず(同サービスブローカーを使っているランタイムからのバインドを全て解除した上で)サービス一覧画面からインスタンス化されたサービスを削除します:
2017021305


サービスが削除されるとウェブ UI からは見えなくなります。が、まだサービスブローカーには登録されているので、以下の cf コマンドでサービスブローカーからも削除します:
> cf delete-service-broker サービスブローカー名
2017021306


このコマンドが成功すると、サービスブローカー一覧からも削除されます。念のため "cf service-brokers" コマンドで確認します:
2017021307




久しぶりの超大作ブログとなり、3回に分けて紹介しましたが、IBM Bluemix のカスタムサービスを作るために実装しないといけない内容や、実装後の登録方法などを紹介できたつもりです。自分が作った REST API を IBM Bluemix に統合して使いたい場合や、公式なサードパーティ API としての登録を検討する場合に必要となる実装がどんなものかを説明しました。

今回紹介した内容はあくまで「同一組織内でのみ有効なカスタムサービス」の登録方法および手順の紹介でしたが、全 IBM Bluemix ユーザー向けに実装する場合であっても同様の API 実装は必要になります。そういったエコシステムを活性化する上での役立つ情報になれば幸いです。


(参考)
 https://www.ibm.com/blogs/bluemix/2017/01/extend-bluemix-service-broker/

このページのトップヘ