XMLBeans で Web サービス・クライアントを作成する

XMLBean 技術を使って、メソッドへの入力にカスタム・データ型を必要とするWeb サービス・クライアントを作成します。XMLBeans を使えば、クライアント側に静的スタブを生成する必要がなくなります。この利点について、詳しく説明します。

Shailesh K. Mishra, Software Engineer, IBM

Shailesh Mishra photoShailesh K. Mishra は、インド、グルガオン所在の IBM ソフトウェア研究所のソフトウェア・エンジニアです。現在、「BizPortlets」プロジェクトに従事しており、ビジネス・インテグレーションを専門分野としています。



2006年 7月 18日

はじめに

Apache XMLBeans は、StAX 仕様に基づくオープン・ソースの XML と Java のバインディング・ツールです。XMLBeansを使うと、XML スキーマから Java クラスと Java インターフェースを生成できます。生成されたJava クラスは、そのスキーマに準拠する XML 文書の解析や生成に使うことができます。さらに嬉しいことに、XMLBeansでは XML を直観的に扱えるので、Java で一層簡単に XML データや文書にアクセスしたり操作したりできるようになります。

XMLBeans の XML へのアプローチとはどんなものなのか、その特徴のいくつかを検討してみましょう。

  • XMLBeans は、お馴染みの Java オブジェクト・ベースのビューで XML データを表示する一方、元のネイティブXML 構造へのアクセスを維持します。
  • XMLBeans では、文書としての XML の整合性を維持します。XML 指向の API は共通してXML を分解し、そのパーツにバインドします。XMLBeans では、XML インスタンス文書全体が1 つの単位として処理されます。XML データは XML としてメモリーに格納されます。つまり、空白文字を持つオリジナルの要素コンテンツとともに、文書の順序が保持されます。
  • スキーマから型が生成されるため、XML インスタンスへのアクセスは、JavaBeanのようなアクセサーにより、get メソッドと set メソッドで行われます。
  • XMLBeans は当初から XML スキーマを念頭に置いて設計されています。そのため、XMLBeansではすべての XML スキーマ定義がサポートされます。
  • XML に素早くアクセスします

XMLBean の開発は、XML スキーマを起点とします。XML スキーマ仕様 (「参考文献」セクションを参照)が提供する豊富なデータ・モデルでは、複雑な構造と、データに関する制約を表現することが可能です。例えば、XMLスキーマでは、文書内でのデータの順序や特定の値に関する制約を制御できます。その一例として、エントリー日付が2000 年より後でなければならないとします。Java では通常、そのようなルールを課すにはカスタム・コードが必要となりますが、XMLBeansではスキーマ制約を使うことができます。

XMLBeans 技術を使えば、WSDL ファイル内に型定義の Java クラスと Java インターフェースを生成できます。それには、WSDLTypes_To_JAVATypesクラスを実行します (「ダウンロード」セクションを参照)。このクラスの mainメソッドでは、WSDL の URL を変更する必要があります。このステップは非常に重要です。なぜならこれによって、Webサービスを起動する SOAP メッセージを作成するために使われる Java クラスとJava インターフェースが生成されるためです。WSDLTypes_To_JAVATypes クラスについての詳細は、 「WSDLに型定義の Java クラスと Java インターフェースを生成する」セクションで説明しています。


ワークスペースを XMLBeans と連動するように構成する

最初に必要なステップは、XMLBeans のバイナリー配布をダウンロードすることです。これは、apache.org の XML ページにあります。次に、アーカイブをディレクトリーに解凍します。XMLBeans 配布に含まれる.jar ファイルをプロジェクトに追加してください。


WSDL に型定義の Java クラスと Java インターフェースを生成する

XMLBeans フレームワークは、WSDL ファイルを Java オブジェクトにコンパイルするために必要なものを提供します。この機能を使って、WSDLで定義され、Web サービス・クライアントで使うことができるデータ型と関連付けたJava クラスと Java インターフェースを生成できます。WSDL 文書を動的に解釈するこの機能によって、標準の静的XML 構文解析と処理技術のより一層強力な制御を実現できます。

