Web サービスにアクセスするための Java Swing クライアント: デザインの詳細

この対処法カタログエントリのサンプルアプリケーションは、文字列型注文書 Web サービスに注文書を送信するための GUI を提供する Swing クライアントです。このアプリプリケーションの画面例を、次に示します。

Screenshot of the Swing application

このアプリケーションは、Netbeans[tm] 4.1 IDE を使って作成されています。このアプリケーションの主クラスは、Swing フレームとして実装されている MainWindow です。この主クラスは委託クラスの POServiceBD を使用して、Web サービスを呼び出します。

このアプリケーションはスタンドアロンで実行することも、Java Web Start を使用して実行することもできます。 このアプリケーションの Java Web Start 対応版は、webstart-client.war にある Web アプリケーションに含まれています。

Web サービスの呼び出し

アプリケーションクライアントは、スタブか動的プロキシ、または DII を使用して、文字列型の注文書 Web サービスを呼び出すオプションを提供します。この Web サービスは、委託クラス POServiceBD を介して呼び出されます。

コード例 1 は、スタブを使用している例です。

// スタブクラスをインポート
import
com.sun.j2ee.blueprints.stringposervice.StringPurchaseOrderService_Impl;
import com.sun.j2ee.blueprints.stringposervice.StringPurchaseOrderServiceSEI;

// ... クラスファイルのその他の内容

// スタブを使用
  StringPurchaseOrderService_Impl svcimpl = new?StringPurchaseOrderService_Impl();
  StringPurchaseOrderServiceSEI poservice = svcimpl.getStringPurchaseOrderServiceSEIPort();
  ((Stub)poservice)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, serviceUrl);
  String result = poservice.submitPO(xmlDocStr);

コード例 1: スタブによる Web サービスの呼び出し

コード例 2 は、動的プロキシを使用している例です。

// サービスエンドポイントインタフェースのクラスをインポート
import com.sun.j2ee.blueprints.stringposervice_wrapped.StringPurchaseOrderServiceSEI;
import com.sun.j2ee.blueprints.stringposervice_wrapped.SubmitPO;
import com.sun.j2ee.blueprints.stringposervice_wrapped.SubmitPOResponse;

// ... クラスファイルのその他の内容

// 動的プロキシを使用
  ServiceFactory sf = ServiceFactory.newInstance();
  URL wsdlURL = new URL(serviceUrl + "?WSDL");
  QName serviceQname = new QName(NS_BODY, "StringPurchaseOrderService");
  Service s = sf.createService(wsdlURL, serviceQname);
  QName portQname = new QName(NS_BODY, "StringPurchaseOrderServiceSEIPort");
  StringPurchaseOrderServiceSEI port = (StringPurchaseOrderServiceSEI) s.getPort(portQname, StringPurchaseOrderServiceSEI.class);
  SubmitPO param = new SubmitPO(xmlDocStr);
  SubmitPOResponse response = port.submitPO(param);
  String result = response.getResult();

コード例 2: 動的プロキシによる Web サービスの呼び出し

