このエントリでは、Oracle Coherenceの機能、
REST APIを取り上げます。
Oracle CoherenceとOracle Service BusはOracle Service Bus内部で統合されており、ビジネスサービスの構成時にCohrence Gridキャッシュを利用することができます(Service Result Cache)。Oracle Service BusのWebコンソールから、オブジェクト/応答の更新ポリシーを設定でき、レスポンスの一意性を特定する識別パラメータを定義できます。
対してCoherenceのREST APIは、新しいアーキテクチャの設計の実現を可能にする他の生活必需品向けに両製品を統合することができます。stardardサービスや特にREST(
JSONと
XML)を通じて相互運用する簡単なサービスとしてのCoherenceノードを考えてみましょう。企業の共有サービスとしてCoherenceを考えると、様々なプロトコル(トランスポートとエンベロープ)がアクセスできる、中央集中型のMap-Redule実装をすることができます。
まだコネクタとコードを想像する人にとっては驚くべき進歩でしょう。この手の統合は、カスタムコードを書いたり、自分で面倒を見なければならない複雑な実装は不要です。付加価値として、独立して、両方の製品がそれぞれ素晴らしい価値によりユニークなものであり、シンプルで堅牢な統合から生まれます。
すでに述べたように、このシナリオにより、これら2つの製品の列の後ろに隠された新たな扉があることがわかります。この扉は次世代アプリケーションにウィンクするエンタープライズアーキテクチャのための新しいアイデアや視点につながります。シンプルでダイナミック、おそらくモバイルやweb 2.0(訳注:表現が古いですが、原文のままです)に向かう扉です。
以下は、CoherenceのREST APIを使用して、これら2つの製品を統合する方法をご説明する上で役立つ、小型で簡単なデモです。このデモは、このアプローチを使って、新しいエンタープライズアーキテクチャを想像することも目的としています。
構成しているテクノロジーに関係なく、企業アプリケーションから簡単に情報を取り込むアラートの集中管理システムを作成してみましょう。Service Busで公開されているサービスを使い、表現用の標準プロトコルとして
RSSを使用します。関心あるものや、カテゴリ、作成者、タイトル、日付別などによって検索・抽出したものだけを閲覧することができる、というものです。
このシステムの実装手順は非常に簡単です。以下のように簡単にご使用の環境内に複製することができます。デモはOracle CoherenceとOracle Service Busの統合が非常に簡単であることを知ってもらうこと、そして新しい技術的アプローチへの想像を刺激することを意図しています。
1) 2個の製品をインストールします。必要に応じて製品インストールガイドを確認して下さい。
2) アラート集中管理システムを作成するので、異種アプリケーションが送信するさまざまな警告の情報を保存・整理するために有用な、警告の属性を含む構造体定義が必要です。以下のように、アラーム情報の標準的なプロパティを含むAlertという名前のJavaクラスを作成しました。
- Title(タイトル)
- Description(内容)
- System(発行システム)
- Time(時間)
- Severity(緊急度)
3) Coherenceノード用に構成ファイルを作成して、(JavaのネイティブAPI、C++、C、.NETだけでなく)REST/HTTPプロトコルからAlertオブジェクトをGrid内に保存できるようにしましょう。Coherence用の2個の最小限の構成ファイルは次のとおりです。
coherence-rest-config.xml
<?xml version="1.0"?>
<rest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-rest-config"
xsi:schemaLocation=
"http://xmlns.oracle.com/coherence/coherence-rest-config
coherence-rest-config.xsd">
<resources>
<resource>
<cache-name>alerts</cache-name>
<key-class>java.lang.String</key-class>
<value-class>com.oracle.cohsb.Alert</value-class>
</resource>
</resources>
</rest>
resty-server-config.xml
<?xml version="1.0"?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>alerts</cache-name>
<scheme-name>dist-http</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<distributed-scheme>
<scheme-name>dist-http</scheme-name>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
<proxy-scheme>
<service-name>ExtendHttpProxyService</service-name>
<thread-count>5</thread-count>
<acceptor-config>
<http-acceptor>
<local-address>
<address>localhost</address>
<port>8080</port>
</local-address>
</http-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>
この最小限の設定により、localhostの8080/tcpから、HTTP-RESTで接続できるalertsという分散キャッシュが利用できます。また、オブジェクトはoracle.cohsb.Alertという型です。
4) 以下は、アラートメッセージを表す簡単なJavaクラスです。
package com.oracle.cohsb;
import java.io.Serializable;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="alert")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Alert implements Serializable{
private static final long serialVersionUID = -6098965042516514325L;
protected String title;
protected String description;
protected Date time;
protected String system;
protected String severity;
public Alert(String title, String description, Date time, String system) {
super();
this.title = title;
this.description = description;
this.time = time;
this.system = system;
}
public Alert() {
super();
}
public String getSeverity() {
return severity;
}
.....
5) このタイミングでCoherenceノードを立ち上げて、HTTPプロトコルでAlert型のXMLやJSONオブジェクトをリスニングし、"alerts"キャッシュを管理できるようにしておきましょう。Coherenceノードのクラスパスには、Alertクラス以下のCoherenceのライブラリ、設定ファイルを含めておきましょう。
クラスパスを設定したら、以下のパラメータを指定して、Coherenceクラス
"com.tangosol.net.DefaultCacheServer" を起動します。
-Dtangosol.coherence.log.level=9
-Dtangosol.coherence.log=stdout
-Dtangosol.coherence.cacheconfig=[PATH_TO_THE_FILE]\resty-server-config.xml
6) プロシージャ(訳注:テストクライアントのことです)を作成して、Coherenceの設定をテストしたりカスタムのアラートをキャッシュに追加したりしてみましょう。この機能を実現するテクノロジーは、JavaScript、Python、Ruby、Scala、C++、Javaとたくさんありますが、それはCoherenceが使えるプロトコルがHTTP/JSONもしくはXMLだからです。
このデモではJavaを使うことにします。今回は、キャッシュにアラートを送信するメソッド、キャッシュの中身を取得するメソッド、そしてこれらのメソッドを実行するためのmainメソッドを実装しています。
package com.oracle.cohsb;
import java.io.BufferedReader;
import java.io.Console;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class UrlUitl {
private final static String TARGET_URL="http://localhost:8080/alerts";
private static String TITLE,DESCRIPTION,SYSTEM,SEVERITY,TIME;
public static void main(String[] args) {
try{
/*
Console console = System.console();
TITLE = console.readLine("Alert Title? ");
DESCRIPTION = console.readLine("Alert Description? ");
SYSTEM = console.readLine("Alert System? ");
SEVERITY = console.readLine("Alert Severity? ");
TIME=new Date().toString();
*/
/** ECLIPSE WORKAROUND */
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Alert Title? ");
TITLE = bufferedReader.readLine();
System.out.println("Alert Description? ");
DESCRIPTION = bufferedReader.readLine();
System.out.println("Alert System? ");
SYSTEM = bufferedReader.readLine();
System.out.println("Alert Severity? ");
SEVERITY = bufferedReader.readLine();
TIME=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date());
/** END ECLIPSE WORKAROUND **/
if(putRest())
getRest();
}catch(Exception e){
e.printStackTrace();
}
}
private static boolean getRest()throws Exception{
String qq="time is not null";
//String qq="system = 'Web Browser' AND severity = 'Fatal' AND title LIKE '%Javascript%'";
String ss=URLEncoder.encode(qq);
URL rest = new URL(TARGET_URL+"?q="+ss);
System.out.println();
System.out.println();
System.out.println("***** QUERY CACHE FOR ALERTS ****");
System.out.println("URI: "+rest.toString());
System.out.println();
System.out.println();
URLConnection yc = rest.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
return false;
}
private static boolean putRest()throws Exception{
URL url = new URL(TARGET_URL+"/"+new Random().nextInt(100000));
String JSON_ALERT="{"
+"\"title\":\""+TITLE+"\",\"description\":\""+DESCRIPTION+
"\",\"time\":\""+TIME+"\",\"system\":\""+SYSTEM
+"\",\"severity\":\""+SEVERITY+"\"}";
System.out.println();
System.out.println();
System.out.println("***** PUT ALERT IN CACHE ****");
System.out.println();
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setRequestProperty("Content-Type", "application/json");
httpCon.setRequestMethod("PUT");
OutputStreamWriter out = new OutputStreamWriter(
httpCon.getOutputStream());
System.out.println(JSON_ALERT);
out.write(JSON_ALERT);
out.flush();
out.close();
InputStream in = httpCon.getInputStream();
BufferedReader res = new BufferedReader(new InputStreamReader(in, "UTF-8"));
StringBuffer sBuffer = new StringBuffer();
String inputLine;
while ((inputLine = res.readLine()) != null)
sBuffer.append(inputLine);
res.close();
return true;
}
}
public void setSeverity(String severity) {
this.severity = severity;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
}
特別なライブラリをクラスパスに追加していません。(JSON構造体は静的に定義されています)。実行時には、タイトル、説明などのいくつかの情報を要求し、アラートを編集、キャッシュに送信し、同じキャッシュに対して照会を実行します。他の技術、例えばJavaScriptコードを含む単純なHTMLページや、PythonやRubyなどを使用して、同じようなプロシージャを作成するのもよい練習になるかと思います。
7) では、Oracle Service Busを構成して、この2つの製品を統合しましょう。まず、Oracle Service Bus内部のアラートシステムと、Coherenceノードをベースとするアラート集中管理システムを統合しましょう。こうした仕組みにより、監視ツールやプロキシメッセージフロー内から直接アラートを投げることができ、直接Coherenceノードにアラートを保存することができますが、今回はOracle WebLogic Server/Service BusのJMSの技術を使用することにします。Oracle WebLogic Server管理コンソールにアクセスし、新しいJMS接続ファクトリと新しいJMS送り先(キュー)を作成し、セットアップします。
Oracle Service Busプロジェクト内で新しいリソースの「アラート送り先」を作成します。この「アラート送り先」リソースは先ほど作成したJMS接続ファクトリとJMS送り先を使って構成します。
最後に、JMS送り先に入ったメッセージアラートを削除してCoherenceノードに送信するため、ビジネスサービスとプロキシサービスをOracle Service Busプロジェクトに追加します。ビジネスサービスはCoherenceのRESTサービスにメッセージ送信するものですので、メソッドアクションとしてPUTを使います。
プロキシサービスは、JMS送り先に追加された全てのメッセージを収集し、集めたメッセージに対してXQuery変換を実行して有効なXML/Alertオブジェクトに変換して、ビジネスサービスを介してCoherenceサービスに送信します。
メッセージフローパイプラインにXQuery変換が組み込んでいます。
信じられないかもしれませんが、何も開発せずに、Oracle Service Busのネイティブのアラートシステムと、簡単にCoherenceノードを組み合わせてアラート集中管理システムを統合しました。
では、テストしてみましょう。テスト用に、プロキシが呼び出されるたびに"アラートの送信先"を使ってアラートを生成できるようなプロキシサービスを作成します。
ダミーのアラートを生成したプロキシサービスを呼び出してから、Webブラウザで http://localhost:8080/alerts/ を開くと、Coherenceノードに追加されたアラートを確認できるはずです。
8) では最後の手順です。新しいメッセージフローを作成して、標準モードで結果の検索や表示に使えるようにします。このために、
RSSの標準的な表現を使って、多種多様なデバイス(iPhoneやAndroidのリーダー)で整形した結果を表示できるようにしました。リクエスト時に問い合わせ内容を指定されているので、ニーズに関連するフィードや項目を返すことができます。
これを実現するため、ビジネスサービス、プロキシサービス、および成形した
RSSの標準文書の形でCoherenceノードから返すべく、アラートのコレクションを変換するために必要な
XQuery変換を新たに作成します。
ではまずこのリソース(XQuery)から始めることにします。これはCoherenceノードから
RSS2.0フィードのフォーマットに合わせて成形して返すアラートのコレクション/XMLを変換する役目があります。
ビジネスサービスは、CoherenceキャッシュにあるアラートをREST APIで検索するものです。
で、最後のリソースであるプロキシサービスですが、これは種々のモバイルデバイスや伝統的なWebリーダに対してRSSフィードとして公開されます。任意のクエリに対して、ビジネスサービスが返す結果をRSS 2.0フィードの形に変換するものです。
変換フェーズ(AlertからFeedへの変換)を持つメッセージフローです。
最後にいくつかの小さなトリックとして、ビジネスサービスにルーティング中に、HTTPヘッダの"
Accept"を付けておき、JSONではなくXMLの回答を取得できるようにしておきましょう。アラートのサブセットを要求するURL中のクエリを確認してください。
このデモではまた、リクエストにCoherenceのパラメータを静的に追加し、日付でソートされ、1から最大100まで並べた結果をCoherenceから受け取れるようにしました。
sort=time:desc;start=0;count=100
できました。信じられないでしょうが、これでできあがりです。2個の製品、Oracle CoherenceとOracle Service Busを組み合わせ、両者の品質と機能 -RASP (Reliability, Availability, Scalability, Performance / 信頼性、可用性、拡張性、性能)- を継承しています。
では、モバイル端末やPC用のWebブラウザから発行されたRSSにアクセスしてみましょう。
ではテストURLをいくつか…。
- 最新の100件のアラートを取得する
http://localhost:7001/alarms
- 時間プロパティがNULLでないアラートを取得する(time is not null)
http://localhost:7001/alarms?q=time+is+not+null
- システムプロパティが”Web Browser”のもの(system='Web Browser')を取得する
http://localhost:7001/alarms?q=system+%3D+%27Web+Browser%27
- システムプロパティが”Web Browser”で、かつ緊急度プロパティが”Fatal”、タイトルプロパティに”Javascript”を含むアラートを取得する
(system = ‘Web Broser’ and severity = ‘Fatal’ and title like ‘%Javascript%’)
http://localhost:8080/alerts?q=system+%3D+%27Web+Browser%27+AND+severity+%3D+%27Fatal%27+AND+title+LIKE+%27%25Javascript%25%27
[訳注]このURLは、アラートを収集しているので、ポート番号は他のURLと異なり、8080を使用しています。
より複雑なクエリを作成したいのであれば、CohQL(Coherence Query Language)のドキュメントを参照されることをお勧めします。
Oracle® Coherence Developer's Guide Release 3.7.1
Using Coherence Query Language
http://download.oracle.com/docs/cd/E24290_01/coh.371/e22837/api_cq.htm .
[参考資料]
このデモは以下からダウンロードできます。
http://blogs.oracle.com/slc/resource/cosb/coh-sb-demo.zip
原文はこちら。
http://blogs.oracle.com/slc/entry/oracle_coherence_and_service_bus