|
開発ガイド 05/16/03 09:21:28 |
この章では、Webサービスコンシューマ(Webサービスにアクセスするプログラム)を生成する「Web Serviceウィザード」の使用について、基本手順と一般的なシナリオを説明します。トピックは次のとおりです。
Webサービスを作成する場合のウィザードの使用手順とシナリオについては、
を参照してください。
WorkbenchのWeb Serviceウィザードを使用すると、「Javaベースのコンシューマプログラム」に必要なコードを生成し、「標準(SOAPベース)のWebサービス」にアクセスすることができます。生成されたコードでは、背後で行われるすべてのHTTP SOAP処理を取り扱い、コンシューマプログラムでWebサービスを「Javaリモートオブジェクト」(RMIを使用)として呼び出したり、そのメソッドを呼び出したりできるようにします。
入力に対して、ウィザードでは、アクセスするWebサービスを説明する「WSDLファイル」が必要です。このファイルでは、次のようなさまざまなWebサービスの実装を処理できます。
ウィザードでは、 JAX-RPC (Java API for XML-based RPC)および jBroker Web (Novell exteNdに含まれているJAX-RPX実装)に基づいて、Javaソースファイルを生成します。JAZ-RPCは、Webサービスサポートを提供するJ2EE仕様です。
生成されたファイルは、そのまま使用したり、必要に応じて変更したりできます。このJava指向の方法には、低レベルのSOAP APIをコーディングする代わりに、熟知しているRMIおよびJ2EEの技術を使用してWebサービスを処理できるという利点があります。
Webサービスの概念、標準、および技術の紹介については、
を参照してください。
ウィザードの詳細については、『ツールガイド』の章「
Web Serviceウィザード」を参照してください。
コンシューマプログラムの開発プロセスには、次の作業が含まれます。
プロジェクトのセットアップによる 生成の準備
ウィザードによってコンシューマコードが生成されるようにするWebサービスを説明する WSDLファイルの提供
ウィザードの使用による コンシューマファイルの生成
次に対するJavaソースを含む、ウィザードによって 生成されたファイルの検査
実行するメソッド呼び出しおよび参照先Webサービスの場所を調整するための、 生成されたファイルの編集
そのままの状態、または他のJavaアプリケーションにコンシューマコードを含むことによる、 生成されたファイルの使用
開発環境(テスト用)および運用環境での コンシューマプログラムの実行
Web Serviceウィザードの使用を準備するには、次の操作を行います。
Workbenchで適切な「プロジェクト」をセットアップします。
作成すべきプロジェクトのタイプは、ウィザードによって生成されるコンシューマコードの最終的な使用方法により異なります。例は次のとおりです。
|
コンシューマコードの使用方法 |
作成するプロジェクト |
|---|---|
|
標準のJavaアプリケーション(ウィザードによって生成する単純なJavaクライアントクラスに基づく) |
JARプロジェクト |
|
J2EEアプリケーションクライアント |
CARプロジェクト |
|
JSPページまたはサーブレット |
WARプロジェクト |
|
Enterprise JavaBean |
EJB JARプロジェクト |
次に示す「jBroker Webに必要なアーカイブ」を、プロジェクトに追加します。
これらのJARは、Workbench compilelibディレクトリにあります。
生成、編集された後でコンシューマクラスをコンパイルできるように、プロジェクトの「クラスパス」を編集します。次のアーカイブを含める必要があります。
「J2EEプロジェクト」には、j2ee_api_1_n.jar (J2EEプロジェクトを作成するとWorkbenchに自動的に含まれます)も必要です。
アプリケーションで「SOAPメッセージハンドラ」(高度なJAR-RPC機能)を使用する場合、プロジェクトには、activation.jar、commons-logging.jar、dom4j.jar、jaxp-api.jar、saaj-ri.jar、およびj2ee_api_1_n.jar (メールサポート用)というアーカイブも必要です。これらのJARは、Workbench compilelibディレクトリにあります。
コンシューマコードを生成するには、ターゲットWebサービスを説明するWSDLファイルをWeb Serviceウィザードに提供する必要があります。ウィザードを開始する前に、このWSDLファイルの場所またはURLを取得しておくことが推奨されます。
コンシューマコードを生成して、EMI (Equated Monthly Instalment) Calculatorという名前でXMethodsパブリックレジストリにリストされているAutoloan .NET Webサービスを使用したいとします。このWebサービスでは、特定の期間(月数)における毎月の返済額、利率、およびローン金額が計算され返されます。
この場合、 www.xmethods.netというWebサイトにアクセスすると、次の対応WSDLファイルのURLを見つけることができます。
http://upload.eraserver.net/circle24/autoloan.asmx?wsdl
このURLを提供すると、Web ServiceウィザードではWSDKファイルを読み込み、Autoloan Webサービスについて必要な情報を取得します。
<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s0="http://circle24.com/webservices/"
targetNamespace="http://circle24.com/webservices/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://circle24.com/webservices/">
<s:element name="Calculate">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="Months" type="s:double" />
<s:element minOccurs="1" maxOccurs="1" name="RateOfInterest" type="s:double" />
<s:element minOccurs="1" maxOccurs="1" name="Amount" type="s:double" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="CalculateResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="CalculateResult" nillable="true"
type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="string" nillable="true" type="s:string" />
</s:schema>
</types>
<message name="CalculateSoapIn">
<part name="parameters" element="s0:Calculate" />
</message>
<message name="CalculateSoapOut">
<part name="parameters" element="s0:CalculateResponse" />
</message>
<message name="CalculateHttpGetIn">
<part name="Months" type="s:string" />
<part name="RateOfInterest" type="s:string" />
<part name="Amount" type="s:string" />
</message>
<message name="CalculateHttpGetOut">
<part name="Body" element="s0:string" />
</message>
<message name="CalculateHttpPostIn">
<part name="Months" type="s:string" />
<part name="RateOfInterest" type="s:string" />
<part name="Amount" type="s:string" />
</message>
<message name="CalculateHttpPostOut">
<part name="Body" element="s0:string" />
</message>
<portType name="AutoloanSoap">
<operation name="Calculate">
<input message="s0:CalculateSoapIn" />
<output message="s0:CalculateSoapOut" />
</operation>
</portType>
<portType name="AutoloanHttpGet">
<operation name="Calculate">
<input message="s0:CalculateHttpGetIn" />
<output message="s0:CalculateHttpGetOut" />
</operation>
</portType>
<portType name="AutoloanHttpPost">
<operation name="Calculate">
<input message="s0:CalculateHttpPostIn" />
<output message="s0:CalculateHttpPostOut" />
</operation>
</portType>
<binding name="AutoloanSoap" type="s0:AutoloanSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="Calculate">
<soap:operation soapAction="http://circle24.com/webservices/Calculate"
style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<binding name="AutoloanHttpGet" type="s0:AutoloanHttpGet">
<http:binding verb="GET" />
<operation name="Calculate">
<http:operation location="/Calculate" />
<input>
<http:urlEncoded />
</input>
<output>
<mime:mimeXml part="Body" />
</output>
</operation>
</binding>
<binding name="AutoloanHttpPost" type="s0:AutoloanHttpPost">
<http:binding verb="POST" />
<operation name="Calculate">
<http:operation location="/Calculate" />
<input>
<mime:content type="application/x-www-form-urlencoded" />
</input>
<output>
<mime:mimeXml part="Body" />
</output>
</operation>
</binding>
<service name="Autoloan">
<documentation>This Web Service mimics a Simple Autoloan calculator.</documentation>
<port name="AutoloanSoap" binding="s0:AutoloanSoap">
<soap:address location="http://upload.eraserver.net/circle24/autoloan.asmx" />
</port>
<port name="AutoloanHttpGet" binding="s0:AutoloanHttpGet">
<http:address location="http://upload.eraserver.net/circle24/autoloan.asmx" />
</port>
<port name="AutoloanHttpPost" binding="s0:AutoloanHttpPost">
<http:address location="http://upload.eraserver.net/circle24/autoloan.asmx" />
</port>
</service>
</definitions>
Autoloan WSDLでは、HttpGetおよびHttpPostの定義(message、portType、binding、およびservice portを含む)を無視できます。Soapの定義のみ、開発しているWebサービスコンシューマプログラムに適用されます。
このWebサービスでは、calculate()という1つのメソッドが表示されています。このメソッドは、3つのdouble (Months、RateOfInterest、およびAmount)を含むCalculateオブジェクトを取得し、1つのString (CalculateResult)を含むCalculateResponseオブジェクトを返します。Web Serviceウィザードでは、このメソッドの呼び出しをサポートするために、対応するリモートインタフェースをJavaで生成します。
typesセクションは、CalculateおよびCalculateResponseの「XMLスキーマ」定義を指定します。Web Serviceウィザードでは、これらのオブジェクトを表現するために、対応するタイプクラスをJavaで生成します。
AutoloanSoapのbindingセクションを参照すると、このWebサービスが「ドキュメントスタイル」(「RPCスタイル」ではない)として定義されていることが確認できます。これは、.NET Webサービスで一般的に見られます。バインドスタイルは、SOAPメッセージの形式を説明します。また、他のWebサービス環境との相互運用性に影響を与える場合があります。
Web Serviceウィザードでは、指定のバインドスタイルの処理に必要なJavaコードを生成します。
AutoloanSoapのport定義(WSDLファイルの最後)は、Webサービスにアクセスできる場所の「アドレス」(URL)を指定します(次を参照)。
http://upload.eraserver.net/circle24/autoloan.asmx
Web Serviceウィザードでは、Webサービスを呼び出すために生成するサービスクラスおよびスタブクラスでこのURLを使用します。
プロジェクトをセットアップして、適切なWSDLファイルを見つけたら、Web Serviceウィザードを使用する準備が整ったことになります。ウィザードでは一度に1つのWebサービスコンシューマが作成されるため、複数を開発する場合は、Webサービスコンシューマを複数回使用する必要があります。
ウィザードを起動するたびに、WSDLファイルおよび指定した他の入力が使用され、1セットのコンシューマソースファイルが生成されます。このプロセスの要約は次のとおりです。
[File]>[New]の順に選択して[New File]ダイアログボックスを表示し、[Web Services]タブに移動します。
「プロジェクトの場所」についての情報を入力するようウィザードで要求されたら、次の項目を指定します。
たとえば、Autoloan Webサービスのコンシューマを生成するとします。この場合、ターゲットJARプロジェクトとしてWebServiceConsumerSampleを指定し、生成されたクラスのパッケージとしてcom.exsamp.netを指定できます。
ウィザードの指示に従って、ターゲットWebサービスを説明する「WSDLファイル」を指定します。
たとえば、Autoloan Webサービスのコンシューマを生成する場合は、XMethodsパブリックレジストリから取得したWSDLファイルのURLを指定します。
「クラス生成およびSOAPオプション」を入力するようウィザードで要求されたら、作成するコードについての詳細を指定する必要があります。
Webサービスコンシューマに必要なファイルを取得するには、[Generate stubs]をオンにします([Generate skeletons]はオフのままにします)。
WSDLで複雑なタイプのタイプクラスを自動的に生成するには、[Map complex XML types to Java types]をオンにします。
たとえば、これらのオプションによって、Autoloan Webサービスの適切なコンシューマソースファイル(タイプクラスを含む)が生成されます。
注記: jBroker Web 1.xアプリケーションのサポートは、「旧製品との互換性」のオプションを使用して有効にできます。詳細については、(前の章の) jBroker Web 1.xの互換性を選択した場合を参照してください。
ウィザードを終了すると、Webサービスコンシューマに対して指定したものがすべて生成され、プロジェクトの他の部分は、サポートする変更内容で更新されます。
ファイル名を生成する場合、Web Serviceウィザードでは、JAX-RPCによって指定された名前付けルールに従います。Webサービスコンシューマでは、結果として付けられるファイル名は、WSDL内の定義に基づきます。
簡単にするため、このマニュアルでは、WSDL定義から派生して生成されたWebサービスコンシューマのファイル名の一部を表すのにxxxを使用します。
Web Serviceウィザードでは、Webサービスコンシューマのファイル(前のリストを参照)を生成する際に、背後で「jBroker Webコンパイラ」を使用します。場合によっては、次のようなアプリケーションに固有の要件をサポートするために、これらのコンパイラによって追加コードやファイルが生成されることがあります。
詳細については、
jBroker Webヘルプを参照してください。
Autoloan Webサービスに対してWeb Serviceウィザードにより生成されたコンシューマコードは、次の「Webサービスアクセスの標準ファイル」から構成されます。
AutoloanSoap.java (リモートインタフェース)
Autoloan.java (サービスインタフェース)
AutoloanImpl.java (サービス実装クラス)
また、WSDLで定義された次の「複雑なタイプをマップするためのアプリケーション固有のファイル」から構成されます。
これらのファイルは、作成すると、指定したディレクトリパスにあるプロジェクトにウィザードによって追加されます。
これは、スタブクラスによって使用されるリモートインタフェースで、Autoloan Webサービスのメソッド呼び出しをサポートします。
package com.exsamp.net;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface AutoloanSoap extends Remote
{
com.exsamp.net.CalculateResponse calculate(com.exsamp.net.Calculate parameters)
throws RemoteException;
}
これは、JAX-RPCで使用されるサービスインタフェースで、Webサービスのスタブをクライアントで取得できるようにします。
package com.exsamp.net;
import javax.xml.rpc.ServiceException;
public interface Autoloan extends javax.xml.rpc.Service
{
public AutoloanSoap_Stub getAutoloanSoap()
throws ServiceException;
}
これは、スタブ(AutoloanSoap_Stub)のインスタンス化を処理するサービス実装クラスです。
package com.exsamp.net;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.Hashtable;
import java.util.Properties;
import java.util.ArrayList;
import java.net.URL;
import java.net.MalformedURLException;
import javax.xml.rpc.Call;
import javax.xml.rpc.ParameterMode;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import com.sssw.jbroker.web.Binding;
import com.sssw.jbroker.web.encoding.DefaultTypeMappingRegistry;
public class AutoloanImpl
extends com.sssw.jbroker.web.xml.rpc.ServiceImpl
implements Autoloan
{
public AutoloanImpl()
{
try {
_typeMappingRegistry.importTypeMappings(_tmprops);
} catch (Exception ex) {
throw new javax.xml.rpc.JAXRPCException("failed to populate default type mapping registry: " + ex.getMessage());
}
try {
createCalls();
} catch (ServiceException ex) {
throw new javax.xml.rpc.JAXRPCException("failed to create the call objects: " + ex.getMessage());
}
}
public QName getServiceName() { return _serviceName; }
public Iterator getPorts() { return _portMapping.keySet().iterator(); }
public void setProxyMode(boolean proxy) { _proxy = proxy; }
public boolean getProxyMode() { return _proxy; }
public URL getWSDLDocumentLocation()
{
return null;
}
public java.rmi.Remote getPort(Class serviceDefInterface)
throws ServiceException
{
if (serviceDefInterface == null)
throw new ServiceException("No Service class specified.");
if (!java.rmi.Remote.class.isAssignableFrom(serviceDefInterface))
throw new ServiceException("Class is not a valid Interface.");
String stubName = (String) _intfMapping.get(serviceDefInterface);
Binding binding = (Binding) _intfBinding.get(serviceDefInterface);
if (stubName == null)
return getPort(serviceDefInterface, binding,
_classInfo, _typeMappingRegistry, null);
else
return getPort(stubName, binding, _typeMappingRegistry);
}
public java.rmi.Remote getPort(QName portName, Class serviceDefInterface)
throws ServiceException
{
return getPort(portName, serviceDefInterface, getProxyMode());
}
public java.rmi.Remote getPort(QName portName, Class serviceDefInterface, boolean proxy)
throws ServiceException
{
if (((proxy==false) || (serviceDefInterface == null)) &&
(portName != null)) {
String stubName = (String) _portMapping.get(portName);
Binding binding = (Binding) _portBinding.get(portName);
if (stubName == null) return getPort(null, serviceDefInterface);
try {
return getPort(stubName, binding, portName,
_typeMappingRegistry);
} catch (Exception ex) {
return getPort(null, serviceDefInterface);
}
} else {
if (serviceDefInterface == null)
throw new ServiceException("No Service class specified.");
if (!java.rmi.Remote.class.isAssignableFrom(serviceDefInterface))
throw new ServiceException("Class is not a valid Interface.");
Binding binding = (Binding) _intfBinding.get(serviceDefInterface);
String uri = (portName == null) ? null : portName.getNamespaceURI();
return getPort(serviceDefInterface, binding, _classInfo,
_typeMappingRegistry, uri);
}
}
public Call[] getCalls(QName portName)
throws ServiceException
{
ArrayList callslist = (ArrayList) _calls.get(portName);
if (callslist == null) return null;
Call[] calls = new Call[callslist.size()];
return (Call[]) callslist.toArray(calls);
}
private void addCall(QName portName, Call call)
{
ArrayList callslist = (ArrayList) _calls.get(portName);
if (callslist == null) {
callslist = new ArrayList();
_calls.put(portName, callslist);
}
callslist.add(call);
}
public AutoloanSoap_Stub getAutoloanSoap()
throws ServiceException
{
try {
return (AutoloanSoap_Stub) getPort(new QName(
"http://circle24.com/webservices/", "AutoloanSoap"), null, false);
} catch (Exception ex) {
return (AutoloanSoap_Stub) getPort(com.exsamp.net.AutoloanSoap.class);
}
}
private void createCalls()
throws ServiceException
{
Call call = null;
call = createCall(new QName("http://circle24.com/webservices/", "AutoloanSoap"),
new QName("http://circle24.com/webservices/", "Calculate"));
call.addParameter("{http://circle24.com/webservices/}Calculate",
new QName("http://circle24.com/webservices/", "Calculate"), com.exsamp.net.Calculate.class, ParameterMode.IN);
call.addParameter("{http://circle24.com/webservices/}CalculateResponse",
new QName("http://circle24.com/webservices/", "CalculateResponse"), com.exsamp.net.CalculateResponse.class, ParameterMode.OUT);
call.setReturnType(new QName("http://circle24.com/webservices/", "CalculateResponse"), com.exsamp.net.CalculateResponse.class);
call.setProperty(Call.OPERATION_STYLE_PROPERTY, "document");
call.setProperty(Call.ENCODINGSTYLE_URI_PROPERTY, null);
call.setProperty(Call.SOAPACTION_URI_PROPERTY, "\"http://circle24.com/webservices/Calculate\"");
call.setTargetEndpointAddress("http://upload.eraserver.net/circle24/autoloan.asmx");
addCall(new QName("http://circle24.com/webservices/", "AutoloanSoap"), call);
}
static boolean _proxy = true;
static final QName _serviceName;
static final Hashtable _intfMapping = new Hashtable();
static final Hashtable _intfBinding = new Hashtable();
static final Hashtable _portBinding = new Hashtable();
static final Hashtable _portMapping = new Hashtable();
static final Hashtable _classInfo = new Hashtable();
static final Properties _tmprops = new Properties();
private final Hashtable _calls = new Hashtable();
static {
_serviceName = new QName("http://circle24.com/webservices/", "com.exsamp.net.Autoloan");
_intfBinding.put(AutoloanSoap.class,
new Binding("soap", "http://upload.eraserver.net/circle24/autoloan.asmx"));
_portBinding.put(new QName("http://circle24.com/webservices/", "AutoloanSoap"),
new Binding("soap", "http://upload.eraserver.net/circle24/autoloan.asmx"));
_intfMapping.put(AutoloanSoap.class, "com.exsamp.net.AutoloanSoap_Stub");
_portMapping.put(new QName("http://circle24.com/webservices/",
"AutoloanSoap"), "com.exsamp.net.AutoloanSoap_Stub");
Hashtable _methodInfo;
Hashtable _paramInfo;
Properties _props;
_methodInfo = new Hashtable();
_paramInfo = new Hashtable();
_props = new Properties();
_props.setProperty("jbroker.web.soap.action","\"http://circle24.com/webservices/Calculate\"");
_paramInfo.put("Properties", _props);
_props = new Properties();
_props.setProperty("jbroker.web.parameter.name", "parameters");
_props.setProperty("jbroker.web.parameter.inout", "1");
_paramInfo.put("Param0", _props);
_props = new Properties();
_props.setProperty("jbroker.web.parameter.name", "parameters");
_props.setProperty("jbroker.web.parameter.inout", "2");
_paramInfo.put("Result", _props);
_methodInfo.put("Calculate", _paramInfo);
_classInfo.put("com.exsamp.net.AutoloanSoap", _methodInfo);
_tmprops.put("tm1", "com.exsamp.net.CalculateResponse com.exsamp.net.CalculateResponseMarshaler com.exsamp.net.CalculateResponseMarshaler http://circle24.com/webservices/ CalculateResponse none");
_tmprops.put("tm0", "com.exsamp.net.Calculate com.exsamp.net.CalculateMarshaler com.exsamp.net.CalculateMarshaler http://circle24.com/webservices/ Calculate none");
}
}
これは、スタブクラスで、メソッド呼び出しをHTTP SOAPリクエストとしてAutoloan Webサービスに渡します。
package com.exsamp.net;
import com.exsamp.net.holders.*;
import java.util.Properties;
import com.sssw.jbroker.web.core.Constants;
import com.sssw.jbroker.web.encoding.TypeMappingRegistry;
import com.sssw.jbroker.web.encoding.DefaultTypeMappingRegistry;
public class AutoloanSoap_Stub
extends com.sssw.jbroker.web.portable.Stub
implements AutoloanSoap
{
private static com.sssw.jbroker.web.QName _portType =
new com.sssw.jbroker.web.QName("http://circle24.com/webservices/", "AutoloanSoap");
private static final com.sssw.jbroker.web.Binding[] _bindings =
new com.sssw.jbroker.web.Binding[] {
new com.sssw.jbroker.web.Binding("soap", "http://upload.eraserver.net/circle24/autoloan.asmx"),
};
public AutoloanSoap_Stub()
{
this(null);
}
public AutoloanSoap_Stub(DefaultTypeMappingRegistry tmr)
{
super(_portType, _bindings);
_setProperty("xmlrpc.schema.uri", (Object) "http://www.w3.org/2001/XMLSchema".intern());
_setProperty("version", (Object) "1.1");
TypeMappingRegistry _tm = null;
try {
if (tmr != null)
_tm = tmr;
else {
_tm = new DefaultTypeMappingRegistry();
if (_tmprops.size() > 0) _tm.importTypeMappings(_tmprops);
}
_setTypeMappingRegistry(_tm);
} catch (Exception ex) {
throw new javax.xml.rpc.JAXRPCException("failed to initialize type mapping registry: " + ex.getMessage());
}
}
public com.exsamp.net.CalculateResponse calculate(com.exsamp.net.Calculate _arg0)
throws java.rmi.RemoteException
{
com.sssw.jbroker.web.portable.ClientResponse in = null;
try {
// create an output stream
_getDelegate().setProperty("xmlrpc.soap.operation.name",
new com.sssw.jbroker.web.QName("http://circle24.com/webservices/", "Calculate"));
//create request
com.sssw.jbroker.web.portable.ClientRequest out =
_request("Calculate", true, "literal", true, "\"http://circle24.com/webservices/Calculate\"");
_getDelegate().setProperty("soapAction", (Object) "\"http://circle24.com/webservices/Calculate\"");
_getDelegate().setProperty(Constants.HTTP_CONTENT_TYPE, (Object) "text/xml; charset=utf-8");
out._setProperties(_getDelegate().getProperties());
Object arg = null;
// marshal the parameters
arg = _arg0;
out.writeObject(arg, "http://circle24.com/webservices/", "Calculate");
// do the invocation
in = _invoke(out);
// unmarshal the results
// return
com.exsamp.net.CalculateResponse ret = null;
try {
ret = (com.exsamp.net.CalculateResponse)
in.readObject(com.exsamp.net.CalculateResponse.class, "http://circle24.com/webservices/", "CalculateResponse");
} catch (java.io.EOFException eofExc) {
ret = null;
}
return ret;
} catch (java.lang.Throwable t) {
if (t instanceof com.sssw.jbroker.web.ServiceException) {
com.sssw.jbroker.web.ServiceException sex =
(com.sssw.jbroker.web.ServiceException) t;
if (sex.getTargetException() != null)
t = sex.getTargetException();
}
// map to remote exception
throw com.sssw.jbroker.web.ServiceException.mapToRemote(t);
}
}
static final Properties _tmprops = new Properties();
static {
_tmprops.put("tm1", "com.exsamp.net.CalculateResponse com.exsamp.net.CalculateResponseMarshaler com.exsamp.net.CalculateResponseMarshaler http://circle24.com/webservices/ CalculateResponse none");
_tmprops.put("tm0", "com.exsamp.net.Calculate com.exsamp.net.CalculateMarshaler com.exsamp.net.CalculateMarshaler http://circle24.com/webservices/ Calculate none");
}
private static Properties _rootHeaders = new Properties();
static {
_rootHeaders.setProperty("content-type", "text/xml; charset=UTF-8");
_rootHeaders.setProperty("content-id", "<soapbody>");
}
}
これは、(サービスオブジェクトを通じて)スタブを取得した後、そのスタブを使用してAutoloan Webサービスのcalculate()メソッドを呼び出す、単純なクライアントアプリケーションです(このメソッド呼び出しは、コメントとして生成されます。詳細については、後の 生成されたファイルの編集で説明します)。
package com.exsamp.net;
import javax.naming.*;
public class AutoloanSoapClient
{
public void process(String[] args) throws Exception
{
AutoloanSoap remote = getRemote(args);
// The following code has been generated for your testing convenience. ln
// order to successfully test your Web Service, you must uncomment one or
// more of these lines and supply meaningful arguments where necessary.
// Once you have modified the test method(s) below, compile this class and
// execute it from a command line with your class path set appropriately.
// System.out.println("Test Result = " + remote.calculate(com.exsamp.net.Calculate));
}
public AutoloanSoap getRemote(String[] args) throws Exception
{
InitialContext ctx = new InitialContext();
String lookup = "xmlrpc:soap:com.exsamp.net.Autoloan";
Autoloan service = (Autoloan)ctx.lookup(lookup);
AutoloanSoap remote = (AutoloanSoap)service.getAutoloanSoap();
return remote;
}
public static void main(String[] args)
{
try
{
AutoloanSoapClient client = new AutoloanSoapClient();
client.process(args);
}
catch (Exception _e)
{
System.out.println("*** Error Executing Generated Test Client ***");
_e.printStackTrace();
}
}
}
このクラスは、WSDLで定義された複雑なタイプCalculateを表します。
package com.exsamp.net;
public class Calculate implements java.io.Serializable
{
public Calculate() {}
public Calculate(double monthsVal, double rateOfInterestVal, double amountVal) {
_months = monthsVal;
_rateOfInterest = rateOfInterestVal;
_amount = amountVal;
}
private double _months;
public double getMonths() {
return _months;
}
public void setMonths(double monthsVal) {
_months = monthsVal;
}
private double _rateOfInterest;
public double getRateOfInterest() {
return _rateOfInterest;
}
public void setRateOfInterest(double rateOfInterestVal) {
_rateOfInterest = rateOfInterestVal;
}
private double _amount;
public double getAmount() {
return _amount;
}
public void setAmount(double amountVal) {
_amount = amountVal;
}
public java.lang.String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("{");
buffer.append("months=" + _months);
buffer.append(",");
buffer.append("rateOfInterest=" + _rateOfInterest);
buffer.append(",");
buffer.append("amount=" + _amount);
buffer.append("}");
return buffer.toString();
}
}
このクラスは、Calculateのシリアル化および非シリアル化を処理します。
package com.exsamp.net;
import java.io.IOException;
import org.xml.sax.Attributes;
import com.sssw.jbroker.web.*;
import com.sssw.jbroker.web.encoding.*;
import com.sssw.jbroker.web.portable.InputStream;
import com.sssw.jbroker.web.portable.OutputStream;
public class CalculateMarshaler implements Marshaler
{
// attributes
// elements
private static final java.lang.String _MONTHS = "Months";
private static final java.lang.String _RATEOFINTEREST = "RateOfInterest";
private static final java.lang.String _AMOUNT = "Amount";
public Attribute[] getAttributes(Object obj)
{
return null;
}
public void serialize(OutputStream os, Object obj) throws IOException
{
Calculate jt = (Calculate) obj;
os.writeObject(new java.lang.Double(jt.getMonths()), _MONTHS);
os.writeObject(new java.lang.Double(jt.getRateOfInterest()), _RATEOFINTEREST);
os.writeObject(new java.lang.Double(jt.getAmount()), _AMOUNT);
}
public Object deserialize(InputStream is, Class javaType)
throws IOException
{
if (javaType != Calculate.class)
throw new
ServiceException("can\qt deserialize " + javaType.getName());
try {
// instantiate the object
Calculate jt = (Calculate) javaType.newInstance();
try {
// read elements
jt.setMonths(is.readDouble(_MONTHS));
jt.setRateOfInterest(is.readDouble(_RATEOFINTEREST));
jt.setAmount(is.readDouble(_AMOUNT));
} catch (java.io.EOFException eofExc) {}
return jt;
} catch (Exception ex) {
if (ex instanceof IOException)
throw (IOException) ex;
throw new ServiceException(ex);
}
}
public java.lang.String getMechanismType() { return null; }
}
これは、Calculateのタイプマッピングサポートを実装するためにJAX-RPCによって必要とされるHolderクラスです。このクラスは、holdersサブディレクトリに生成されます。
package com.exsamp.net.holders;
import com.exsamp.net.Calculate;
public final class CalculateHolder implements javax.xml.rpc.holders.Holder
{
public com.exsamp.net.Calculate value;
public CalculateHolder() { }
public CalculateHolder(com.exsamp.net.Calculate val)
{
value = val;
}
}
このクラスは、WSDLで定義された複雑なタイプCalculateResponseを表します。
package com.exsamp.net;
public class CalculateResponse implements java.io.Serializable
{
public CalculateResponse() {}
public CalculateResponse(java.lang.String calculateResultVal) {
_calculateResult = calculateResultVal;
}
private java.lang.String _calculateResult;
public java.lang.String getCalculateResult() {
return _calculateResult;
}
public void setCalculateResult(java.lang.String calculateResultVal) {
_calculateResult = calculateResultVal;
}
public java.lang.String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("{");
buffer.append("calculateResult=" + _calculateResult);
buffer.append("}");
return buffer.toString();
}
}
このクラスは、CalculateResponseのシリアル化および非シリアル化を処理します。
package com.exsamp.net;
import java.io.IOException;
import org.xml.sax.Attributes;
import com.sssw.jbroker.web.*;
import com.sssw.jbroker.web.encoding.*;
import com.sssw.jbroker.web.portable.InputStream;
import com.sssw.jbroker.web.portable.OutputStream;
public class CalculateResponseMarshaler implements Marshaler
{
// attributes
// elements
private static final java.lang.String _CALCULATERESULT = "CalculateResult";
public Attribute[] getAttributes(Object obj)
{
return null;
}
public void serialize(OutputStream os, Object obj) throws IOException
{
CalculateResponse jt = (CalculateResponse) obj;
os.writeObject(jt.getCalculateResult(), _CALCULATERESULT);
}
public Object deserialize(InputStream is, Class javaType)
throws IOException
{
if (javaType != CalculateResponse.class)
throw new
ServiceException("can\qt deserialize " + javaType.getName());
try {
// instantiate the object
CalculateResponse jt = (CalculateResponse) javaType.newInstance();
try {
// read elements
jt.setCalculateResult((java.lang.String)is.readObject(java.lang.String.class, _CALCULATERESULT));
} catch (java.io.EOFException eofExc) {}
return jt;
} catch (Exception ex) {
if (ex instanceof IOException)
throw (IOException) ex;
throw new ServiceException(ex);
}
}
public java.lang.String getMechanismType() { return null; }
}
これは、CalculateResponseのタイプマッピングサポートを実装するためにJAX-RPCによって必要とされるHolderクラスです。このクラスは、holdersサブディレクトリに生成されます。
package com.exsamp.net.holders;
import com.exsamp.net.CalculateResponse;
public final class CalculateResponseHolder implements javax.xml.rpc.holders.Holder
{
public com.exsamp.net.CalculateResponse value;
public CalculateResponseHolder() { }
public CalculateResponseHolder(com.exsamp.net.CalculateResponse val)
{
value = val;
}
}
このファイルで指定された設定は、CalculateおよびCalculateResponseのタイプマッピングの設定方法をjBroker Webに通知します。これらのマッピングは、データがXMLからJavaに、またはJavaからXMLに変換される場合に適用されます。
生成されたスタブおよびサービスクラスによってマッピングが自動的に設定されるため、このmappingsファイルは通常は必要ありません。これは、特別な状況(マッピングを無効にしたい場合など)のために提供されています。
mappingsファイルは、ソースツリー(src)のベースディレクトリに生成されます。
Calculate=com.exsamp.net.Calculate com.exsamp.net.CalculateMarshaler com.exsamp.net.CalculateMarshaler http://circle24.com/webservices/ Calculate none CalculateResponse=com.exsamp.net.CalculateResponse com.exsamp.net.CalculateResponseMarshaler com.exsamp.net.CalculateResponseMarshaler http://circle24.com/webservices/ CalculateResponse none
Web Serviceウィザードによって生成されたファイルを編集する場合は、次のガイドラインに従います。
|
ガイドライン |
詳細 |
|---|---|
|
編集する必要のあるファイル |
|
|
編集してはいけないファイル |
生成された他のファイルは編集してもかまいませんが、通常は必要ではありません。
生成されたxxxClient.javaファイルを使用する前に、次のことを確認してください。
ターゲットWebサービスの1つまたは複数のメソッドを呼び出すには、process()メソッドを編集しなければなりません。
ターゲットWebサービスにアクセスするための正しい場所(バインド)を指定するには、getRemote()メソッドを編集しなければならない場合があります。
process()メソッドでは、生成されたクライアントアプリケーションによってWebサービスのメソッドが呼び出されます。ここでは、生成されたリモートインタフェースで定義された各メソッドを呼び出して、コンソールに戻り値を表示する、コメント付きのコードを示します。例は次のとおりです。
public void process(String[] args) throws Exception
{
AutoloanSoap remote = getRemote(args);
// The following code has been generated for your testing convenience. ln
// order to successfully test your Web Service, you must uncomment one or
// more of these lines and supply meaningful arguments where necessary.
// Once you have modified the test method(s) below, compile this class and
// execute it from a command line with your class path set appropriately.
// System.out.println("Test Result = " + remote.calculate(com.exsamp.net.Calculate));
}
ハードコード化された値またはランタイム時に提供されるパラメータとして、各メソッド呼び出しに適切な引数を提供します。ランタイム引数には、指定された値を検証するコードを追加することもできます。
戻りデータタイプをチェックし、toString()を使用して変換できることを確認します。toString()を使用して変換できない場合は、System.out.printlnに代わるものを使用して、返されたデータを表示します。
編集後のcalculate()メソッド呼び出しの行は、次のようになります。
System.out.println("Autoloan Web Service\n " +
"Loan input data:\n 24 months, 8%, $15000\n " +
"Output from the Web Service:\n " +
remote.calculate(new com.exsamp.net.Calculate(24, 8, 15000)));
この節では、getRemote()メソッドの基本的な使用方法、およびバインド情報を指定する必要がある場合のgetRemote()メソッドの修正方法について説明します。
基本的な使用方法 getRemote()メソッドでは、Webサービスへのメソッド呼び出しを処理するために、生成されたクライアントアプリケーションによってリモートオブジェクトが取得されます。このリモートオブジェクトは、生成されたスタブクラス(xxx_Stub)のインスタンスです。スタブインスタンスを作成するために、getRemote()では次のことが実行されます。
getRemote()に対して生成された一般的なコードの例は、次のようになります。通常は、このコードを編集する必要はありません。
public AutoloanSoap getRemote(String[] args) throws Exception
{
InitialContext ctx = new InitialContext();
String lookup = "xmlrpc:soap:com.exsamp.net.Autoloan";
Autoloan service = (Autoloan)ctx.lookup(lookup);
AutoloanSoap remote = (AutoloanSoap)service.getAutoloanSoap();
return remote;
}
バインド情報の指定 ウィザードにより、ターゲットWebサービスのバインド情報が、生成されたスタブクラス(xxx_Stub.java)およびサービス実装クラス(xxxServiceImpl.java)に含まれます。バインドでは、Webサービスにアクセスできる場所の「サービスエンドポイントアドレス」が提供されます。WSDLファイルでは、このアドレスは、soap:address location要素のURLです。
別の方法として、getRemote()メソッドでスタブインスタンスを作成する際に、使用するバインドを指定することもできます。この方法を使用すると、(Webサービスが新しい場所に移動した場合などに)スタブクラスのバインドを無効にできます。スタブのアドレスプロパティを設定するために、次のように1行のコードを追加するだけで、これを実行できます。
public AutoloanSoap getRemote(String[] args) throws Exception
{
InitialContext ctx = new InitialContext();
String lookup = "xmlrpc:soap:com.exsamp.net.Autoloan";
Autoloan service = (Autoloan)ctx.lookup(lookup);
AutoloanSoap remote = (AutoloanSoap)service.getAutoloanSoap();
((javax.xml.rpc.Stub)remote)._setProperty("javax.xml.rpc.service.endpoint.address",
"http://upload.eraserver.net/circle24/autoloan.asmx");
return remote;
}
この時点でのWebサービスコンシューマコードの使用方法は、開発しているアプリケーションの性質によって異なります。たとえば、場合によっては、生成されたxxxClient.javaファイルを強化してアプリケーションに含める必要があったり、xxxClient.javaから独自のクラスに構文をコピーすることだけが必要になったりします。しかし、いずれの場合でも、生成されたリモートインタフェース、サービス、およびスタブファイルが常に必要となります。
アプリケーション固有のコーディングを開始する前に、基本的なxxxClientをテストして、コンシューマコードが期待どおりに機能することを確認しておくことが推奨されます。まず、ソースファイルをコンパイルするためにプロジェクトを作成する必要があります。その後、次の節で説明するように、xxxClientを実行できます。
生成されたWebサービスコンシューマプログラムであるxxxClientは、標準のJavaアプリケーションです。このプログラムは、次のいずれかの方法で実行できます。
生成されたクライアントをすばやく簡単にテストできるようにするために、WorkbenchにはWeb Service Wizard Client Runnerが装備されています。この機能によって、現在のプロジェクトのクライアントアプリケーションがリストされ、実行するクライアントアプリケーションを選択できます。クライアントアプリケーションを実行するたびに、必要なファイルをすべて含むようにクラスパスが自動的に設定され、コマンドライン引数を指定できるようになります。
[Project]>[Run Web Service Client Class]の順に選択して、[Client Runner]ウィンドウを表示します。
[Client class to run]ドロップダウンからクライアントを選択します。
このドロップダウンリストには、プロジェクト内でmain()メソッドを持つコンパイル済みのクラスがすべて表示されます。
たとえば、生成されたAutoloanSoapClientクラスをClient Runnerを使用して実行すると、次のようになります。
AutoloanSoapClientが実行されると、Autoloan Webサービスのcalculate()メソッドが呼び出され、ローンデータ(期間、率、金額)を含むCalculateオブジェクトが渡されます。calculate()メソッドは、支払い情報の文字列を含むCalculateResponseオブジェクトを返します(これは、AutoloanSoapClientによって画面に表示されます)。
Running com.exsamp.net.AutoloanSoapClient...
*********************
Autoloan Web Service
Loan input data:
24 months, 8%, $15000
Output from the Web Service:
{calculateResult=Equated Monthly Instalment (EMI) For the Amount $15000 is $678}
*********************
生成されたクライアントは、オペレーティングシステムのコマンドプロンプトから実行することもできます。この場合、必要なファイル(生成されたコンシューマクラス、jbroker-webなど)をすべて含むようにクラスパスを設定する必要があります。
クライアントのコマンドラインを表示してコピーするには、Web Service Wizard Client Runnerを使用する方法が推奨されます(前の節の説明を参照)。その後、コマンドラインをコマンドプロンプトに貼り付けて実行できます。
クライアントを他のコンピュータ(開発マシン以外)で実行する場合は、このコマンドラインにリストされるすべてのファイルにアクセスできることを確認してください。
|
開発ガイド 05/16/03 09:21:28 |
Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC, a wholly owned subsidiary of Novell, Inc. All rights reserved.