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

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

タグ:designer

久しぶりのノーツネタです。


ノーツ9のクライアントでカレンダーを開くと、左下にこのようなセレクターが表示されます:
2015051501

ここで選択した形式でカレンダーが表示されます。自分は1週間単位で見ることが多いので、「1週間(勤務日)」で使っていることが多いです。なお「1週間(勤務日)」は月曜から金曜までの5日間を表示(土日は表示しない)、「1週間」だと月曜から日曜までの7日間が表示されます。

最近、自分の勤務が土日も含まれることが多くなってきました。というわけで、勤務用の5日表示では大事な仕事を忘れてしまいかねません。かといって「1週間(勤務日)」を残したまま「1週間」を選ぶのもわかりにくいというか・・・

こんなときこそカスタマイズです!さっそくドミノデザイナーでメールテンプレートを開いて、共有要素 - アウトライン内の NotesCalendarOutline を選択します:
2015051504


その中の「1週間」を書かれたラベルを選択して、ラベルの値を「1週間」から(例えば)「オレの1週間」に変更して保存します:
2015051502


これでノーツカレンダーを開き直すと、「オレの1週間」が選択できるようになり、選択すると7日間分のカレンダーが表示されます。これで安心して週末にも仕事のスケジュール入れられます(涙)。
2015051503




 

IBM Bluemix をはじめ、多くの便利な REST API が公開されています。REST API は HTTP プロトコルベースなので、特定のプラットフォームやプログラミング言語環境に縛られることなく、HTTP クライアント機能を持っている多くのプラットフォームやプログラミング言語から利用できるようになっています。

その一方で、IBM ノーツを使っている技術者の立場として、こういった外部の REST API をノーツからどうやって使うか、という情報があまり公開されておらず、「ノーツからは使えないんじゃないか?」と思われてしまっているように感じています。実際、ハードル高いと思う。

1点補足すると、これは「ドミノサーバー」からの話ではなく「ノーツクライアント」からの話です。ドミノサーバーであれば、Java サーブレットも使えるし、もちろんそのサーブレットからノーツデータベースにアクセスすることもできるので、連携もあまり問題ないと思うのですが、問題は「ノーツクライアント上」から「外部の」 REST API を使う、というケースです。 特に「外部の」という部分がミソで、JavaScript の AJAX などから使おうとしてもクロスサイトスクリプティング制約があったりするので、結構難しい問題だと思っています。


で、今回紹介するのは、ノーツクライアントから外部の REST API を使う方法です。"REST API" といっても、要は
 ・特定の URL に対して GET や POST でデータを送信してリクエストすると、
 ・結果が XML や JSON で返ってくるもの
という緩い定義で考えるものにします。これをノーツクライアントから実行して結果を受け取る、というものです。

今回は REST API のサンプルとして、マンホールマップの公開 API を使います。具体的には以下の URL に(GET で)アクセスすると、マンホールマップサービスに投稿されたデータから、最新20件のデータを取り出して JSON フォーマットで返す、というごく一般的(?)なものです:
http://manholemap.juge.me/searchcreated?limit=20&format=json

試しにウェブブラウザでこの URL にアクセスすると、取得結果の JSON がそのまま表示されて、こんな感じの結果になります。ちなみにこの JSON の中身の意味は・・・興味ある人はコメントなどで連絡ください、個人的に教えます(苦笑):
2015033001


この REST API にノーツクライアントからアクセスして JSON データを取得し、中身を解析してノーツで活用しよう、というのが今回の目的です。

まず最初に、これを実現するには「REST API を実行して、結果を取得する」という、ウェブ API ではごく当たり前のことを行う必要があるのですが、ノーツクライアントからこれを実行するには Java エージェントを使う必要があります。LotusScript や式関数などのマクロではノーツに関するカスタマイズ処理を記述することはできますが、TCP/IP 通信や HTTP プロトコルのレベルで処理をカスタマイズする方法は用意されていません。LSX(LotusScript eXtension) や WinSock の DLL を使って TCP/IP のソケット通信を行って・・・という手段がないわけではないと思いますが、そこまで自前で用意した上で更に HTTP プロトコルを実装、となるとさすがに非現実的です。その点、Java を使えば TCP/IP 通信は標準で持っているし、外部の便利なライブラリを使って比較的簡単に HTTP 通信を実現することもできます(更に言うと今回の例では JSON の解析も行う必要がありますが、それもライブラリに任せることができます)。 という背景もあって、今回は Java エージェントを使って REST API を実行します。

実際に Java エージェントを作る前の準備として、HTTP 通信用の Java ライブラリを用意しておきます。選択肢としてはいくつかあると思いますが、サンプルの多さなどから自分が個人的に使っているのが Jakarta Commons(Apache Commons)HTTP Client 3.1 です。この本体と、更に依存関係で必要な Logging ライブラリ、そして Codec ライブラリを全てダウンロードします。 更に実行結果の JSON テキストを取得した後の解析用に JSON ライブラリが必要になるので、これも JSON simple ライブラリをダウンロードしておきます。これらは同様の機能を持っているものであれば別のライブラリを使ってもいいのですが、以下のサンプルではこれらを使っている前提で紹介します。

