ヘッダーをスキップ
Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービス・スタート・ガイド
12c リリース1(12.1.1)
B65942-01
  目次へ移動
目次

前
 
次
 

6 WebLogic Webサービス・クライアントの開発

この章では、Java API for XML-based Web services(JAX-WS)を使用するWebLogic Webサービスを呼び出すクライアントの開発方法について説明します。

この章では、以下のトピックについて説明します。

WebLogic Webサービス・クライアント開発の概要

Webサービスの起動とは、Webサービスを使用するためにクライアント・アプリケーションが実行する操作のことです。

クライアント・アプリケーションには以下の2種類があります。

(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 Examples->Examples->API->Web Services」ノードを展開してください。

詳細については、以下を参照してください。


注意:

この章では、clientgenまたはwsdlc Antタスクで生成されるクライアント側のアーチファクトを使用してWebサービスを呼び出す場合、CLASSPATHのWebLogic Serverクラスの全体のセットを持っていることが想定されます。


Java SEクライアントからのWebサービスの呼出し


注意:

(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

環境を設定します。

コマンド・ウィンドウを開いて、ドメイン・ディレクトリのbinサブディレクトリにあるsetDomainEnv.cmd (Windows)またはsetDomainEnv.sh (UNIX)コマンドを実行します。WebLogic Serverドメインのデフォルトの場所は、MW_HOME/user_projects/domains/domainNameMW_HOMEはOracle製品の最上位のインストール・ディレクトリ、domainNameはドメインの名前。

2

build.xmlファイルを更新して、Webサービスの呼出しに必要なクライアント側アーティファクトを生成するclientgen Antタスクが実行されるようします。

「クライアントのアーティファクトを生成するためのclientgen Antタスクの使用」を参照してください。

3

Webサービスに関する情報(その操作のシグネチャ、ポートの名前など)を取得します。

「Webサービスに関する情報の取得」を参照してください。

4

Webサービス操作を呼び出すためのコードを含むクライアント・アプリケーションのJavaコードを記述します。

「Webサービスを呼び出すJavaクライアント・アプリケーション・コードの記述」を参照してください。

5

基本のAntビルド・ファイルbuild.xmlを作成します。

「基本的なAnt build.xmlファイルの作成」を参照してください。

6

Javaクライアント・アプリケーションをコンパイルし、実行します。

「クライアント・アプリケーションのコンパイルと実行」を参照してください。


クライアントのアーティファクトを生成するためのclientgen Antタスクの使用

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タスクによって生成されたファイルやアーティファクトを確認します。

Webサービスに関する情報の取得

操作を呼び出す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サービスにbuysellの2つの操作があることを示しています(わかりやすくするため、WSDLの関連部分のみを記載しています)。

  <binding name="TraderServiceSoapBinding" ...>
    ...
    <operation name="sell">
    ...
    </operation>
    <operation name="buy">
    </operation>
  </binding>

Webサービスを呼び出すJavaクライアント・アプリケーション・コードの記述

次のサンプル・コードでは、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.xmlrunターゲットを追加します。次に例を示します。

<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クライアントのサンプルAntビルド・ファイル

次の例では、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サービスの呼出し

WebLogic Webサービス内からのWebサービスの呼出しは、Java SEクライアントからのWebサービスの呼出しに関する項で説明したJava SEアプリケーションからのWebサービスの呼出しに似ていますが、次の点が異なります。

この項では、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ファイル」を参照してください。

クライアントWebサービスを実装するJWSファイルに加える必要のある変更は次のとおりです。JWSファイルの完全なサンプルについては、「Webサービスを呼び出すサンプルJWSファイル」を参照してください。

Webサービス・クライアントのサンプルbuild.xmlファイル

次のサンプル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>

Webサービスを呼び出すサンプルJWSファイル

次に示すサンプル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サービスで使用されるユーザー定義データ型をインポートします。このサンプルでは、ComplexServiceBasicStruct 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();
    
  • ComplexServiceechoComplexType操作を、直前にインスタンス化したポートを使用して呼び出します。

    BasicStruct result = port.echoComplexType(input);
    

Webサービス・クライアントの構成

デフォルトでは、Webサービス・クライアントではサーバーに対して定義されているWebサービス構成を使用します。次のメソッドのいずれかを使用してWebサービス・クライアントが使用する構成設定をオーバーライドできます。

@WebServiceRefアノテーションを使用したWebサービス参照の定義

@WebServiceRefアノテーションを使用すると、Webサービスへの参照を定義し、クライアント・インスタンスにWebサービスの構成をアタッチできます。

たとえば、次のコードの引用では、@WebServiceRefを使用して、クライアントのWebサービス・インスタンスにMyReliableEchoServiceの構成をアタッチします。後で作成および初期化されるポートは、Webアプリケーションのweblogic.xmlMyReliableEchoServiceサービス参照で定義されているプロパティを使用します。

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を生成できます。


注意:

省略可能ですが、クライアントIDを明示的に定義することをお薦めします。


weblogic.wsee.jaxws.persistence.ClientIdentityFeatureクライアント機能を使用すると、Webサービス・クライアントがWebサービスのクライアントIDを設定およびアクセスできます。次の表では、ClientIdentityFeatureメソッドをまとめます。

表6-2 クライアントIDの設定およびアクセスのためのClientIdentityFeatureメソッド

メソッド 説明

getClientID()

Webサービス・ポートで現在定義されているクライアントIDを取得します。

setClientID()

Webサービス・ポートのクライアントIDを設定します。

また、ClientIdentityFeatureオブジェクトをインスタンス化する場合は、クライアントIDを引数として渡すことにより、クライアントIDを設定できます。例:

ClientIdentityFeature clientIDFeature = new 
 ClientIdentityFeature("MyBackendServiceAsyncClient"); 

dispose()

クライアントIDを破棄します。

クライアントIDを明示的に破棄される場合、クライアントIDを使用するクライアント・インスタンスのコンテナが無効化されるとき(ホストWebアプリケーションまたはEJBが無効化される場合など)に実行されます。詳細は、クライアント・アイデンティティのライフサイクルに関する項を参照してください。


次の項は、クライアントIDを管理するためのメソッドを説明します。

ポート初期化時のクライアント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を定義することをお薦めします。


サーバーが自動生成するクライアント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は、ClientIdentityFeaturedispose()メソッドを使用して明示的に公開します。

  • クライアントIDを使用するクライアント・インスタンスのコンテナが無効化されます(ホストWebアプリケーションまたはEJBが無効化される場合など)。

Webサービス呼出し時のプロキシ・サーバーの使用

プロキシ・サーバーを使用すると、クライアント・アプリケーションから、呼び出されるWebサービスをホストするアプリケーション・サーバー(WebLogic、非WebLogicいずれでも)へのリクエストをプロキシできます。通常、プロキシ・サーバーは、アプリケーション・サーバーがファイアウォールの内側にある場合に使用します。Javaシステム・プロパティを使用してクライアント・アプリケーションにプロキシ・サーバーを指定できます。クライアント・アプリケーションでプロキシ・サーバーを指定する方法には、WebLogic ClientProxyFeature APIでプログラム的に行う方法と、システム・プロパティを使用する方法の2つがあります。

ClientProxyFeature APIを使用したプロキシ・サーバーの指定

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を構成し、クライアント・プロキシ設定を無効化するポートにアタッチしたら、プロキシ・ポートを負の値に設定します。例:

例6-6 クライアント・プロキシ設定の無効化

. . .
    ClientProxyFeature cpf = new ClientProxyFeature();
    cpf.setProxyPort(-1);\
    cpf.attachsPort(port);
. . .

システム・プロパティを使用したプロキシ・サーバーの指定

プロキシ・サーバーの指定にシステム・プロパティを使用する場合は、クライアント・アプリケーションの記述は標準的な方式で行い、クライアント・アプリケーションの実行時に以下のシステム・プロパティを指定します。

次の表に、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>

Webサービスを再デプロイする際にクライアント側で考慮すべき事項

WebLogic Serverでは本番再デプロイメントをサポートしています。つまり、更新後の新しいバージョンのWebLogic Webサービスを同じWebサービスの古いバージョンと並行してデプロイできます。

WebLogic Serverでは、新しいクライアントのリクエストのみが新しいバージョンに転送されるように、クライアント接続が自動的に管理されます。再デプロイメント時にすでにWebサービスに接続していたクライアントは、作業が完了するまで古いバージョンのサービスを使用し続け、作業が完了した時点で古いWebサービスが自動的に廃止されます。

Webサービスの新しいバージョンで以下のWebサービス・アーティファクトが変更されていなければ、その新しいバージョンで古いクライアント・アプリケーションを引続き使用できます。

上記のアーティファクトのいずれかが変更されている場合、clientgen Antタスクを再び実行して、クライアント・アプリケーションで使用されるJAX-WSスタブを再生成する必要があります。

たとえば、Webサービスの新しいバージョンで操作のシグネチャを変更すると、Webサービスの新しいバージョンを記述するWSDLファイルも変更されます。この場合、JAX-WSスタブを再生成する必要があります。ただし、単に操作の実装のみを変更し、操作のパブリック・コントラクトは変更しない場合、既存のクライアント・アプリケーションを引続き使用できます。

Webサービスおよびクライアントを同一の管理対象サーバーにデプロイする場合のクライアントに関する考慮事項

Webサービスおよびクライアントを同一の管理対象サーバーにデプロイし、次のいずれかが該当する場合:

続いて、Webサービスとクライアントがデプロイされている管理対象サーバーを再起動するとき、アプリケーションは最初管理モードでデプロイされ、その後本番モードに遷移してHTTPリクエストを受け入れるため、デプロイメントの順序に関係なくWebサービス・クライアントは再デプロイに失敗する場合があります。この場合、サーバーが再起動したらアプリケーションを手動で再起動する必要があります。

Webサービスおよびクライアントを同一の管理対象サーバーにデプロイする場合、この状況を回避するために、Webサービス・アプリケーションの一部としてWSDLをパッケージ化し、@WebServiceRefアノテーションからパッケージ化されたバージョンを参照することをお薦めします。