ヘッダーをスキップ
Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング
12cリリース1(12.1.1)
B65943-02
  目次へ移動
目次

前
 
次
 

16 SOAPフォルトを使用した例外処理

この章では、Java API for XML Web Services (JAX-WS)を使用したWebLogic Webサービスで、メッセージの処理中に発生する例外をSimple Object Access Protocol (SOAP)フォルトを使用して処理する方法について説明します。

この章の内容は以下のとおりです。

SOAPフォルトを使用した例外処理の概要

Webサービス・リクエストの処理中にエラーが発生した場合、クライアント、すなわちリクエストの送信者にそのエラーの内容を通知する必要があります。クライアントは、各種言語を使用して様々なプラットフォーム上に作成できるため、エラーを通知するには、プラットフォームに依存しない標準のメカニズムが必要です。

SOAP仕様(http://www.w3.org/TR/soap/で入手可能)では、SOAPフォルトを使用して、SOAPメッセージにエラーを記述するためのプラットフォームに依存しない標準の方法を定義しています。一般に、SOAPフォルトはアプリケーション例外に類似しています。SOAPフォルトは、ビジネス・ロジック・エラーや予期せぬ状況を報告するために受信側によって生成されます。

JAX-WSでは、Java WebサービスによってスローされるJava例外(java.lang.Exception)がSOAPフォルトにマップされ、フォルトの理由を通知するためにクライアントに返されます。SOAPフォルトのタイプは、次のいずれかになります。

フォルトは、リクエスト/レスポンス・メッセージングが使用中の場合にのみ送信者に返されます。Webサービス操作が一方向として構成されている場合、SOAPフォルトは送信者には返されませんが、後続の処理のために格納されます。

図16-1に示すように、JAX-WSはSOAPプロトコル・バインディングでSOAPフォルト処理を行います。SOAPバインディングは、例外をSOAPフォルト・メッセージにマップします。

図16-1 SOAPフォルト処理の仕組み

図16-1の説明が続きます
「図16-1 SOAPフォルト処理の仕組み」の説明

SOAPフォルト要素のコンテンツ

SOAPメッセージでエラーおよびステータス情報を送信するには、SOAP <Fault>要素を使用します。<Fault>要素は本体要素の子要素です。SOAPメッセージの本体には<Fault>要素を1つだけ含めることができます。

次の項では、SOAP 1.2および1.1のSOAP <Fault>要素のコンテンツを定義します。

SOAP 1.2 <Fault>要素のコンテンツ

SOAP 1.2の<Fault>要素には、表16-1に定義されているサブ要素が含まれます。

表16-1 SOAP 1.2 <Fault>要素のサブ要素

サブ要素 説明 必須/省略可能

env:Code

フォルト・エラー・コードに関する情報。env:Code要素は次の2つのサブ要素で構成されます。

  • env:Value

  • env: Subcode

これらのサブ要素は次のように定義されています。

必須

env:Value

フォルトに関する詳細情報を示すコード値。SOAP仕様で事前に定義されている一連のコード値は次のとおりです。

  • VersionMismatch: SOAPエンベロープ要素に無効な名前空間が定義されています。SOAPエンベロープは、http://schemas.xmlsoap.org/soap/envelopeの名前空間に準拠する必要があります。

  • MustUnderstand: SOAPヘッダー・エントリが処理側で認識できません。

  • Sender: メッセージのフォーマットが正しくないか、情報が欠落しています。

  • Receiver: サーバーの問題によりメッセージを処理できません。

  • DataEncodingUnknown: 受信したメッセージには、認識できないエンコーディング・スタイルの値が使用されています。SOAPヘッダー・ブロックおよびSOAP本体の子要素に対してエンコーディング・スタイルを定義できます。このエンコーディング・スタイルはWebサービスのサーバーで認識される必要があります。

必須

env:Subcode

フォルトに関する詳細情報を示すサブコード値。このサブ要素は、再帰的構造をとることができます。

省略可能

env:Reason

フォルトに関する判読可能な記述。

<env:Reason>要素には、1つ以上の<Text>要素が含まれており、それぞれの要素にはフォルトに関する情報が異なる言語で格納されます。

必須

env:Node

フォルトを発生させたアクター(SOAPノード)に関する情報。

省略可能

env:Role

フォルトが発生したときにアクターが実行していたロール。

省略可能

env:Detail

アプリケーション固有の情報(スローされた例外など)。

省略可能


次の例では、SOAP 1.2のフォルト・メッセージを示します。

例16-1 SOAP 1.2のフォルト・メッセージの例

<?xml version="1.0"?>
<env:Envelope xmlns:env=http://www.w3.org/2003/05/soap-envelope>
   <env:Body>
      <env:Fault>
         <env:Code>
            <env:Value>env:Sender</env:Value>
            <env:Subcode>
               <env:Value>rpc:BadArguments</env:Value>
            </env:Subcode>
         </env:Code>
         <env:Reason>
            <env:Text xml:lang=en-US>Processing error<env:Text>
         </env:Reason>
         <env:Detail>
            <e:myFaultDetails 
               xmlns:e=http://travelcompany.example.org/faults>
               <e:message>Name does not match card number</e:message>
               <e:errorcode>999</e:errorcode>
            </e:myFaultDetails>
         </env:Detail>
      </env:Fault>
   </env:Body>
</env:Envelope>

SOAP 1.1 <Fault>要素のコンテンツ

SOAP 1.1の<Fault>要素には、表16-2に定義されているサブ要素が含まれます。

表16-2 SOAP 1.1 <Fault>要素のサブ要素

サブ要素 説明

faultcode

フォルトに関する詳細情報を示す標準コード。SOAP仕様で事前に定義されている一連のコード値は次のとおりです。この一連のフォルト・コード値は、アプリケーションで拡張できます。

事前定義済のフォルト・コード値は次のとおりです。

  • VersionMismatch: SOAPエンベロープ要素に無効な名前空間が定義されています。SOAPエンベロープは、http://schemas.xmlsoap.org/soap/envelopeの名前空間に準拠する必要があります。

  • MustUnderstand: SOAPヘッダー・エントリが処理側で認識できません。

  • Client: メッセージのフォーマットが正しくないか、情報が欠落しています。

  • Server: サーバーの問題によりメッセージを処理できません。

faultstring

フォルトに関する判読可能な記述。

faultactor

フォルトを発生させたアクター(SOAPノード)に関連付けられているURI。RPCスタイルのメッセージングでは、アクターはWebサービスのURIです。

detail

アプリケーション固有の情報(スローされた例外など)。この要素は、XML構造またはプレーン・テキストにすることができます。


次の例では、SOAP 1.1のフォルト・メッセージを示します。

例16-2 SOAP 1.1のフォルト・メッセージの例

<?xml version="1.0"?>
<soap:Envelope 
    xmlns:soap='http://schemas.xmlsoap.org/soap/envelope'>
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:VersionMismatch</faultcode>
         <faultstring, xml:lang='en">
            Message was not SOAP 1.1 compliant
         </faultstring>
         <faultactor>
            http://sample.org.ocm/jws/authnticator
         </faultactor>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

モデル化されたフォルトの使用

前述したように、モデル化されたフォルトは、Javaコードのビジネス・ロジックから明示的にスローされる例外にマップされます。この場合、その例外は、Webサービスのデプロイ時にWSDLファイルのwsdl:fault定義にマップされます。

次の項では、モデル化されたフォルトの使用に関する詳細を説明します。

カスタム例外の作成と使用

モデル化されたフォルトを使用するには、カスタムのJava例外を作成して、Webサービス内からスローする必要があります。

例16-3では、Webサービスからスローされるカスタム例外の簡単な例を示します。この例外の名前はMissingNameで、入力引数が空の場合にスローされます。

例16-3 カスタム例外を使用したWebサービス

package examples;
import javax.jws.WebService;

@WebService(name="HelloWorld", serviceName="HelloWorldService")
public class HelloWorld {
   public String sayHelloWorld(String message) throws MissingName {
        System.out.println("Say Hello World: " + message);
        if (message == null || message.isEmpty()) {
           throw new MissingName();
        }
      return "Here is the message: '" + message + "'";
      }
}

例16-4に、例外のクラスMissingName.javaを示します。

例16-4 カスタム例外クラス(MissingName)

package examples;
import java.lang.Exception;

public class MissingName extends Exception {
    public MissingName() {
        super("Your name is required.");
    }
}

モデル化されたフォルトのWSDLファイルにおけるマッピングの仕組み

JAX-WSのJava-to-WSDLマッピングにより、java.lang.Exceptionのサブクラスがwsdl:faultメッセージにバインドされます。例16-4は、例16-3のアノテーション付きのWebサービスから生成されたWSDLを示しています。*

この例の内容:

  • <message name="MissingName">要素は、MissingNameメッセージのパート、すなわちfaultと、関連付けられたデータ型tns:MissingNameを定義しています。

      <message name="MissingName">
        <part name="fault" element="tns:MissingName" /> 
      </message>
    
  • MissingName SOAPフォルトは、sayHelloWorld操作にマップされています。

        <operation name="sayHelloWorld">
          <input message="tns:sayHelloWorld" /> 
          <output message="tns:sayHelloWorldResponse" /> 
          <fault message="tns:MissingName" name="MissingName" /> 
        </operation>
    

    この例の<fault>サブ要素は、sayHelloWorld()メソッド宣言のthrows MissingName句から導出されています(例16-3を参照)。

    public String sayHelloWorld(String message) throws MissingName {
    ...
    }
    
  • フォルト・メッセージは、<binding>要素のsayHelloWorld操作にもマップされます。

    <fault name="MissingName">
      <soap:fault name="MissingName" use="literal" /> 
    </fault>
    

例16-5 モデル化された例外を使用したWSDLの例

<?xml version="1.0" encoding="UTF-8" ?> 
<definitions 
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:tns="http://examples/" 
   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
   xmlns="http://schemas.xmlsoap.org/wsdl/" 
   targetNamespace="http://examples/" 
   name="HelloWorldService">
  <types>
    <xsd:schema>
      <xsd:import namespace="http://examples/" 
     schemaLocation="http://localhost:7001/HelloWorld/HelloWorldService?xsd=1"/>
    </xsd:schema>
  </types>
  <message name="sayHelloWorld">
    <part name="parameters" element="tns:sayHelloWorld" /> 
  </message>
  <message name="sayHelloWorldResponse">
    <part name="parameters" element="tns:sayHelloWorldResponse" /> 
  </message>
  <message name="MissingName">
    <part name="fault" element="tns:MissingName" /> 
  </message>
  <portType name="HelloWorld">
    <operation name="sayHelloWorld">
      <input message="tns:sayHelloWorld" /> 
      <output message="tns:sayHelloWorldResponse" /> 
      <fault message="tns:MissingName" name="MissingName" /> 
    </operation>
  </portType>
  <binding name="HelloWorldPortBinding" type="tns:HelloWorld">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
      style="document" /> 
    <operation name="sayHelloWorld">
      <soap:operation soapAction="" /> 
      <input>
        <soap:body use="literal" /> 
      </input>
      <output>
        <soap:body use="literal" /> 
       </output>
      <fault name="MissingName">
        <soap:fault name="MissingName" use="literal" /> 
      </fault>
    </operation>
  </binding>
  <service name="HelloWorldService">
    <port name="HelloWorldPort" binding="tns:HelloWorldPortBinding">
      <soap:address 
        location="http://localhost:7001/HelloWorld/HelloWorldService" /> 
    </port>
  </service>

SOAPメッセージによるフォルト通知の仕組み

例16-6は、MissingName Java例外がスローされた場合に、生成されたSOAPメッセージでSOAPフォルトが通知される仕組みを示しています。

例16-6 MissingName例外のSOAPフォルト・メッセージの例

<?xml version = '1.0' encoding = 'UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
         <faultcode>S:Server</faultcode>
         <faultstring>Your name is required.</faultstring>
         <detail>
            <ns2:MissingName xmlns:ns2="http://examples/">
               <message>Your name is required.</message>
            </ns2:MissingName>
            <ns2:exception xmlns:ns2="http://jax-ws.dev.java.net/"
 class="examples.MissingName" note="To disable this feature, set
 com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace system 
 property to false">
               <message>Your name is required.</message>
               <ns2:stackTrace>
                  <ns2:frame class="examples.HelloWorld" file="HelloWorld.java" 
  line="14" method="sayHelloWorld"/>
  ...
               </ns2:stackTrace>
            </ns2:exception>
         </detail>
      </S:Fault>
   </S:Body>
</S:Envelope>

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

clientgenを使用して、マップされたフォルトを含むWSDLファイルからWebサービス・クライアントを生成すると、必要な例外クラス(マップされた例外、フォルトBean、サービス実装クラス、クライアント実装クラスなど)が自動的に生成されますが、それらの例外クラスは変更する必要があります。次の項では、その手順について説明します。

clientgenの詳細は、『Oracle WebLogic Server WebLogic Webサービス・リファレンス』のclientgenに関する項を参照してください。

生成されたJava例外クラスの確認

生成されたJava例外クラスの例を例16-7に示します。@WebFaultアノテーションは、このクラスをマップされた例外として指定しています。

例16-7 生成されたJava例外クラスの例

package examples.client;
 
import javax.xml.ws.WebFault;
 
@WebFault(name = "MissingName", targetNamespace = "http://examples/")
public class MissingName_Exception extends Exception {
  private MissingName faultInfo;
  public MissingName_Exception(String message, MissingName faultInfo) { ... }
  public MissingName_Exception(String message, MissingName faultInfo, 
     Throwable cause) { ... }
  public MissingName getFaultInfo() { ... }
}

生成されたJavaフォルトBeanクラスの確認

生成されたJavaフォルトBeanクラスの例を例16-8に示します。このクラスには、フォルト・メッセージのgetterとsetterが定義されています。

例16-8 生成されたJavaフォルトBeanクラスの例

package examples.client;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
 
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MissingName", propOrder = {
    "message"
})
public class MissingName {
 