以上をまとめて、以下の表のダウンロードサイトからライブラリ(のバイナリ)をダウンロードして、ダウンロードしたモジュールを展開するなどして表内右端列の4つの JAR ファイルをあらかじめ取得しておいてください。図のように同じフォルダに格納しておくと後で便利です(いずれも 2015年3月30日時点の最新バージョンです):
2015033002

ライブラリダウンロードサイト必要なファイル
HTTP Client 3.xCommons HttpClient Archivescommons-httpclient-3.1.jar
LoggingDownload Apache Commons Loggingcommons-logging-1.2.jar
CodecDownload Apache Commons Codeccommons-codec-1.10.jar
JSON simpleDownloads - JSON simplejson-simple-1.1.1.jar


では改めてノーツ上で Java エージェントを作ります。目的のデータベース(なければ新規に作って)をドミノデザイナーで開き、コード - エージェントをダブルクリックして選択後に「新規エージェント」ボタンをクリックして、エージェントを追加します:
2015033000


新規エージェント作成画面でエージェント名(図では "REST API Sample")を入力し、エージェントタイプに "Java" を選択して OK ボタンをクリックし、Java エージェントを作成します:
2015033003


新規に Java エージェントが追加されました。この中身を記述する前に、先ほど用意した4つのライブラリファイルを、このエージェント内にインポートして使えるようにしておきます。エージェント画面内の インポート - アーカイブ を選択します:
2015033004


ソースディレクトリに JAR ファイルが格納されているフォルダを指定し、インポートしたい JAR ファイルをまとめて指定して「終了」ボタンをクリックします。JAR ファイルが別々のフォルダに格納されている場合は、この手順を繰り返して全ての JAR ファイルをインポートします:
2015033005


Java エージェントのアーカイブに指定した JAR ファイルが追加されていることを確認してください。これで Java エージェント内でこれらのライブラリを使った処理を記述することができるようになりました。改めて javaAgent.java をダブルクリックして、エージェント処理の実装にとりかかります:
2015033006


ドミノデザイナー内でコードエディタが開き、javaAgent.java の編集状態になります。ここで記述された内容がこのエージェントの実行内容になります。コメントで "(Your code goes here)" と書かれた箇所の後に(というか、その前の部分を触らないように)実行内容を Java で記述します:
2015033007


今回の場合は、目的の REST API を実行して、その結果を取得する、という実装を行います。取得結果を最終的にどう扱うか(例えばノーツのデータとして格納するのか?別のデータベースに格納するのか?単に表示するだけか?など)は別に検討する必要があると思いますが、今回は結果を Java コンソールに出力する、という内容にします。なので、実装コードはこんな感じです。ここはもうノーツの世界ではなく、普通に Jakarta HTTP Client を使っているだけです:
  :
  :
  // (Your code goes here)
  HttpClient client = new HttpClient();
  GetMethod get = new GetMethod( "http://manholemap.juge.me/searchcreated?limit=20&format=json" );
  int sc = client.executeMethod( get );
  if( sc == 200 ){
    String json = get.getResponseBodyAsString();
    JSONParser parser = new JSONParser();
    JSONArray objs = ( JSONArray )parser.parse( json );
    int n = objs.size();
    for( int i = 0; i < n; i ++ ){
      JSONObject obj = ( JSONObject )objs.get( i );
      Long id = ( Long )obj.get( "id" );
      String username = ( String )obj.get( "username" );
      String text = ( String )obj.get( "text" );

      //. とりあえず整形してコンソールに出力
      String line = i + ": [" + id  + "] " + text + "(" + username + ")";
      System.out.println( line );
    }
  }
  :
  :

これで javaAgent.java およびこの(今回の例だと "REST API Sample")エージェントを保存します。


では試しにこのエージェントをノーツクライアント上で実行してみます。ノーツでこのエージェントを作ったデータベースを開きます。今回の例では最終結果を Java コンソールに出力しているので、その確認のためメニューから ツール - Java デバッグコンソールの表示 を選択します:
2015033001


こんな感じの Java コンソールウィンドウが開きます。実行結果はこの中に表示されるので、ウィンドウを閉じずにこのまま続けます:
2015033002


改めてノーツクライアントの画面に戻り、メニューから アクション - (作ったエージェント名(今回の例だと "REST API Sample")) を選択して、上記で作成した Java エージェントを実行します。実行方法はこれ以外にトリガを用意しても構いませんが、動作確認目的であれば、この方法が簡単でオススメです:
2015033003


作成した Java コードが正しく実行されると、REST API が呼び出され、結果の JSON テキストがパース&解析されて、取得したデータが1行ずつ Java コンソールに表示されるはずです:
2015033004


この例だと取得結果を Java コンソールに表示するだけでしたが、この結果を DB に格納するなり、これを元に HTML を作ってブラウザで表示する(参考記事)なり、色々な応用があると思います。ともあれノーツクライアントからであっても一般的な REST API を実行することができました。

後はこれを IBM Bluemix 上の各種 Watson API など、様々な外部 REST API を使う形で応用できると思っています。ノーツのデータを元に人工知能 API を使った解析を行うなど、いろんな使い方の可能性が広がると思っています。

 

このページのトップヘ