ホーム > X-Plus > XML Square >  デベロッパーズコーナー  >  JavaプログラミングとXML

この記事を送る はてなブックマークに追加する BuzzurlにブックマークBuzzurlにブックマーク Yahoo!ブックマークに登録
テキストリンクコードを取得する

デベロッパーズコーナー:Javaプログラミングを極める「JAXM(その1)」

2003年01月27日作成 

Javaプログラミングを極める
第5回:JAXM(その1)

(株)日本ユニテック
太田 純

<この記事はDigital Xpress 2002 Vol.11(10-11月号)に掲載されたものです>

今回と次回にわたって、SOAPを利用したメッセージングAPI であるJAXM について扱います。1 回目はサーバサイドのプログラミングです。

Java の開発環境では、2001 年から2002 年にかけて、XMLのための新しいJava APIが利用可能になってきました。Sun Microsystems 社は、これらのAPI をまとめて「Java XML Pack」としてダウンロードできるようにしています。

http://java.sun.com/xml/

執筆時点(2002 年8 月)で提供されているJava XML Packには以下のAPI が含まれています。

  ● Java API for XML Messaging (JAXM)
  ● Java API for XML Processing (JAXP)
  ● Java API for XML Registries (JAXR)
  ● Java API for XML-based RPC (JAX-RPC)
  ● SOAP with Attachments API for Java (SAAJ)

以前に紹介したJAXP の最新版もこの中に含まれています。JAXM とJAX-RPC は両方ともSOAPメッセージを扱うためのAPIです。JAXR はUDDI レジストリやebXML レジストリへアクセスするAPI を提供します。SAAJ は、JAXM と共に使用して添付ファイル付きSOAP メッセージを扱うためのAPI を提供します。

さらに、このJava XML Pack にサーバツール群を加えたJava Web Services Developer Pack (Java WSDP) も準備されています。Java WSDP はWeb サービスを構築することに焦点を当てて、必要なAPI とツール群を集めたものといえます。

http://java.sun.com/webservices/

Java WSDP としてダウンロードすれば、まとめてインストールすることができ、複数のコンポーネントを動作確認がなされたバージョンの組み合わせで使うことが容易になります。

さ て、この記事の本論はJAXM です。Java API for XMLMessaging (JAXM) は、XML データをメッセージとして送受信するためのAPI です(図1参照)。JAXM は一般的な SOAP メッセージの交換に用いられるように設計されており、SOAP メッセージで添付ファイルを使用するための「SOAP with Attachment」の仕様もサポートしており、SOAP with Attachments API for Java (SAAJ) APIと組み合わせて使います。

【図1:JAXMメッセージ交換】

JAXM のドキュメントを読むときには「メッセージ」という言葉の使い方に注意してください。JAXM におけるメッセージ、つまりjavax.xml.soap.SOAPMessage クラスによって表される構造には添付ファイルの部分(AttachmentPart) も含まれており、図2のような階層構造で表現されます。AttachmentPart は0 個以上、つまり存在しなくてもよく、何個あってもかまいません。

【図2:JAXMにおけるメッセージの階層構造】

JAX-RPC との違いについても簡単に説明しておきましょう。JAXM とJAX-RPC はどちらもSOAP メッセージの送受信を扱うAPI ですが、JAX-RPC が抽象度の高いRPC ベースのインターフェイスを提供するのに対して、JAXM はよりきめ細かい処理を行うのに適したAPI を提供します。JAXM は基本的に言ってどんなSOAP メッセージでも扱うことができますから、当然RPC (Remote Procedure Call) としての利用も可能です。しかし、RPC、つまりメソッド呼び出しとしてSOAP を使う場合にはJAXM はそれほど便利ではありません。その場合はJAX-RPC を使ったほうがよいケースだといえます。JAXM を使うのがよいのは、別のアプリケーションやコンポーネントによってXML 形式で作成されたデータを送受信する場合でしょう。

ここで例として考えるのは、クライアントが注文可能になった新商品を問い合わせ、サーバが商品リストを返却するものです。サーバ側の実装から見てみましょう。サンプルコードをリスト1 に示します。

JAXM で作るWeb サービスはjavax.xml.messaging.JAXMServlet から派生したクラスを使って作成します。この例のように要求応答型のサービスは、javax.xml.messaging.ReqRespListener インターフェイスを実装します。最低限実装すべきメソッドはonMessage です。これは引数に要求メッセージを受け取り、戻り値として応答メッセージを返します。どちらもjavax.xml.soap.SOAPMessageクラスのオブジェクトです。

このサンプルでは非常に簡単な配信型サービスを想定しているので、要求メッセージは単に要求する操作の名前だけを送り、応答メッセージは手動であらかじめ作成したSOAPデータを返すだけのものとします。要求メッセージの例をリスト2 に、応答メッセージの例をリスト3 に示しました。