クラス SubmitPO はサービスの WSDL から生成されますが、プライベートフィールドの 1 つ ((String_1) の名前の付け方が異なるという (String_1 ではなく string_1 という名前が付けられる)、JAX-RPC コンパイラのバグを回避するには作成し直す必要がありました。このバグのため、動的プロキシや DII では、SubmiPO クラスは利用できなくなります。

コード例 3 は、DII を使用している例です。

// サービスエンドポイントインタフェースのクラスをインポート
import com.sun.j2ee.blueprints.stringposervice_wrapped.StringPurchaseOrderServiceSEI;
import com.sun.j2ee.blueprints.stringposervice_wrapped.SubmitPO;
import com.sun.j2ee.blueprints.stringposervice_wrapped.SubmitPOResponse;

// ... クラスファイルのその他の内容

// DII を使用
  ServiceFactory sf = ServiceFactory.newInstance();
  URL wsdlURL = new URL(serviceUrl + "?WSDL");
  QName serviceQname = new QName(NS_BODY, "StringPurchaseOrderService");
  Service s = sf.createService(wsdlURL, serviceQname);
  QName portQname = new QName(NS_BODY, "StringPurchaseOrderServiceSEIPort");
           
  Call call = s.createCall(portQname);
  call.setTargetEndpointAddress(serviceUrl);
  call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(true));
  call.setProperty(Call.SOAPACTION_URI_PROPERTY,"");
           
   // WS-I 準拠の document-literal の場合は、エンコーディング
   //形式として "" を指定し、オペレーションスタイルを
   //document に設定することによってエンコーディング形式を literal に設定する必要がある
  String ENCODING_STYLE_PROPERTY = "javax.xml.rpc.encodingstyle.namespace.uri";
  String URI_ENCODING = "";
  call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING);
  call.setProperty(Call.OPERATION_STYLE_PROPERTY, "document");
           
  // call.setOperationName(new QName(NS_BODY, "submitPO"));
  //を呼び出すことによってオペレーション名を設定する必要がないことに注意
  // これは、Web サービスの使用する SOAP バインドが rpc ではなく、document であるため。
           
  // 要求パラメータおよび戻り値の型は WSDL ファイルそのものに
  //定義されているため、それらの qnames は本体の名前空間で定義される
  QName requestQname = new QName(NS_BODY, "submitPO");
  QName responseQname = new QName(NS_BODY, "submitPOResponse");
           
  // DII 呼び出しの戻り値の型を定義。
  // SubmitPOResponse は、Web サービスによって送信されるラップされた型に一致する必要がある。
  call.setReturnType(responseQname, SubmitPOResponse.class);
           
  // DII 呼び出しのメソッドパラメータの型を定義。
  // WSDL ファイルでは、submitPO のメッセージ部の名前は "parameters"
  // このため、要求パラメータは次の方法で定義される。
  call.addParameter("parameters", requestQname, SubmitPO.class, ParameterMode.IN);
  SubmitPO param = new SubmitPO(xmlDocStr);
  Object[] params = {param};
           
  // DII 呼び出しを呼び出す
  SubmitPOResponse response = (SubmitPOResponse) call.invoke(params);
           
  String result = response.getResult();

コード例 3: DII による Web サービスの呼び出し

Web サービスでは SOAP バインドにドキュメントスタイルを使用するため、呼び出しにオペレーション名を設定する必要がないことに注意してください。

JAR の署名

Java Web Start 版の Swing アプリケーションでは、JAXRPC 実行時環境 JAR が含まれます。これら JAR ファイルに含まれるクラスには、システムへの無制限アクセスを必要とするものがあるため、JAR は署名されている必要があります。 このため、クライアントでセキュリティー警告が発行されますが、ユーザーが許可を受ければ、クライアントが Web サービス呼び出しを行うことができます。

アプリケーションクラスはすべて、 swing-client.jar という単位の JAR ファイルに含まれています。その他の JAR ファイルは、インストールされた J2EE SDK の lib/ から取られる JAXRPC 実行時環境用です。これらの JAR ファイルはすべて、同じ証明書による署名である必要があります。この例の JAR ファイルの署名には、J2EE SDK のデフォルトドメイン (domain1) のキーストアにある s1as 証明書を使用されています。コード例 4 は、JAR ファイルの署名方法を示す Ant build.xml の部分です。

    <!-- use the keystore present in the default domain of the J2EE SDK -->
    <property name="keystore.location" value="${j2ee.home}/domains/domain1/config/keystore.jks"/>
    <!-- we are using the default password used for the keystore. This value should be changed if the keystore password has been changed for the J2EE SDK -->
    <property name="keystore.password" value="changeit"/>
    <property name="key.alias" value="s1as"/>
 
    <!-- sign application jar -->
    <signjar jar="${war.build.dir}/swing-client.jar" signedjar="${war.build.dir}/swing-client-signed.jar" alias="${key.alias}" keystore="${keystore.location}" storepass="${keystore.password}"/>
     
    <property name="jaxrpc-webstart-support.dir" value="${war.build.dir}/jws-support"/>
    <!-- sign JAXRPC runtime jars -->
    <signjar jar="${j2ee.home}/lib/j2ee.jar" signedjar="${jaxrpc-webstart-support.dir}/j2ee.jar" alias="${key.alias}" keystore="${keystore.location}" storepass="${keystore.password}"/>
    <signjar jar="${j2ee.home}/lib/jaxrpc-api.jar" signedjar="${jaxrpc-webstart-support.dir}/jaxrpc-api.jar" alias="${key.alias}" keystore="${keystore.location}" storepass="${keystore.password}"/>
    <!-- ..... sign other jar files in the same way -->

コード例 4: JAR ファイルに署名するための Ang 構築ファイルの部分