    protected String message;
 
    public String getMessage() {
        return message;
    }

    public void setMessage(String value) {
        this.message = value;
    }
}

クライアント側のサービス実装の確認

生成されたクライアント側サービス実装クラスの例を例16-9に示します。

例16-9 クライアント側のサービス実装

package examples.client;
...
@WebService(name = "HelloWorld", targetNamespace = "http://examples/")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface HelloWorld {
 
    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "sayHelloWorld", 
       targetNamespace = "http://examples/", 
       className = "examples.client.SayHelloWorld")
    @ResponseWrapper(localName = "sayHelloWorldResponse", 
       targetNamespace = "http://examples/", 
       className = "examples.client.SayHelloWorldResponse")
    public String sayHelloWorld(
        @WebParam(name = "arg0", targetNamespace = "")
        String arg0)
        throws MissingName_Exception;
}

クライアント実装クラスの作成

Webサービス・メソッドを呼び出し、カスタム例外をスローするクライアント実装クラスを作成します。続いて、そのクライアントをコンパイルし、実行します。Webサービス・クライアントの作成に関する詳細は、『Oracle WebLogic Server JAX-WS Webサービス・スタート・ガイド』のWebサービスの呼出しに関する項を参照してください。

例16-10に、クライアント実装クラスの例を示します。