要求メッセージを読み取るときは、SOAPMessage クラスから順に下位構造を取り出すためのメソッドを呼び出しています。DOM ライクな構造になっていますが、org.w3c.dom パッケージで提供されているDOM のオブジェクト群とはメソッド名などが異なるので注意してください。DOM の扱いに慣れている人なら、API ドキュメントを見ながらSOAPMessage の内容を取り出したり操作したりするのにそれほど苦労することはないでしょう。

応答メッセージを作成するときには、まずjavax.xml.soap .MessageFactory オブジェクトを作成してから、そのファクトリにメッセージを作らせます。

MessageFactory fac = MessageFactory.newInstance();
SOAPMessage msg = fac.createMessage();

ちょうど、JAXP においてDocumentBuilder を作成するときと同じような手順になっていることが分かると思います。このSOAPMessage オブジェクトから順に下位構造をたどって必要な要素やテキストを追加していくことができます。このサンプルでは、ノードを1 つずつ追加するのではなく、あらかじめ用意したSOAP データを読み込んで設定することにします。javax.xml.soap.SOAPPart クラスのsetContent メソッドは、引数にjavax.xml.transform.Source インターフェイスを持つオブジェクトを受け取ります。この例では、まず通常の JAXP のメソッド群を使ってDOM のDocument オブジェクトを作成してから、DOMSource としてsetContent メソッドに渡します。正しいSOAP メッセージがDOM に読み込まれていれば、これですぐに応答メッセージを送信可能になります。

ここで注意を一点。SOAP メッセージをDOM に読み込む際、必ず名前空間を有効にしておく必要があります。

dbf.setNamespaceAware(true);

DocumentBuilderFactory はデフォルトで名前空間が無効になっているので、この呼び出しを行わなければSOAP メッセージを正しく扱うことができなくなってしまいます。

また、ここではいったんDOM オブジェクトを構築していますが、構造の編集を行わずに単にXML データを読み込むだけなら、StreamSource を使うほうが便利でしょう。

さて、SOAPPart クラスには、setContent と対称をなすgetContent というメソッドもあります。

Source src = part.getContent();

このメソッドを、メッセージを読み込む際に使うこともできます。戻ってくるのはjavax.xml.transform.Source インターフェイスを持つオブジェクトですから、これを直接XSLT変換メソッドに渡して、適切な形式に変換することができます。

さて、次回はJAXM とXSLT を組み合わせて使うサンプルを紹介するとともに、クライアントサイドのJAXM プログラミングにおける問題点を検証します。

【リスト1:UnitecSoundShop.java】
import java.io.*;
import java.util.*;
import javax.xml.messaging.*;
import javax.servlet.*;
import javax.xml.soap.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import javax.xml.transform.dom.*;

public class UnitecSoundShop
    extends JAXMServlet implements ReqRespListener

{
    public void init(ServletConfig servletConfig) throws ServletException
    {
        super.init(servletConfig);
    }
    static String strDataDir = "http://localhost:8080/UnitecSoundShop/";

    public SOAPMessage onMessage(SOAPMessage message)
    {
        boolean fault = false;
        try {
            SOAPPart part = message.getSOAPPart();
            SOAPEnvelope env = part.getEnvelope();
            SOAPBody body = env.getBody();
            Name name = env.createName(
                "RequestNewItemList", "u",
                "http://soundshop.utj.co.jp/shema/2002/");
            Iterator it = body.getChildElements(name);

            if(it.hasNext()) {
                SOAPBodyElement method = (SOAPBodyElement)it.next();
            } else {
                fault = true;
            }
         } catch(Exception e) {
            fault = true;
        }
        try {
            MessageFactory fac = MessageFactory.newInstance();
            SOAPMessage msg = fac.createMessage();
            SOAPPart part = msg.getSOAPPart();

            String strFileName
                = strDataDir + (fault? "faultmessage.xml": "itemlist.xml");
            DocumentBuilderFactory dbf
                = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(strFileName);
            DOMSource source = new DOMSource(doc);
            part.setContent(source);

            return msg;
        } catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}


【リスト2:要求メッセージの例】
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <RequestNewItemList xmlns="http://soundshop.utj.co.jp/shema/2002/" />
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


【リスト3:応答メッセージの例】
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <RequestNewItemListResponse xmlns="http://soundshop.utj.co.jp/shema/2002/">
            <RequestNewItemListResult>
                <item catalogNo="9n9r-0003">
                    <name> なんか不思議な胸騒ぎ</name>
                    <price>1200</price>
                </item>
            </RequestNewItemListResult>
        </RequestNewItemListResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>



関連サービス

IT技術およびIT製品の可用性調査・検証業務



この記事と関連の高い記事

関連キーワード:JAXM


関連キーワード:Java


関連キーワード:プログラミング




ページトップへ戻る