以下のコード・リストは、「参考文献」セクションに記載されている記事「UsingJava to Handle Custom WSDLData Types」から引用した WSDLTypes_To_JAVATypesクラス・ファイルです。このコードを見ると、WSDL ファイルで定義されたデータ型からスキーマを生成する方法が分かるはずです。

リスト 1. generateSchemas メソッド
generateSchemas(String schemadir, String classesdir,
String javasrcdir, String wsdlFileName) {
boolean doNotValidateContents = false;
XmlObject wsdlDoc = null;
MyEntityResolver myentityResolver = new MyEntityResolver();
ArrayList outerrlistener = new ArrayList();
XmlErrorWatcher errlistener = new XmlErrorWatcher(outerrlistener);
ArrayList schemalist = new ArrayList();
try {
SchemaTypeLoader loader =
XmlBeans.typeLoaderForClassLoader(SchemaDocument.class.getClassLoader());
.................................       
................................
addWsdlSchemas(wsdlFileName,
(DefinitionsDocument)wsdlDoc,errlistener,doNotValidateContents,schemalist);
.................................

addWsdlSchemas メソッドでスキーマを生成し、そのスキーマを検証してから arraylistに追加します。

リスト 2. addWsdlSchemas メソッド
addWsdlSchemas(String wsdlFileName,DefinitionsDocument definitionsDocument,
XmlErrorWatcher  errlistener, boolean doNotValidateContents,ArrayList schemalist){

XmlObject[]types = definitionsDocument.getDefinitions().getTypesArray();
for (int j = 0; j < types.length; j++) {
XmlObject[] schemas = types[j].selectPath("declare namespace"
+ " xs=\"http://www.w3.org/2001/XMLSchema\""        
+ " xs:schema");
if (schemas.length == 0) {
StscState.addWarning(errlistener, "The WSDL " + wsdlFileName
+ " has no schema documents in namespace "
+ "'http://www.w3.org/2001/XMLSchema'",
XmlErrorCodes.GENERIC_ERROR,definitionsDocument);
continue;
}
for (int k = 0; k < schemas.length; k++) {
if (schemas[k] instanceof SchemaDocument.Schema) {
SchemaDocumentImpl.SchemaImpl schemaImpl = (SchemaDocumentImpl.SchemaImpl) schemas[k];
System.out.println ("Validating schema...");
if (schemaImpl.validate(opts)) {
System.out.println("Schema passed validation");
schemalist.add(schemas[k]);
}else {
System.out.println("Schema failed validation");
schemalist.add(schemas[k]);
}
}

compileSchema メソッドと generateJavaSource メソッドで、生成されたスキーマのコンパイルとJava ファイルの生成をそれぞれ行います。最後に、CompileJavaSource メソッドでJava ソース・ファイルをコンパイルします。

リスト 3. compileSchemas、generateJavaSource、および CompileJavaSourceメソッド
SchemaTypeSystem compileSchemas(String schemadir,ArrayList schemalist, MyEntityResolver 
myentityResolver,XmlErrorWatcher errlistener) 
{
SchemaDocument.Schema[] sdocs = (SchemaDocument.Schema[]) schemalist
.toArray(new SchemaDocument.Schema[schemalist.size()]);
ResourceLoader cpResourceLoader = null;
SchemaTypeLoader linkTo = SchemaTypeLoaderImpl.build (null, cpResourceLoader, null);.
.................
.................
SchemaTypeSystem sts = SchemaTypeSystemCompiler.compile (params);
....................


generateJavaSource(String classesdir,String javasrcdir, SchemaTypeSystem sts) {
File classesDir = new File(classesdir);
File srcDir = IOUtil.createDir(new File("."), javasrcdir);

// now, generate the source files
XmlOptions options = new XmlOptions();
boolean verbose = false;
boolean incrSrcGen = false;
Repackager repackager = null;
FilerImpl filer = new FilerImpl(classesDir, srcDir, repackager,
verbose, incrSrcGen);

System.out.println ("Generating Java source...");
if (SchemaTypeSystemCompiler.generateTypes(sts, filer, options)) {
............................
...............................

CompileJavaSource(List sourceFiles, String classesDirName) {
File classesDir = new File(classesDirName);
boolean debug = false;
System.out.println ("Compiling Java source files...");
If (CodeGenUtil.externalCompile (sourceFiles, classesDir, null, debug)) {       
..................
..................

Web サービスのクライアントを作成する

XMLBeans を使って Web サービスのクライアントを作成するには、SOAP メッセージを直接作成し、そのSOAP メッセージを Web サービス URL に送ります。

SOAP メッセージを作成する

  • ステップ 1. 以下を呼び出して SOAPMessaage インタスタンスを作成します。 SOAPMessage smsg =MessageFactory.newInstance ().createMessage ()
  • ステップ 2. SOAP エンベロープと本体を作成します。 SOAPPart prt = smsg.getSOAPPart ();
    SOAPEnvelope env = prt.getEnvelope ();
    SOAPBody bdy = env.getBody ();
  • ステップ 3. メソッドの入力タイプに合わせてクラスをインスタンス化します。 GetPlacedOrderDocument Placedorderdoc=GetPlacedOrderDocument.Factory.newInstance();
    GetPlacedOrderDocument.GetPlacedOrder order=placedorderdoc.addNewGetPlacedOrder();
    Customer customer=order.addNewCust ();
    customer.setId (835163);
    customer.setFname ("Jerry");
    customer.setLname ("tukker");
    customer.setLocation ("abcd..");
  • ステップ 4. 上記のクラス・インスタンスを SOAP メッセージの本体に追加します。 Node nd= placedorderdoc.getDomNode ();
    SOAPBodyElement ele = bdy.addDocument ((Document) nd);
  • ステップ 5. SOAP メッセージを Web サービスのエンド・ポイントに送信します。 URL endpoint = new URL ("http://localhost:9080/Sample/services/SampleWebService");
    SOAPMessage response = con.call (smsg, endpoint);

上記のステップが完了すると、以下のコード・リストになります。

リスト 4. SOAP クライアント
MessageFactory mfact = MessageFactory.newInstance();
SOAPMessage smsg = mfact.createMessage();

SOAPPart prt = smsg.getSOAPPart();
SOAPEnvelope env = prt.getEnvelope();
SOAPBody bdy = env.getBody();

GetPlacedOrderDocument placedorderdoc=GetPlacedOrderDocument.Factory.newInstance();
GetPlacedOrderDocument.GetPlacedOrder order=placedorderdoc.addNewGetPlacedOrder();
Customer customer=order.addNewCust();
customer.setId(835163);
customer.setFname("Jerry");
customer.setLname("tukker");
customer.setLocation ("abcd...");
smsg.writeTo(System.out);
System.out.println();
Node nd = placedorderdoc.getDomNode();
SOAPBodyElement ele = bdy.addDocument((Document) nd); 
.............................
URL endpoint = new URL("http://localhost:9080/Sample/services/SampleWebService");

   //Send the message
SOAPMessage response = con.call(smsg, endpoint);
response.writeTo(System.out);
...........................

上記のコード・リスト GetPlacedOrderDocument は、WSDLTypes_To_JAVATypes クラスを実行した後に、(コードをテストするために使ったサンプルWeb サービスの) WSDL ファイル から生成されたインターフェースです。このWeb サービスには、Customer クラスを引数とする getPlacedOrder メソッドがあります。この Customer クラスは、idfnamelnamelocation の 4 つの属性を持ちます。


まとめ

このチュートリアルでは、XMLBeans を使って Web サービス・クライアントを作成するお手伝いをしました。作業の流れとして、まずWSDL ファイルからスキーマを生成し、これらのスキーマをコンパイルし、そして最終的に、コンパイルしたスキーマからJava ソースを生成しました。Java ソースを生成すれば、あとは簡単に SOAP メッセージを作成してWeb サービス URL に送信できます。これによって、自分で SOAP メッセージを書いたり、カスタムJava オブジェクトのシリアライゼーション/デシリアライゼーションを行う必要から解放されます。

この記事のレビューとコメントを引き受けてくださった WebSphere CommunityEdition/Geronimo L3 サポートの主任、Krishnakumar Balachandar (KK) に感謝します。


ダウンロード

内容ファイル名サイズ
Sample codexmlbeansample.zip96KB

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=SOA and web services
ArticleID=243759
ArticleTitle=XMLBeans で Web サービス・クライアントを作成する
publish-date=07182006