この対処法カタログエントリのサンプルアプリケーションは、文字列型注文書 Web サービスに注文書を送信するための GUI を提供する Swing クライアントです。このアプリプリケーションの画面例を、次に示します。
このアプリケーションは、Netbeans[tm] 4.1 IDE を使って作成されています。このアプリケーションの主クラスは、Swing フレームとして実装されている MainWindow
です。この主クラスは委託クラスの POServiceBD を使用して、Web サービスを呼び出します。
このアプリケーションはスタンドアロンで実行することも、Java Web Start を使用して実行することもできます。
このアプリケーションの Java Web Start 対応版は、webstart-client.war
にある Web アプリケーションに含まれています。
POServiceBD
を介して呼び出されます。
// スタブクラスをインポート
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 サービスの呼び出し
// サービスエンドポイントインタフェースのクラスをインポート
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
クラスは利用できなくなります。 // サービスエンドポイントインタフェースのクラスをインポート
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 サービスの呼び出し
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
要素は、アプリケーションの JAR ファイルがある URL であるコードベース属性を必要とします。このコードベースが動的に検出されるようにして、アプリケーション の WAR モジュールが配備されている URL に一致するようにします。同様に、Swing クライアントは、文字列型注文書 Web サービスが実行されている URL を動的に特定する必要があります。これは、アプリケーションの WAR モジュールに含まれている JSP ファイルを使用して JNLP 記述子を生成することによって行うことができます。application/x-java-jnlp-file
という特定の内容の種類の XML ファイルを出力する必要があります。これは、コード例 5 に示すような JSP ページ指令を使用して実現することができます。 <%@ page contentType="application/x-java-jnlp-file" info="Swing Client JNLP" %>
コード例 5: JNLP 記述子に対する contentType ページ指令の使用
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: コードベースの動的生成
<%
String serviceurl = serverurl + "webservice/StringPurchaseOrderService";
%>
<!-- ... other JNLP descriptor contents -->
<resources>
<!-- ... other resource delcarations -->
<property name="stringwebservice.url" value="<%=serviceurl%>"/>
</resources>
コード例 7: Java Web Start アプリケーションへのシステムプロパティーの引き渡し
stringwebservice.url
プロパティーを使用して、Web サービスの URL を設定します。 String serviceurl = System.getProperty("stringwebservice.url");
if (serviceurl != null) {
serviceUrlTextField.setText(serviceurl);
}
コード例 8: Java Web Start アプリケーションにおけるシステムプロパティーの取り込み
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 拡張子へのマッピング