例16-10 クライアント実装クラス

package examples.client;
 
import javax.xml.namespace.QName;
import java.net.MalformedURLException;
import java.net.URL;
import examples.client.MissingName_Exception;
 
public class Main {
 
  public static void main(String[] args) throws MissingName_Exception {
    HelloWorldService service;
 
    try {
      service = new HelloWorldService(new URL(args[0] + "?WSDL"), 
                    new QName("http://examples/", "HelloWorldService") );
    } catch (MalformedURLException murl) { throw new RuntimeException(murl); }
      HelloWorld port = service.getHelloWorldPort();
 
      String result = null;
    try {
      result = port.sayHelloWorld("");
    } catch (MissingName_Exception e) {
      System.err.println("Error: " + e);
    }
      System.out.println( "Got result: " + result );
  }
}

モデル化されていないフォルトの使用

前述したように、モデル化されていないフォルトは、WSDLにビジネス・ロジック・フォルトが定義されていない場合は、実行時に生成される例外(java.lang.RuntimeExceptionなど)にマップされます。この場合、Java例外は汎用的なSOAPフォルト例外であるjavax.xml.ws.soap.SOAPFaultExceptionとして表されます。

次の例では、モデル化されていないフォルトにマップされた例外を示します。

例16-11 モデル化されていないフォルトを使用したWebサービスの例