JNLP 記述子の生成

JNLP 記述子は、ユーザーシステムにインストールされている Java Web Start 実行時環境の呼び出しに使用されます。JNLP 記述子の内容は動的である必要があります。たとえば jnlp 要素は、アプリケーションの JAR ファイルがある URL であるコードベース属性を必要とします。このコードベースが動的に検出されるようにして、アプリケーション の WAR モジュールが配備されている URL に一致するようにします。同様に、Swing クライアントは、文字列型注文書 Web サービスが実行されている URL を動的に特定する必要があります。これは、アプリケーションの WAR モジュールに含まれている JSP ファイルを使用して JNLP 記述子を生成することによって行うことができます。
Java Web Start が正しく呼び出されるよう、JSP ファイルは、application/x-java-jnlp-file という特定の内容の種類の XML ファイルを出力する必要があります。これは、コード例 5 に示すような JSP ページ指令を使用して実現することができます。

<%@ page contentType="application/x-java-jnlp-file" info="Swing Client JNLP" %>

コード例 5: JNLP 記述子に対する contentType ページ指令の使用

コードベースの URL もまた作成する必要があります。この URL は、プロトコルの種類 (http または https) とサーバー名、サーバーポート、アプリケーションの JAR ファイルがあるコンテキストパスで構成されます。サーバーポートが 80 (http の場合) または 443 (https) の場合、サーバーポートを指定する必要はありません。コード例 6 は、コードベースを求める JSP コードの例です。

<%
  StringBuffer serverurl = new StringBuffer();
  serverurl.append(!request.isSecure() ? "http://" : "https://");
  serverurl.append(request.getServerName());
  if (request.getServerPort() != (!request.isSecure() ? 80 : 443))
  {
    serverurl.append(':');
    serverurl.append(request.getServerPort());
  }
  serverurl.append('/');
  String codebase = serverurl + request.getContextPath() + '/';
%>
<?xml version="1.0" encoding="UTF-8"?>
<%-- JNLP File for launching Swing Client with JavaWebStart --%>
<jnlp spec="1.0+" codebase="<%=codebase%>" href="swing-client.jnlp">

コード例 6: コードベースの動的生成

文字列型注文書 Web サービスの URL は、コード例 7 に示すのと同様の方法で求められます。

<%
  String serviceurl = serverurl + "webservice/StringPurchaseOrderService";
%>
  <!-- ... other JNLP descriptor contents -->
  <resources>
    <!-- ... other resource delcarations -->
    <property name="stringwebservice.url" value="<%=serviceurl%>"/>
  </resources>

コード例 7: Java Web Start アプリケーションへのシステムプロパティーの引き渡し

コード例 8 に示すように、Swing クライアントは stringwebservice.url プロパティーを使用して、Web サービスの URL を設定します。

  String serviceurl = System.getProperty("stringwebservice.url");
  if (serviceurl != null) {
    serviceUrlTextField.setText(serviceurl);
  }

コード例 8: Java Web Start アプリケーションにおけるシステムプロパティーの取り込み

この Web アプリケーションの開始ページ (index_ja.html) は、Java Web Start 経由で Swing アプリケーションを起動するためのリンクを提供します。このリンクは、JNLP 記述子を生成する JSP ファイルを直接参照するわけではありません。そうではなく、JSP ファイルにマッピングされている仮想の URL swing-client.jnlp にリンクしています。これを行うのは、ブラウザがファイル拡張子を使用して Java Web Start を呼び出す場合に備えて、必ず、ブラウザが JNLP ファイルの .jnlp 拡張子を取得するようにするためです。これは、コード例 9 に見られるように、servlet-mapping 要素を使用して行います。

  <!-- map the JNLP JSP as a servlet since only servlets can have servlet-mapings -->
  <servlet>
    <servlet-name>jnlp-gen</servlet-name>
    <jsp-file>swing-client-jnlp.jsp</jsp-file>
  </servlet>
  <!-- map the virtual URL /swing-client.jnlp to the JSP file -->
  <servlet-mapping>
    <servlet-name>jnlp-gen</servlet-name>
    <url-pattern>/swing-client.jnlp</url-pattern>
  </servlet-mapping>

コード例 9: JNLP 記述子を生成する JSP ファイルの、.jnlp 拡張子へのマッピング

© Sun Microsystems 2005. All of the material in The Java BluePrints Solutions Catalog is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.