ただし、新しいWebサービスが利用可能となった時に、それを発見するための単純な方法が必要なくなったわけではなく、他の領域では作業が行われています。例えばW3CのWeb Services Addressing Working Groupでは、Webサービス・エンドポイントのアドレッシングと参照の方法を開発するための作業を続けています。残念ながら、W3CやOASIS組織の努力の下で開発されつつあるWS-Addressing仕様も、その間連のWS-* 仕様も、新しいWebサービスが利用可能となった時にクライアントに通知するための単純な方法を提供する、という基本的な問題には対応していません。
ここにAtom 1.0が登場します。過去1年間、IETFのAtom Publishing Format and Protocol Working Groupは、(その目的の一部として)Webベースのリソースが作られた場合、あるいは変更された場合に、クライアントが通知を受信できるよう、標準XMLフォーマットを定義するための作業を続けています。Atom Syndication Formatは、元々はWeblogやニュースの配信をターゲットにしたものですが、任意のデータ・フォーマットを配布するための手段としての機能を備えています。
この先では、今や消滅状態となったWS-Inspectionの機能的な置き換えとして、Atom 1.0仕様とWeb Services Addressing 1.0仕様とを組み合わせて使う方法の紹介と解説を行います。この記事を読む前提として、AtomとWS-Addressingの両方の仕様を基本的に理解していることが必要です。また、両方の仕様のコピーを手元に置き、この記事を読みながら参照するようにお勧めします(参考文献に、これらの仕様へのリンクがあります)。
この記事に付随するコードに関する注意として、この記事で取り上げている例は、IBM WebSphere® Application Server V6.0(以下、Application Serverと呼びます)に埋め込みのWebサービス・ランタイムに基づいています。同じ概念は他のWebサービス・ランタイムにも容易に適用できますが、このコードを実行しようとする場合には、Application Serverをインストールする必要があります。参考文献には、無料でダウンロードできる試用版へのリンクがありますので、参考にしてください。
サンプル・コードでは、Atom 1.0文書(リスト1)を生成するためにJava™サーブレットを利用しています。この文書は、Application Server環境にデプロイされたWebサービスそれぞれに対して、1つのエントリーを含んでいます。新しいWebサービスがデプロイされると、必ず新しいエントリーがAtomフィードに追加されます。クライアントは、新しいエントリーがないかどうか定期的にフィードをポーリングすることによって、新しいサービス、または改訂されたサービスを検出することができます。
フィードの中の各エントリーは、新しいサービス・エンドポイントにアクセスするために必要な全情報をクライアントに提供するために、エンドポイントを記述するWS-Addressing Endpoint Referenceを持ちます。
リスト1. Atom + WS-Addressingのフィード
<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en"
xmlns="http://www.w3.org/2005/Atom"
xmlns:fh="http://purl.org/syndication/history/1.0">
<id>http://localhost:9085/wsatom/services.atom</id>
<title>Web Services on localhost</title>
<fh:incremental>false</fh:incremental>
<updated>2005-08-23T23:00:35Z</updated>
<link href="http://localhost:9085/wsatom/services.atom"
rel="self"
type="application/atom+xml"/>
<author>
<name>WebSphere</name>
<uri>http://localhost:9085/wsatom</uri>
</author>
<entry>
<id>tag:localhost,2005:/services/HelloWorld</id>
<title>HelloWorld</title>
<summary>Service 'HelloWorld' is available at
http://localhost:9085/wsatom/services/HelloWorld</summary>
<link href="http://localhost:9085/wsatom/services/HelloWorld"
rel="alternate"
title="Service Endpoint"/>
<link
href="http://localhost:9085/wsatom/services/HelloWorld?wsdl"
rel="alternate"
title="WSDL"
type="application/wsdl+xml"/>
<updated>2005-08-23T23:00:35Z</updated>
<content type="application/xml">
<EndpointReference
xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://localhost:9085/wsatom/services/HelloWorld
</Address>
</EndpointReference>
</content>
</entry>
</feed>
|
このフィードがどのように生成されるかを説明する前に、サーブレットが生成するAtom文書は常に、サーバー上で利用できるサービスの完全一式であることを指摘しておきます。あるサービスに対する特定なエントリーがフィードから無くなったとすると、それは、そのサービスがもはやサーバー上にデプロイされていないことを意味します。また、フィード上にサービスが現れる順序には、何ら重要な意味はありません。新しいサービスは、サービスの集合の、任意の位置に現れます。
Application Serverに埋め込まれたWebサービス・ランタイムの実装の基になっているのは、エンタープライズJava環境用Webサービスのプログラミングやデプロイメントのモデルを定義した、Web Services for J2EE version 1.0仕様(JSR-109と呼ばれます・・・参考文献を見てください)です。JSR-109用のデプロイメント・モデルは、webservices.xmlと呼ばれるコンフィギュレーション・ファイルを中心とした、宣言的手法に基づいています。
JSR-109の仕様によると、webservices.xmlは、「J2EEが使用可能なコンテナーに対するWebサービスにデプロイすべきWebサービス・セットを定義します」。これを大まかに言い換えると、「webservices.xmlファイルは、Atomフィードの中で宣伝しようとしているサービスのリストを探すための場所」ということになります。
典型的なシナリオでは、webservices.xmlファイルが置かれている場所は、標準J2EE Webアプリケーションの/WEB-INFディレクトリーである場合がほとんどです。ただし、Webアプリケーションのクラスパスのそこら中に、複数のwebservices.xmlファイルがある場合もあります。リスト2は、サンプル・アプリケーションに関するwebservices.xmlデプロイメント記述子を示しています。
リスト2. webservices.xml
<?xml version="1.0" encoding="UTF-8"?>
<webservices
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.1"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd">
<webservice-description>
<webservice-description-name>HelloWorldService
</webservice-description-name>
<wsdl-file>WEB-INF/wsdl/HelloWorld.wsdl
</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/HelloWorld_mapping.xml
</jaxrpc-mapping-file>
<port-component>
<port-component-name>HelloWorld
</port-component-name>
<wsdl-port
xmlns:pfx="http://example.com">pfx:HelloWorld
</wsdl-port>
<service-endpoint-interface>com.example.HelloWorld
</service-endpoint-interface>
<service-impl-bean>
<servlet-link>com_example_HelloWorld
</servlet-link>
</service-impl-bean>
</port-component>
</webservice-description>
</webservices>
|
webservices.xmlフォーマットは、最上位レベルの<webservices>要素と、任意の数の子要素<webservice-description>が含まれるように構成されています(デプロイされたWebサービス毎に、1つの子要素があります)。<webservice-description>要素の内容は、下記を規定します。
- サービスの名前
- そのサービスを記述したWSDL(Web Services Description Language)文書のURL
- ネイティブJavaタイプを適当なXML表現に関連付けるためのマッピング・ファイル
- そのサービスの持つ、ある特定なJava実装へのバインディング
こうした情報の中で、主に注目すべきものは、サービス名とWSDLだけです。
実行されるプロセスは、下記のようにごく単純です。
- 見つかったwebservices.xmlファイルすべてを構文解析する
- 見つかったwebservice記述それぞれに対して、そのサービスに対するWS-Addressing Endpoint Referenceを作ります。
- Endpoint Referenceそれぞれに対してAtomエントリーを作ります。
- AtomエントリーそれぞれをAtomフィードに追加します。
Atomフィードを生成するための全作業は、1つのHTTPサーブレットとして分離されています。この概略をリスト3から6に示します。
リスト3. AtomServlet.java
package com.example.atom;
...
public class AtomServlet
extends HttpServlet
implements Servlet {
...
|
最初の仕事(リスト4のinitファンクションが処理します)は、利用可能なすべてのwebservices.xmlファイルを発見することです。デフォルトで、最初にWebアプリケーションのWEB-INFディレクトリーをチェックします。JSR-109デプロイメント記述子も、Webアプリケーションのクラスパスの様々な場所に置かれている可能性があります。このサンプル実装では、サービスを求めてクラスパスを検索することは、デフォルトではしないようになっています。
リスト4. webservices.xmlを見つける
public void init(
ServletConfig config)
throws ServletException {
super.init(config);
try {
webservicesdocs = new ArrayList();
File webservices =
new File(
getServletContext().getRealPath(
"WEB-INF/webservices.xml"));
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
documentBuilder = dbf.newDocumentBuilder();
Document webservicesdoc =
documentBuilder.parse(webservices);
webservicesdocs.add(webservicesdoc);
if (INCLUDE_CLASSPATH) {
Enumeration enum =
Thread.currentThread().
getContextClassLoader().getResources(
"META-INF/webservices.xml");
for (;enum.hasMoreElements();) {
try {
URL url = (URL)enum.nextElement();
documentBuilder = dbf.newDocumentBuilder();
Document doc = documentBuilder.parse(url.openStream());
webservicesdocs.add(doc);
} catch (Exception e) {}
}
}
lastmodified = Calendar.getInstance();
lastmodified.setTimeInMillis(webservices.lastModified());
} catch (Exception e) {} }
... |
一連のwebservices.xmlデプロイメント記述子が見つかり、構文解析されると、Atomフィードのためのリクエストをサービスできるようになります。このプロセス(リスト5に示します)は単純です。もしwebservices.xml文書が変更されていると、現在のEndpoint Referenceの完全セットを含むAtom文書が生成され、クライアントに返されます。
リスト5. Atomフィードを取得する
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException,
IOException {
String modsince =
request.getHeader("If-Modified-Since");
String lastmod =
httpdateformat(lastmodified);
if (modsince != null &&
modsince.equals(lastmod)) {
response.setStatus(
HttpServletResponse.SC_NOT_MODIFIED);
} else {
response.setContentType("application/atom+xml");
response.setCharacterEncoding("utf-8");
response.setHeader(
"Last-Modified",
httpdateformat(lastmodified));
Document doc = getAtom(request);
OutputFormat of = new OutputFormat(doc);
of.setOmitComments(true);
of.setOmitDocumentType(true);
of.setOmitXMLDeclaration(false);
of.setEncoding("utf-8");
of.setIndenting(false);
of.setPreserveSpace(false);
SerializerFactory factory =
SerializerFactory.getSerializerFactory(
Method.XML);
Serializer ser =
factory.makeSerializer(
response.getWriter(), of);
DOMSerializer domser = ser.asDOMSerializer();
domser.serialize(doc);
}
}
|
Atom文書の生成(リスト6)は、サーブレットを初期化した際に構文解析したwebservice.xmlファイルの集合の中に見つかった<webservice-description>要素すべてに対して、単純に繰り返しを行うだけです。フィードが作られ、デプロイされたサービスそれぞれに対して、Atomエントリーが作られます。
リスト6. フィードを生成する
private Document getAtom(HttpServletRequest request) {
Document feedDocument = documentBuilder.newDocument();
Element feed = createFeed(feedDocument, request);
NodeList nl =
webservicesdoc.getElementsByTagNameNS(
WAS,"webservice-description");
for (int n = 0; n < nl.getLength(); n++) {
Element service = (Element) nl.item(n);
feed.appendChild(
createEntry(
feedDocument,
service,
request));
}
return feedDocument;
}
private Element createFeed(
Document doc,
HttpServletRequest request) {
...
}
private Element createEntry(
Document doc,
Element service,
HttpServletRequest request) {
...
}
...
}
|
サーブレットが実装されると、そのWebサービスを含むWebアプリケーションにデプロイされ、URLマッピングが与えられます。このサーブレットURLに対してHTTP GETリクエストを行うと、生成されたAtom文書が得られます(リスト7)。
リスト7. http://localhost:9085/wsatom/services.atom
<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en"
xmlns="http://www.w3.org/2005/Atom"
xmlns:fh="http://purl.org/syndication/history/1.0">
<id>http://localhost:9085/wsatom/services.atom</id>
<title>Web Services on localhost</title>
<fh:incremental>false</fh:incremental>
<updated>2005-08-23T23:00:35Z</updated>
<link href="http://localhost:9085/wsatom/services.atom"
rel="self"
type="application/atom+xml"/>
<author>
<name>WebSphere</name>
<uri>http://localhost:9085/wsatom</uri>
</author>
<entry>
<id>tag:localhost,2005:/services/HelloWorld</id>
<title>HelloWorld</title>
<summary>Service 'HelloWorld' is available at
http://localhost:9085/wsatom/services/HelloWorld</summary>
<link href="http://localhost:9085/wsatom/services/HelloWorld"
rel="alternate"
title="Service Endpoint"/>
<link
href="http://localhost:9085/wsatom/services/HelloWorld?wsdl"
rel="alternate"
title="WSDL"
type="application/wsdl+xml"/>
<updated>2005-08-23T23:00:35Z</updated>
<content type="application/xml">
<EndpointReference
xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://localhost:9085/wsatom/services/HelloWorld
</Address>
</EndpointReference>
</content>
</entry>
</feed>
|
Atomフィードがデプロイされると、クライアントは自分の好きなAtom 1.0対応のフィード・リーダー(例えばSharpReaderなど)を使って、そのフィードを購読できるようになります。これを図1に示します。またクライアントは、埋め込まれたWS-Addressing Endpoint Referenceを利用して、プログラム的にフィードにアクセスすることもできます。
図1. SharpReaderでのhttp://localhost:9085/wsatom/services.atom
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Atom Web Services Sample Code | ws-atomwascode.zip | 18KB | HTTP |
学ぶために
- W3CのWebサイトで、WS-Addressing 1.0 - Coreの勧告候補ドラフトを入手してください。
-
Atom Publishing Format and Protocolで、このワーキング・グループに関して学んでください。
- developerWorksにある、Web Services Inspection Language Draftを入手してください。
- Java Community ProcessのWebサイトで、Web Services for J2EE (JSR-109) specificationの最新版を入手してください。
製品や技術を入手するために
-
WebSphere Application Server version 6.0の無料試用版をダウンロードしてください。
James Snellは、IBMのEmerging Technologies Toolkitチームの一員です。過去2年間は、新興のWebサービス技術や標準などに焦点を当てており、またAtom 1.0仕様にも貢献しました。新興技術に焦点を当てたウェブログ、http://www.ibm.com/developerworks/blogs/page/jasnellを維持管理しています。