package examples;
 
import javax.jws.WebService;
@WebService(name="HelloWorld", serviceName="HelloWorldService")
public class HelloWorld {
   public String sayHelloWorld(String message) throws MissingName {
        System.out.println("Say Hello World: " + message);
        if (message == null || message.isEmpty()) {
           throw new MissingName(); // Modeled fault
        } else if (message.equalsIgnoreCase("abc")) {
         throw new RuntimeException("Please enter a name."); //Unmodeled fault
        } 
 
      return "Here is the message: '" + message + "'";
   }
}

この例では、文字列「abc」がメソッドに渡されると、次のSOAPFaultExceptionメッセージおよびRuntimeExceptionメッセージが次のようにログ・ファイルに返されます。

例16-12 モデル化されていないフォルトのログ・ファイル・メッセージの例

...
run:
  [java] Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Please
enter a name.
...
Caused by: java.lang.RuntimeException: Please enter a name.\
...

例外処理プロセスのカスタマイズ

SOAPメッセージ・ハンドラを使用して、SOAPフォルトの処理プロセスをカスタマイズできます。SOAPメッセージ・ハンドラは、Webサービスのリクエストとレスポンスの両方でSOAPメッセージをインターセプトするメカニズムです。SOAPメッセージ・ハンドラを作成すると、WebサービスおよびクライアントがSOAPメッセージの追加処理を実行できるようになります。詳細は、第17章「SOAPメッセージ・ハンドラの作成と使用」を参照してください。

