Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービス・スタート・ガイド 11gリリース1 (10.3.6) B61645-06 |
|
![]() 前 |
![]() 次 |
この章では、Java API for XML-based Web service (JAX-WS) を使用してWebLogic Webサービスを呼び出す方法について説明します。
この章では、以下のトピックについて説明します。
詳細については、以下を参照してください。
メッセージ保護されたWebサービスの呼出しの詳細は、『Oracle WebLogic Server WebLogic Webサービスの保護』のクライアント・アプリケーションの更新によるメッセージ保護されたWebサービスの呼出しに関する項を参照してください。
Webサービス・クライアント開発におけるベスト・プラクティスは、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』のWebサービスの非同期起動に関する項を参照してください。
Webサービスの非同期起動については、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』のWebサービスの非同期起動に関する項を参照してください。
javax.xml.ws.Service APIを使用して、Webサービス・クライアントがサービス・エンドポイント・インタフェース(SEI)に基づいて実行時に動的にWebサービスを呼び出す(clientgen
は使用しない)ことができるdynamic proxy client
の作成については、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』の動的プロキシ・クライアントの作成に関する項を参照してください。
注意: この章では、clientgen またはwsdlc Antタスクで生成されるクライアント側のアーチファクトを使用してWebサービスを呼び出す場合、CLASSPATHのWebLogic Serverクラスの全体のセットを持っていることが想定されます。 |
Webサービスの起動とは、Webサービスを使用するためにクライアント・アプリケーションが実行する操作のことです。
クライアント・アプリケーションには以下の2種類があります。
Java SE クライアント - 最も単純な形式では、java
コマンドで呼び出すMain
パブリック・クラスがあるJavaプログラムです。
WebLogic ServerにデプロイされたJava EEコンポーネント - この種のクライアント・アプリケーションでは、EJB、サーブレット、または別のWebサービスなど、WebLogic ServerにデプロイされているJava Platform, Enterprise Edition (Java EE)バージョン5コンポーネント内でWebサービスが実行されます。したがって、WebLogic Serverコンテナの内部で実行されます。
(WebLogic Serverクラスパスへのアクセス権を使用して)WebLogic Serverで実行されているJava SEまたはJava EEアプリケーションからWebサービスを呼び出すことができます。WebLogic Serverライブラリが使用できない環境で実行されているスタンドアロンJavaアプリケーションのサポートは、JAX-WSのこのリリースでは使用できません。
後続のセクションでは、JAX-WS仕様のOracleの実装を使用して、Javaクライアント・アプリケーションからWebサービスを呼び出す方法について説明します。この実装を使用することで、WebLogicおよび非WebLogicにかかわらず任意のアプリケーション・サーバーで実行されているWebサービスを呼び出すことができます。
この章では、呼び出す必要のある特定のWebサービス用にService
インタフェース実装の静的Javaクラスを生成する方法について説明します。動的プロキシ・クライアントの生成の詳細は、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』の動的プロキシ・クライアントの作成を参照してください。
WebLogic ServerのWL_HOME
/samples/server/examples/src/examples/webservices
ディレクトリには、WebLogic Webサービスの作成と呼出しのサンプルがあります(WL_HOME
は、WebLogicサーバー・のメイン・ディレクトリです)。サンプルのビルドおよび実行方法の詳細については、ブラウザでWebページWL_HOME
/samples/server/docs/index.html
を開いて、「WebLogic Serverサンプル」->「サンプル」->「API」->「Webサービス」ノードを展開してください。
このセクションで説明されているコマンド・ライン・ツールの他に、Webサービス・プロキシを生成およびテストするためにOracle JDeveloperまたはOracle Enterprise Pack for Eclipse (OEPE)のようなIDEを使用できます。詳細は、『Oracle WebLogic Server WebLogic Webサービスの紹介』のWebサービスをビルドするためのOracle IDEの使用に関する項を参照してください。
注意: (WebLogic Serverクラスパスへのアクセス権を使用して)WebLogic Serverで実行されているJava SEまたはJava EEアプリケーションからWebサービスを呼び出すことができます。WebLogic Serverライブラリが使用できない環境で実行されているスタンドアロンJavaアプリケーションからのWebサービスの呼出し、JAX-WS Webサービスのこのリリースではサポートされていません。 |
次の表では、Webサービスを呼び出すJava SEアプリケーションを作成する主要な手順をまとめています。
注意: 開発環境でのクライアント・アプリケーションのビルドやJavaファイルのコンパイルなどにAntを使用すること、およびWebサービスのクライアント・タスクで更新する必要のあるbuild.xml ファイルがすでに存在することを想定しています。開発環境でのAntの使用に関する一般情報は、「基本的なAnt build.xmlファイルの作成」を参照してください。この項で使用しているbuild.xml ファイルの完全な例は、「JavaクライアントのサンプルAntビルド・ファイル」を参照してください。 |
表6-1 Java SEクライアントからWebサービスを呼び出す手順
# |
手順 | 説明 |
---|---|---|
1 |
環境を設定します。 |
コマンド・ウィンドウを開いて、ドメイン・ディレクトリの |
2 |
|
|
3 |
Webサービスに関する情報(その操作のシグネチャ、ポートの名前など)を取得します。 |
「Webサービスに関する情報の取得」を参照してください。 |
4 |
Webサービス操作を呼び出すためのコードを含むクライアント・アプリケーションのJavaコードを記述します。 |
「Webサービスを呼び出すJavaクライアント・アプリケーション・コードの記述」を参照してください。 |
5 |
基本のAntビルド・ファイル |
「基本的なAnt build.xmlファイルの作成」を参照してください。 |
6 |
Javaクライアント・アプリケーションをコンパイルし、実行します。 |
「クライアント・アプリケーションのコンパイルと実行」を参照してください。 |
clientgen
WebLogic WebサービスAntタスクは、クライアント・アプリケーションがWebLogic Webサービスと非WebLogic Webサービスの両方の呼出しに使用できるクライアント・アーティファクトを既存のWSDLファイルから生成します。次のようなアーティファクトがあります。
呼出しの対象となる特定のWebサービスに対するService
インタフェース実装のJavaクラス。
JAXBデータ・バインディング・アーティファクト。
WSDLファイルで指定されたユーザー定義XMLスキーマ・データ型のJavaクラス。
clientgen
Antタスクの詳細(使用可能なすべての属性など)は、『『Oracle WebLogic Server WebLogic Webサービス・リファレンス』』のAntタスク・リファレンスに関する項を参照してください。
次のサンプルのように、build.xml
ファイルを更新してclientgen
Antタスクに呼出しを追加します。
<taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" /> <target name="build-client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" destDir="clientclasses" packageName="examples.webservices.simple_client" type="JAXWS"/> </target>
clientgen
WebLogic WebサービスAntタスクを実行するには、その前にこのタスクの完全なJavaクラス名を標準のtaskdef
Antタスクを使用して指定する必要があります。
クライアント側アーティファクトの作成に使用するWSDLファイルと、そうしたアーティファクトの生成先ディレクトリを指定するには、clientgen
Antタスクのwsdl
属性とdestDir
属性を含める必要があります。packageName
属性は省略できます。省略した場合、clientgen
タスクではWSDLのtargetNamespace
に基づくパッケージ名が使用されます。この例ではtype
を指定する必要があります。指定しない場合、JAXRPC
がデフォルト値になります。
この例では、パッケージ名はクライアント・アプリケーションと同じパッケージ名examples.webservices.simple_client
に設定されます。パッケージ名をクライアント・アプリケーションとは異なる名前に設定した場合は、適切なクラス・ファイルをインポートする必要があります。たとえば、examples.webservices.complex
というパッケージ名にした場合、クライアント・アプリケーションの以下のクラス・ファイルをインポートする必要があります。
import examples.webservices.complex.BasicStruct; import examples.webservices.complex.ComplexPortType; import examples.webservices.complex.ComplexService;
注意: clientgen AntタスクのdestFile 属性を使用すると、生成されたJavaファイルを自動的にコンパイルして、すべてのアーティファクトをJARファイルにパッケージ化できます。詳細と例については、『Oracle WebLogic Server WebLogic Webサービス・リファレンス』のclientgenに関する項を参照してください。 |
WSDLファイルで、Webサービス操作の入力パラメータまたは戻り値としてユーザー定義のデータ型が指定されている場合、clientgen
はWSDLに定義されたXMLスキーマ・データ型のJava表現であるJavaBeanクラスを自動的に生成します。JavaBeanクラスは、destDir
ディレクトリに生成されます。
この手順で説明されている追加のターゲット(clean
など)を含む、完全なサンプルbuild.xml
ファイルについては、「JavaクライアントのサンプルAntビルド・ファイル」を参照してください。
clientgen
Antタスクを他のサポートAntタスクと一緒に実行するには、コマンド・ラインでbuild-client
ターゲットを指定します。
prompt> ant build-client
clientclasses
ディレクトリで、clientgen
Antタスクによって生成されたファイルやアーティファクトを確認します。
操作を呼び出すJavaクライアント・アプリケーション・コードの記述に先立って、Webサービスの名前と操作のシグネチャを知る必要があります。この情報を調べるには様々な方法があります。
一番よいのは、clientgen
Antタスクを使用してWebサービス固有のService
ファイルを生成し、生成された*.java
ファイルを調べる方法です。destDir
属性で指定したディレクトリ内のpackageName
属性の値に対応したサブディレクトリに生成されます。packageName属性が指定されていない場合、WSDLのtargetNamespace
に基づくパッケージに対応したサブディレクトリに生成されます。
ServiceName
.java
ソース・ファイルには、Webサービスのポートを取得するためのgetPortName()
メソッドが含まれており、ServiceName
はWebサービス名、PortName
はポート名を意味します。WebサービスがJWSファイルで実装されている場合、Webサービス名は@WebService
JWSアノテーションのserviceName
属性の値となり、ポート名はjwsc
Antタスクの<jws>
要素の子要素<WLHttpTransport>
のportName
属性の値となります。
PortType.
java
ファイルには、Webサービスのパブリック操作に対応するメソッド・シグネチャが含まれており、PortType
はWebサービスのポートの種類を表します。WebサービスがJWSファイルで実装されている場合、ポートの種類は@WebService
JWSアノテーションのname
属性の値となります。
Webサービスの実際のWSDLを調べることもできます。デプロイされているWebLogic WebサービスのWSDLの詳細は、「WebサービスのWSDLの参照」を参照してください。Webサービス名は、次のTraderService
WSDLの引用に示すように、<service>
要素内にあります。
<service name="TraderService"> <port name="TraderServicePort" binding="tns:TraderServiceSoapBinding"> ... </port> </service>
このWebサービス用に定義されている操作は、対応する<binding>
要素の下に記述されています。たとえば次のWSDLの抜粋は、TraderService
Webサービスにbuy
とsell
の2つの操作があることを示しています(わかりやすくするため、WSDLの関連部分のみを記載しています)。
<binding name="TraderServiceSoapBinding" ...> ... <operation name="sell"> ... </operation> <operation name="buy"> </operation> </binding>
次のサンプル・コードでは、JavaアプリケーションがWebサービス操作を呼び出しています。アプリケーションは、標準JAX-WS APIコードと、clientgen
によって生成されたService
インタフェースのWebサービス固有の実装を使用して、Webサービスの操作を呼び出します。
このサンプルでは、ユーザー定義のデータ型(examples.webservices.simple_client.BasicStruct
)を入力パラメータおよび戻り値として使用する操作を呼び出す方法も示します。clientgen
Antタスクによって、このユーザー定義のデータ型のJavaコードが自動的に生成されます。
<clientgen>
packageName
属性はクライアント・アプリケーションと同じパッケージ名に設定されているため、<clientgen>
生成ファイルをインポートする必要はありません。
package examples.webservices.simple_client; /** * This is a simple Java application that invokes the * the echoComplexType operation of the ComplexService Web service. */ public class Main { public static void main(String[] args) { ComplexService test = new ComplexService(); ComplexPortType port = test.getComplexPortTypePort(); BasicStruct in = new BasicStruct(); in.setIntValue(999); in.setStringValue("Hello Struct"); BasicStruct result = port.echoComplexType(in); System.out.println("echoComplexType called. Result: " + result.getIntValue() + ", " + result.getStringValue()); } }
上記の例で注目すべき点は以下のとおりです。
次のコードは、ComplexPortType
スタブを作成する方法を示します。
ComplexService test = new ComplexService(), ComplexPortType port = test.getComplexPortTypePort();
ComplexService
クラスはJAX-WS Service
インタフェースを実装します。getComplexServicePortTypePort()
メソッドは、ComplexPortType
スタブ実装のインスタンスを返すために使用します。
次のコードは、ComplexService
WebサービスのechoComplexType
操作を呼び出す方法を示します。
BasicStruct result = port.echoComplexType(in);
echoComplexType
操作は、BasicStruct
というユーザー定義データ型を返します。
すべてのJavaファイル(クライアント・アプリケーションおよびclientgen
によって生成されたファイルの両方)をクラス・ファイルにコンパイルするには、build.xml
ファイルのbuild-client
ターゲットにjavac
タスクを追加します。該当箇所を次のサンプルに太字で示します。
<target name="build-client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" destDir="clientclasses" packageName="examples.webservices.simple_client" type="JAXWS"/> <javac srcdir="clientclasses" destdir="clientclasses" includes="**/*.java"/> <javac srcdir="src" destdir="clientclasses" includes="examples/webservices/simple_client/*.java"/> </target>
この例では、1番目のjavac
タスクでclientgen
によって生成されたclientclasses
ディレクトリ内のJavaファイルをコンパイルし、2番目のjavac
タスクでカレント・ディレクトリのexamples/webservices/simple_client
サブディレクトリ(Javaクライアント・アプリケーションのソースの場所と想定されるディレクトリ)内にあるJavaファイルをコンパイルしています。
この例では、clientgen
によって生成されたJavaソース・ファイルとコンパイル後のクラスが同じディレクトリ(clientclasses
)に格納されます。プロトタイピングの段階ではこれで十分ですが、多くの場合はソース・コード(生成されたコードも含む)とコンパイルされたクラスを別々のディレクトリに格納するのがベスト・プラクティスです。これを行うには、両方のjavac
タスクのdestdir
に、srcdir
ディレクトリとは異なるディレクトリを設定します。クライアント・アプリケーションを実行するには、java
タスクの呼出しを含むbuild.xml
にrun
ターゲットを追加します。次に例を示します。
<path id="client.class.path"> <pathelement path="clientclasses"/> <pathelement path="${java.class.path}"/> </path> <target name="run" > <java fork="true" classname="examples.webServices.simple_client.Main" failonerror="true" > <classpath refid="client.class.path"/> </target>
path
タスクは、CLASSPATHにclientclasses
ディレクトリを追加します。run
ターゲットはMain
アプリケーションを呼び出し、デプロイされたWebサービスのURLを1つの引数として渡します。
この手順で説明されている追加のターゲット(cleanなど)を含む、完全なサンプルbuild.xml
ファイルについては、「JavaクライアントのサンプルAntビルド・ファイル」
を参照してください。
アーティファクトを再生成してクラスに再コンパイルするためにbuild-client
ターゲットを再実行してから、run
ターゲットを実行してechoStruct
操作を呼び出します。
prompt> ant build-client run
build.xml
ファイルのbuild-client
およびrun
ターゲットを使用して、開発プロセスの一環としてJavaクライアント・アプリケーションを繰返し更新、再ビルド、および実行できます。
次の例では、Javaクライアントを生成およびコンパイルするための完全なbuild.xml
ファイルを示します。太字のセクションについては、「クライアントのアーティファクトを生成するためのclientgen Antタスクの使用」および「クライアント・アプリケーションのコンパイルと実行」を参照してください。
<project name="webservices-simple_client" default="all"> <!-- set global properties for this build --> <property name="wls.hostname" value="localhost" /> <property name="wls.port" value="7001" /> <property name="example-output" value="output" /> <property name="clientclass-dir" value="${example-output}/clientclass" /> <path id="client.class.path"> <pathelement path="${clientclass-dir}"/> <pathelement path="${java.class.path}"/> </path> <taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" /> <target name="clean" > <delete dir="${clientclass-dir}"/> </target> <target name="all" depends="clean,build-client,run" /> <target name="build-client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" destDir="${clientclass-dir}" packageName="examples.webservices.simple_client" type="JAXWS"/> <javac srcdir="${clientclass-dir}" destdir="${clientclass-dir}" includes="**/*.java"/> <javac srcdir="src" destdir="${clientclass-dir}" includes="examples/webservices/simple_client/*.java"/> </target> <target name="run" > <java fork="true" classname="examples.webservices.simple_client.Main" failonerror="true" > <classpath refid="client.class.path"/> </java> </target> </project>
WebLogic Webサービス内からのWebサービスの呼出しは、「Java SEクライアントからのWebサービスの呼出し」で説明している、Java SEアプリケーションからのWebサービスの呼出しに似ていますが、次の点が異なります:
呼び出されるWebサービスのJAX-WS Service
インタフェースを生成するclientgen
Antタスクを使用するかわりに、呼び出す側のWebサービスをコンパイルするjwsc
Antタスクの内部で、<jws>
要素の<clientgen>
子要素を使用します。一方、他のWebサービスを呼び出すJWSファイルでは、Service
およびPortType
インスタンスの取得に同じ標準JAX-WS APIを使用して、Webサービス操作を呼び出します。
Webサービスに対する参照の定義に@WebServiceRef
アノテーションを使用できます。「Webサービスを呼び出すサンプルJWSファイル」を参照してください。
この項では、Webサービス(特に別のWebサービス)をJava EEコンポーネント内のクライアントから呼び出す場合とJava SEクライアントから呼び出す場合の違いについて説明します。「Java SEクライアントからのWebサービスの呼出し」をすでに読み、理解していることが前提となります。また、クライアント・アプリケーションのビルドやJavaファイルのコンパイルなどに開発環境でAntを使用していること、そして別のWebサービスを呼び出すために更新したいWebサービスをビルドするbuild.xml
ファイルをすでに持っていることも前提となります。
クライアントWebサービスをビルドするbuild.xml
ファイルに加える必要のある変更は次のとおりです(このクライアントWebサービスが別のWebサービスを呼び出すことになります)。build.xmlファイルの完全なサンプルについては、「Webサービス・クライアントのサンプルbuild.xmlファイル」
を参照してください。
JWSファイル(別のWebサービスを呼び出すWebサービスを実装しているもの)を指定する<jws>
要素に、<clientgen>
子要素が追加されます。呼び出されるWebサービスのWSDLに、必要なwsdl
属性を設定します。JAX-WSクライアント・スタブの生成先とするパッケージに、必要なpackageName
属性を設定します。
クライアントWebサービスを実装するJWSファイルに加える必要のある変更は次のとおりです。JWSファイルの完全なサンプルについては、「Webサービスを呼び出すサンプルJWSファイル」を参照してください。
jwsc
Antタスクの<clientgen>
子要素で生成される一連のファイルがインポートされます。これらのファイルには、呼び出されるWebサービスの操作でパラメータまたは戻り値として使用するユーザー定義データ型のJava表現のみでなく、呼び出されるWebサービスのJAX-WS Service
インタフェースも含まれます。
注意: <clientgen> のpackageName 属性で設定されているパッケージ名が、クライアント・アプリケーションと同じパッケージ名である場合、<clientgen> 生成ファイルをインポートする必要はありません。 |
Service
およびPortType
インタフェース実装を取得して、通常どおりポート上で操作を呼び出します。詳細は、「Webサービスを呼び出すJavaクライアント・アプリケーション・コードの記述」を参照してください。
次のサンプルbuild.xml
ファイルでは、別のWebサービスを呼び出すWebサービスを作成する方法を示します。別のWebサービスを呼び出さない単純なWebサービスをビルドするためのbuild.xml
と異なっている部分は、太字で示されています。
この場合のbuild-service
ターゲットは、単純なWebサービスをビルドするターゲットとよく似ています。唯一の違いは、呼び出すWebサービスをビルドするjwsc
Antタスクに<jws>
要素の<clientgen>
子要素も含まれるという点で、これによってjwsc
では必要なJAX-WSクライアント・スタブも生成されるようになります。
<project name="webservices-service_to_service" default="all"> <!-- set global properties for this build --> <property name="wls.username" value="weblogic" /> <property name="wls.password" value="weblogic" /> <property name="wls.hostname" value="localhost" /> <property name="wls.port" value="7001" /> <property name="wls.server.name" value="myserver" /> <property name="ear.deployed.name" value="ClientServiceEar" /> <property name="example-output" value="output" /> <property name="ear-dir" value="${example-output}/ClientServiceEar" /> <property name="clientclass-dir" value="${example-output}/clientclasses" /> <path id="client.class.path"> <pathelement path="${clientclass-dir}"/> <pathelement path="${java.class.path}"/> </path> <taskdef name="jwsc" classname="weblogic.wsee.tools.anttasks.JwscTask" /> <taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" /> <taskdef name="wldeploy" classname="weblogic.ant.taskdefs.management.WLDeploy"/> <target name="all" depends="clean,build-service,deploy,client" /> <target name="clean" depends="undeploy"> <delete dir="${example-output}"/> </target> <target name="build-service"> <jwsc srcdir="src" destdir="${ear-dir}" > <jws file="examples/webservices/service_to_service/ClientServiceImpl.java" type="JAXWS"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL" packageName="examples.webservices.complex" /> </jws> </jwsc> </target> <target name="deploy"> <wldeploy action="deploy" name="${ear.deployed.name}" source="${ear-dir}" user="${wls.username}" password="${wls.password}" verbose="true" adminurl="t3://${wls.hostname}:${wls.port}" targets="${wls.server.name}" /> </target> <target name="undeploy"> <wldeploy action="undeploy" name="${ear.deployed.name}" failonerror="false" user="${wls.username}" password="${wls.password}" verbose="true" adminurl="t3://${wls.hostname}:${wls.port}" targets="${wls.server.name}" /> </target> <target name="client"> <clientgen wsdl="http://${wls.hostname}:${wls.port}/ClientService/ClientService?WSDL" destDir="${clientclass-dir}" packageName="examples.webservices.service_to_service.client" type="JAXWS"/> <javac srcdir="${clientclass-dir}" destdir="${clientclass-dir}" includes="**/*.java"/> <javac srcdir="src" destdir="${clientclass-dir}" includes="examples/webservices/service_to_service/client/**/*.java"/> </target> <target name="run"> <java classname="examples.webservices.service_to_service.client.Main" fork="true" failonerror="true" > <classpath refid="client.class.path"/> </java> </target> </project>
次に示すサンプルJWSファイル(ClientServiceImpl.java
)は、ClientService
というWebサービスを実装しており、このWebサービスに含まれている操作がComplexService
というWebサービスのechoComplexType
操作を呼び出します。この操作では、パラメータとしても戻り値としてもユーザー定義データ型(BasicStruct
)を使用します。該当するコードを太字で示し、例の後で説明を加えます。
package examples.webservices.service_to_service; import javax.jws.WebService; import javax.jws.WebMethod; import javax.xml.ws.WebServiceRef; // Import the BasicStruct data type, generated by clientgen and used // by the ComplexService Web Service import examples.webservices.complex.BasicStruct; // Import the JAX-WS stubs generated by clientgen for invoking // the ComplexService Web service. import examples.webservices.complex.ComplexPortType; import examples.webservices.complex.ComplexService; @WebService(name="ClientPortType", serviceName="ClientService", targetNamespace="http://examples.org") public class ClientServiceImpl { // Use the @WebServiceRef annotation to define a reference to a Web service. @WebServiceRef() ComplexService test; @WebMethod() public String callComplexService(BasicStruct input, String serviceUrl) { // Create a port stub to invoke ComplexService ComplexPortType port = test.getComplexPortTypePort(); // Invoke the echoComplexType operation of ComplexService BasicStruct result = port.echoComplexType(input); System.out.println("Invoked ComplexPortType.echoComplexType." ); return "Invoke went okay! Here's the result: '" + result.getIntValue() + ", " + result.getStringValue() + "'"; } }
別のWebサービスを呼び出すJWSファイルをプログラミングする際は、次のガイドラインに従います。ガイドラインのサンプル・コードは、上述のサンプル内では太字で示されています。
呼び出されるWebサービスで使用されるユーザー定義データ型をインポートします。このサンプルでは、ComplexService
でBasicStruct
JavaBeanを使用しています。
import examples.webservices.complex.BasicStruct;
ComplexService
WebサービスのJAX-WSインタフェースをインポートします。このスタブは、<jws>
の<cliengen>
子要素によって生成されます。
import examples.webservices.complex.ComplexPortType; import examples.webservices.complex.ComplexService;
@WebServiceRef
アノテーションを使用して、Webサービスへの参照およびそのインジェクション・ターゲットを定義します。
@WebServiceRef() ComplexService service;
または、次に示すように、ComplexService Webサービスへのプロキシ・スタブを作成できます。
ComplexService test = new ComplexService();
Webサービス参照でgetComplexPortTypePort()
操作を呼び出すことによって、ComplexPortType
スタブ実装のインスタンスを戻します。
ComplexPortType port = service.getComplexPortTypePort();
ComplexService
のechoComplexType
操作を、直前にインスタンス化したポートを使用して呼び出します。
BasicStruct result = port.echoComplexType(input);
デフォルトでは、Webサービス・クライアントではサーバーに対して定義されているWebサービス構成を使用します。次のメソッドのいずれかを使用してWebサービス・クライアントが使用する構成設定をオーバーライドできます。
該当する場合、管理またはWLSTを使用。クライアントで構成可能なのはWebサービス機能のサブセットのみです。
@WebServiceRef
アノテーションを使用してWebサービスのクライアントを指定のWebサービス参照に対して定義する構成に関連付けます。Webサービスの参照構成はWebコンテナではweblogic.xml
に定義され、EJBコンテナではweblogic-ejb-jar.xml
で定義されます。@WebServiceRef
アノテーションの詳細は、「@WebServiceRefアノテーションを使用したWebサービス参照を定義」を参照してください。
Webサービスの信頼性のあるメッセージング・クライアントを作成する場合は、WsrmClientInitFeature
を使用。詳細は、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』のWebサービス・クライアントの信頼性のあるメッセージングの構成に関する項を参照してください。
@WebServiceRef
アノテーションを使用すると、Webサービスへの参照を定義し、クライアント・インスタンスにWebサービスの構成をアタッチできます。
たとえば、次のコードの引用では、@WebServiceRef
を使用して、クライアントのWebサービス・インスタンスにMyReliableEchoService
の構成をアタッチします。後で作成および初期化されるポートは、Webアプリケーションのweblogic.xml
のMyReliableEchoService
サービス参照で定義されているプロパティを使用します。
package wsrm_jaxws.example; import java.xml.ws.WebService; import java.xml.ws.WebServiceRef; import wsrm_jaxws.example.client_service.*; import wsrm_jaxws.example.client_service.EchoResponse; ... @WebService public class ClientServiceImpl { @WebServiceRef(name="MyServiceRef") private ReliableEchoService service; private ReliableEchoPortType port = null; @PostConstruct public void initPort() { port = service.getReliableEchoPort(); ... } }
例6-1にWebサービス参照の記述を含むweblogic.xml
ファイルの例を示します。この例に示す信頼性のあるメッセージ・プロパティの詳細は、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』の信頼性のあるメッセージングの構成に関する項を参照してください。
例6-1 Webサービス参照の記述を含むweblogic.xmlのサンプル・ファイル
<?xml version='1.0' encoding='UTF-8'?> <weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"> <service-reference-description> <!-- Any name you want, but use this same name on @WebServiceRef(name=<my name>). This anno goes on the service field in your client container --> <service-ref-name>MyServiceRef</service-ref-name> <!-- Use / and any path within the web app to get a local WSDL, or use a resource name as defined by the Java ClassLoader, or use an absolute/external URL you can guarantee is deployed when this web app deploys --> <wsdl-url>/WEB-INF/wsdls/ReliableEcho.wsdl</wsdl-url> <!-- One or more port-infos, one for each type of port/stub you'll create in your JWS --> <port-info> <!-- The local name of wsdl:port (not portType). The Java type for this port, when created from the @WebServiceRef JWS field, will contain, in RequestContext, the props you define below --> <port-name>ReliableEchoPort</port-name> <!-- Any prop name/value pairs you want to show up on you service stub The Java type for this port, when created from the @WebServiceRef JWS field, will contain, in RequestContext, the stub-props you define below --> <!-- RM Source Properties --> <stub-property> <name>weblogic.wsee.wsrm.BaseRetransmissionInterval</name> <value>PT30S</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.RetransmissionExponentialBackoff</name> <value>true</value> </stub-property> <!-- RM Destination Properties --> <stub-property> <name>weblogic.wsee.wsrm.RetryCount</name> <value>5</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.RetryDelay</name> <value>PT30S</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.AcknowledgementInterval</name> <value>PT5S</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.NonBufferedDestination</name> <value>true</value> </stub-property> <!-- RM Source *or* Destination Properties --> <stub-property> <name>weblogic.wsee.wsrm.InactivityTimeout</name> <value>PT5M</value> </stub-property> <stub-property> <name>weblogic.wsee.wsrm.SequenceExpiration</name> <value>PT10M</value> </stub-property> </port-info> </service-reference-description> <wl-dispatch-policy>weblogic.wsee.mdb.DispatchPolicy</wl-dispatch-policy> </weblogic-web-app>
Webサービスを使用すると、クライアント・アイデンティティ(クライアントID)として表される意味のある名前をクライアントに割り当てることができます。このクライアントIDを使用して、実行時検証のレポートの目的などで統計情報およびその他の監視情報をグループ化します。
サーバー上のクライアント(WebLogic Serverインスタンス内のコンテナで実行されるクライアント)では、次のいずれかの方法でクライアントIDを生成できます。
Webサービス・ポートへの接続を初期化する場合はクライアントで実行。これは、推奨アプローチです。「ポート初期化時のクライアントIDの定義」を参照してください。
サーバーで実行、その後クライアントで検出。クライアント「サーバー生成のクライアントIDへのアクセス」を参照してください。
注意: 省略可能ですが、クライアントIDを明示的に定義することをお薦めします。 |
weblogic.wsee.jaxws.persistence.ClientIdentityFeature
クライアント機能を使用すると、Webサービス・クライアントがWebサービスのクライアントIDを設定およびアクセスできます。次の表では、ClientIdentityFeature
メソッドをまとめます。
表6-2 クライアントIDの設定およびアクセスのためのClientIdentityFeatureメソッド
メソッド | 説明 |
---|---|
|
Webサービス・ポートで現在定義されているクライアントIDを取得します。 |
|
Webサービス・ポートのクライアントIDを設定します。 また、 ClientIdentityFeature clientIDFeature = new ClientIdentityFeature("MyBackendServiceAsyncClient"); |
|
クライアントIDを破棄します。 クライアントIDを明示的に破棄される場合、クライアントIDを使用するクライアント・インスタンスのコンテナが無効化されるとき(ホストWebアプリケーションまたはEJBが無効化される場合など)に実行されます。詳細は、「クライアント・アイデンティティのライフサイクル」を参照してください。 |
次の項は、クライアントIDを管理するためのメソッドを説明します。
クライアントIDを提供するには、初期化時にクライアントIDを含むClientIdentityFeature
のインスタンスをWebサービス・ポートに渡すことができます。
クライアントIDは、クライアントを含むWebアプリケーションまたはEJB内で一意である必要があります。クライアントIDがビジネスの目的を適宜反映していることをお薦めします。クライアントIDが必ず一意であるようにするため、含む側のサーバー、アプリケーション、コンポーネント(WebアプリケーションまたはEJB)の名前をクライアントIDの前に付けます。
注意: クライアントIDの選択時は注意する必要があります。既存のクライアント・インスタンスと同じクライアントIDを使用してクライアント・インスタンスを作成する場合、2つのクライアント・インスタンスが同じインスタンスとして処理されます。例外がスローされ重複していることをアラートします。 |
次の例に、クライアントIDを指定するこのメソッドを示します。次の示すように、すべての処理が完了したら、クライアント・インスタンスを閉じることをお薦めします。
この例は、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』のWebサービス・クライアントのベスト・プラクティスの例の引用です。
例6-2 ポート初期化時のクライアントIDの指定例
import javax.servlet.*; import javax.xml.ws.*; import weblogic.jws.jaxws.client.ClientIdentityFeature; . . . public class BestPracticeAsyncClient extends GenericServlet { ... private BackendServiceService _service; ... // Client ID ClientIdentityFeature clientIdFeature = new ClientIdentityFeature("MyBackendServiceAsyncClient"); features.add(clientIdFeature); ... _features = features.toArray(new WebServiceFeature[features.size()]); ... BackendService port = _service.getBackendServicePort(_features); ... ((java.io.Closeable)_port).close(); } }
注意: この項での説明に従って、クライアントIDが一意であるようにするため、サーバー生成のバージョンが長く読みにくくなる場合があります。クライアントIDが読みづらい形式で表示されるように保証するため、「ポート初期化時のクライアントIDの定義」の説明に従ってポート初期化時にクライアントIDを定義することをお薦めします。 |
サーバーが自動生成するクライアントIDでは次の形式を使用します。
applicationname[_applicationversion]:componentname:uniqueID
ここで:
applicationname
- クライアントをホストするアプリケーションの名前。
applicationversion
- アプリケーションのバージョン。同じアプリケーションの複数のバーションを同時に実行する場合にのみ使用します。
componentnam
- クライアントをホストするコンポーネント(WebアプリケーションまたはEJB)の名前。
uniqueID
- クライアント・インスタンスが作成される場合に使用可能な情報に基づいて算出されます。uniqueID
は次のいずれか(使用可能な方)を選択することで作成されます。
Webサービス参照名。@WebServiceRef
アノテーションにより定義されます。
[portNamespaceURI:portLocalName][:][endpointAddress]
- ポート名、エンドポイント・アドレスまたは両方(コロンで区切ります)。
ポートクラスの単純な名前。
また、次の情報(可能な場合)は、次に示す順序でコロン(:)で区切り、uniqueID
に連結することができます。
WSDLの場所(マイナス記号 ?wsdl
)
クライアント・インスタンスの作成に使用する機能。機能のクラス名で表し、ダッシュ(-)で区切ります。
たとえば、Webサービス・クライアントに関連付けられている次の情報を使用してWebサービス・クライアントをデプロイするとします。
アプリケーション名: example
コンポーネント: BestPracticeClient
と呼ばれるWebアプリケーション
ポート名: http://example/BackendServicePort
ポート・クラス: BackendService
WSDL: jar:file:/E:/p4/dev/src1034/wls/modules/wsee/test/server/build/output/example/BackendService.war!/WEB-INF/BackendServiceService.wsdl
サーバー生成クライアントIDは次のようになります。
example:BestPracticeClient:http://example/:BackendServicePort:jar:file:/E:/p4/dev/src1034/wls/modules/wsee/test/server/build/output/example/BackendService.war!/WEB-INF/BackendServiceService.wsdl:AsyncClientTransportFeature()-ClientIdentityFeature
コードを実行するたびに、同一の包含階層内にあることを前提として、同一のクライアントIDが生成されます。これにより、サーバー仮想マシンのインスタンス全体で使用できる安定したクライアントIDを提供し、サーバーの再起動後でも非同期レスポンスをクライアントに配信できます。
注意: クライアント・コードの複数の場所から特定のクライアントIDを使用できますが、クライアントIDの他の場所で使用されている方法と同じ方法(同じ機能、サービスなど)でクライアントIDを使用するポート/ディスパッチ・インスタンスの初期化時に注意する必要があります。クライアント・インスタンス(ポートまたはディスパッチ)の初期化における推奨アプローチのベスト・プラクティスは、『Oracle WebLogic Server JAX-WS Webサービス・スタート・ガイド』のWebサービス・クライアント開発のロードマップに関する項を参照してください。 |
次の例に、サーバー生成のクライアントIDにアクセスする方法を示します。この例は、『Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング』のWebサービス・クライアントのベスト・プラクティスの例の引用です。
例6-3 サーバー生成クライアントIDへのアクセス
... // Create a port without explicitly defining the client ID to view the client ID that is // generated automatically. ClientIdentityFeature dummyClientIdFeature = new ClientIdentityFeature(null); BackendService dummyPort = _service.getBackendServicePort(dummyClientIdFeature); System.out.println("Generated Client Identity is: " + dummyClientIdFeature.getClientId()); // Best Practice: Explicitly close client instances when processing is complete. // If not closed, the port will be closed automatically when it goes out of scope. // Note, this client ID will remain registered and visible until our // container (Web application) is undeployed. ((java.io.Closeable)dummyPort).close();
クライアントIDを使用して最初のクライアント・インスタンス(ポートまたはディスパッチ・インスタンス)が作成されるときに、WebサービスのランタイムでクライアントIDが登録されます。また、クライアント・インスタンスに関連付けられている非同期レスポンスのエンドポイントも登録されているクライアントIDで追跡されます。
クライアントIDは次のいずれかが発生するまで登録が維持されます。
表6-2
に示すように、クライアントIDは、ClientIdentityFeature
でdispose()メソッドを使用して明示的に公開します。
クライアントIDを使用するクライアント・インスタンスのコンテナが無効化されます(ホストWebアプリケーションまたはEJBが無効化される場合など)。
プロキシ・サーバーを使用すると、クライアント・アプリケーションから、呼び出されるWebサービスをホストするアプリケーション・サーバー(WebLogic、非WebLogicいずれでも)へのリクエストをプロキシできます。通常、プロキシ・サーバーは、アプリケーション・サーバーがファイアウォールの内側にある場合に使用します。Javaシステム・プロパティを使用してクライアント・アプリケーションにプロキシ・サーバーを指定できます。クライアント・アプリケーションでプロキシ・サーバーを指定する方法には、WebLogic ClientProxyFeature
APIでプログラム的に行う方法と、システム・プロパティを使用する方法の2つがあります。
weblogic.wsee.jaxws.proxy.ClientProxyFeature
APIを使用してWebサービスの呼出しをプロキシするプロキシ・サーバーの詳細を、Javaクライアント・アプリケーション自体にプログラムで指定できます。ClientProxyFeature
APIの詳細は、Oracle WebLogic Server APIリファレンスを参照してください。
JVMレベルに定義されている設定は、「システム・プロパティを使用したプロキシ・サーバーの指定」
に記載されているように、ClientProxyFeatureで定義されたプロキシ・サーバー設定によってオーバーライドされます。
注意: ClientProxyFeature は、WebLogic HTTP over SSLのポートを構成します。WebLogic ServerにはSSLを構成することをお薦めします。詳細は、『Oracle WebLogic Serverの保護』のSSLの構成に関する項を参照してください。 |
次の例で示すように、ClientProxyFeature
を使用してプロキシ・サーバー情報を構成し、Webサービス・ポートの作成時に引数としてClientProxyFeatureを渡すことができます。
例6-4 ポート作成時に引数としてClientProxyFeatureを渡す
package examples.webservices.simple_client; import weblogic.wsee.jaxws.proxy public class Main { public static void main(String[] args) { ComplexService test = new ComplexService(); ClientProxyFeature cpf = new ClientProxyFeature(); cpf.setProxyHost("localhost"); cpf.setProxyPort(8888); cpf.setProxyUserName("proxyu"); cpf.setProxyPassword("proxyp"); ComplexPortType port = test.getComplexPortTypePort(cpf); BasicStruct in = new BasicStruct(); in.setIntValue(999); in.setStringValue("Hello Struct"); BasicStruct result = port.echoComplexType(in); System.out.println("echoComplexType called. Result: " + result.getIntValue() + ", " + result.getStringValue()); } }
または、次の例に示すように、ポートが作成された後にプロキシ・サーバー情報を構成することも可能です。この場合は、attachsPort()
メソッドを実行し、既存のポートにClientProxyFeature
をアタッチします。
例6-5 ポート作成後のClientProxyFeatureの構成
package examples.webservices.simple_client; import weblogic.wsee.jaxws.proxy public class Main { public static void main(String[] args) { ComplexService test = new ComplexService(); ComplexPortType port = test.getComplexPortTypePort(); ClientProxyFeature cpf = new ClientProxyFeature(); cpf.setProxyHost("localhost"); cpf.setProxyPort(8888); cpf.setProxyUserName("proxyu"); cpf.setProxyPassword("proxyp"); cpf.attachsPort(port); BasicStruct in = new BasicStruct(); in.setIntValue(999); in.setStringValue("Hello Struct"); BasicStruct result = port.echoComplexType(in); System.out.println("echoComplexType called. Result: " + result.getIntValue() + ", " + result.getStringValue()); } }
ClientProxyFeature
を構成し、クライアント・プロキシ設定を無効化するポートにアタッチしたら、プロキシ・ポートを負の値に設定します。例:
プロキシ・サーバーの指定にシステム・プロパティを使用する場合は、クライアント・アプリケーションの記述は標準的な方式で行い、クライアント・アプリケーションの実行時に以下のシステム・プロパティを指定します。
次の表に、Javaシステム・プロパティをまとめます。
注意: その場合は、proxySetのシステム・プロパティを設定することはできません。proxySetのシステム・プロパティが(proxySet=false)に設定されている場合、プロキシ・プロパティは無視され、プロキシは使用できません。 |
表6-3 Javaシステム・プロパティを使用したプロキシ・サーバーの指定
プロパティ | 説明 |
---|---|
http.proxyHost=proxyHostまたはhttps.proxyHost=proxyHost |
プロキシ・サーバー が動作しているホスト・コンピュータ名。HTTP over SSLに対してhttps.proxyHostを使用します。 |
http.proxyPort=proxyPortまたはhttps.proxy.Port=proxyPort |
プロキシ・サーバーがリスニングしているポート。HTTP over SSLに対してhttps.proxyPortを使用します。 |
http.nonProxyHosts=hostname | hostname | ... |
プロキシをバイパスし、直接アクセスするホストのリスト。各ホスト名を「|」文字で区切ります。このプロパティはHTTPおよびHTTPSの両方に適用されます。 |
以下のAntビルド・スクリプトの抜粋では、clients.InvokeMyService
というクライアント・アプリケーションを呼び出す場合のJavaシステム・プロパティの設定例を示します。
<target name="run-client"> <java fork="true" classname="clients.InvokeMyService" failonerror="true"> <classpath refid="client.class.path"/> <arg line="${http-endpoint}"/> <jvmarg line= "-Dhttp.proxyHost=${proxy-host} -Dhttp.proxyPort=${proxy-port} -Dhttp.nonProxyHosts=${mydomain}" /> </java> </target>
WebLogic Serverでは本番再デプロイメントをサポートしています。つまり、更新後の新しいバージョンのWebLogic Webサービスを同じWebサービスの古いバージョンと並行してデプロイできます。
WebLogic Serverでは、新しいクライアントのリクエストのみが新しいバージョンに転送されるように、クライアント接続が自動的に管理されます。再デプロイメント時にすでにWebサービスに接続していたクライアントは、作業が完了するまで古いバージョンのサービスを使用し続け、それらの作業が完了した時点で、WebLogic Serverが古いWebサービスを自動的にリタイアします。
Webサービスの新しいバージョンで以下のWebサービス・アーティファクトが変更されていなければ、その新しいバージョンで古いクライアント・アプリケーションを引続き使用できます。
Webサービスを記述するWSDL
Webサービスに添付されたWS-Policyファイル
上記のアーティファクトのいずれかが変更されている場合、clientgen
Antタスクを再び実行して、クライアント・アプリケーションで使用されるJAX-WSスタブを再生成する必要があります。
たとえば、Webサービスの新しいバージョンで操作のシグネチャを変更すると、Webサービスの新しいバージョンを記述するWSDLファイルも変更されます。この場合、JAX-WSスタブを再生成する必要があります。ただし、単に操作の実装のみを変更し、操作のパブリック・コントラクトは変更しない場合、既存のクライアント・アプリケーションを引続き使用できます。
Webサービスおよびクライアントを同一の管理対象サーバーにデプロイし、次のいずれかが該当する場合:
Webサービス・クライアントが@WebServiceRef
アノテーションを使用しますが、wsdlLocation
要素の値を指定しません。
Webサービス・クライアントが@WebServiceRef
アノテーションのwsdlLocation
要素を使用して、Webサービス・アプリケーションでパッケージ化されるWSDL(たとえば、@WebServiceRef(wsdlLocation="myService.wsdl")
)とは反対に、ライブのWSDLの場所(たとえば、@WebServiceRef(wsdlLocation="http://xyz.com/myService?WSDL")
)を参照します。
続いて、Webサービスとクライアントがデプロイされている管理対象サーバーを再起動するとき、アプリケーションは最初管理モードでデプロイされ、その後本番モードに遷移してHTTPリクエストを受け入れるため、デプロイメントの順序に関係なくWebサービス・クライアントは再デプロイに失敗する場合があります。この場合、サーバーが再起動したらアプリケーションを手動で再起動する必要があります。
Webサービスおよびクライアントを同一の管理対象サーバーにデプロイする場合、この状況を回避するために、Webサービス・アプリケーションの一部としてWSDLをパッケージ化し、@WebServiceRef
アノテーションからパッケージ化されたバージョンを参照することをお薦めします。