SOAPフォルトからのスタック・トレースの無効化


注意:

com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTraceプロパティは、JDK 6.0の拡張としてサポートされています。このAPIはJDK 6.0キットの一部としては提供されないため、変更される可能性があります。


デフォルトでは、スタック・トレース全体(ネスト例外を含む)が、SOAPフォルト・メッセージの詳細に含まれます。たとえば、次の例は、スタック・トレースが含まれるSOAPフォルト・メッセージを示しています。

例16-13 SOAPフォルト・メッセージのスタック・トレースの例

<?xml version = '1.0' encoding = 'UTF-8'?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
   <S:Body>
      <S:Fault xmlns:ns4="http://schemas.xmlsoap.org/soap/envelope/">
         <S:Code>
            <S:Value>S:Receiver</S:Value>
         </S:Code>
         <S:Reason>
            <S:Text xml:lang="en">String index out of range: 3</S:Text>
         </S:Reason>
         <S:Detail>
            <ns2:exception xmlns:ns2="http://jax-ws.dev.java.net/" 
             class="java.lang.StringIndexOutOfBoundsException" note="To disable this feature, set
             com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace system property 
             to false">
               <message>String index out of range: 3</message>
               <ns2:stackTrace>
                  <ns2:frame class="java.lang.String" file="String.java" line="1934"
                    method="substring"/>
                  <ns2:frame class="ratingservice.CreditRating" file="CreditRating.java"
                    line="21" method="processRating"/>
                  <ns2:frame class="sun.reflect.NativeMethodAccessorImpl"
                    file="NativeMethodAccessorImpl.java" line="native" method="invoke0"/>
                  <ns2:frame class="sun.reflect.NativeMethodAccessorImpl"
                    file="NativeMethodAccessorImpl.java" line="39" method="invoke"/>
                  <ns2:frame class="sun.reflect.DelegatingMethodAccessorImpl"
                    file="DelegatingMethodAccessorImpl.java" line="25" method="invoke"/>
                  <ns2:frame class="java.lang.reflect.Method" file="Method.java" line="597"
                    method="invoke"/>
                  ...
               </ns2:stackTrace>
            </ns2:exception>
         </S:Detail>
      </S:Fault>
   </S:Body>
</S:Envelope>

Java起動プロパティcom.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTracefalseに設定することで、スタック・トレースがSOAPフォルト・メッセージに含まれないようにすることができます。

スタック・トレースを無効にするには:

  1. WL_HOMEuser_projects/domainsdomainName/startWebLogic.cmdファイルで、次のエントリをみつけます。WL_HOMEは、WebLogic Serverのメイン・インストール・ディレクトリです。

    set JAVA_OPTIONS=%SAVE_JAVA_OPTIONS%
    
  2. エントリを次のように編集します。

    set JAVA_OPTIONS=-Dcom.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace=false %SAVE_JAVA_OPTIONS%
    
  3. startWebLogic.cmdファイルを保存します。

その他の例外

Webサービスで明示的にスローされるカスタム例外、およびビジネス・ロジックでキャッチされない例外のマッピングに使用されるSOAPFaultExceptionsに加えて、この他に2つの例外があります。これらの例外は、Webサービス・クライアントに通知される可能性があるため、確認しておく必要があります。

表16-3 その他の例外

例外 説明

javax.xml.ws.WebServiceException

すべてのJAX-WS APIランタイム例外の基本例外。JAX-WS Javaクラス(Service.BindingProviderDispatchなど)の呼出しに失敗した場合に使用されます。

java.util.concurrent.ExecutionException

クライアントが非同期呼出しからレスポンスを取得する際に、JAX-WS非同期呼出しで使用されます。