Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの開発 12c (12.2.1.1.0) E77380-02 |
|
前 |
次 |
この章の内容は次のとおりです:
Webサービス・リクエストの処理中にエラーが発生した場合、クライアント、すなわちリクエストの送信者にそのエラーの内容を通知する必要があります。クライアントは、各種言語を使用して様々なプラットフォーム上に作成できるため、エラーを通知するには、プラットフォームに依存しない標準のメカニズムが必要です。
SOAP仕様(http://www.w3.org/TR/soap/
で入手可能)では、SOAPフォルトを使用して、SOAPメッセージにエラーを記述するためのプラットフォームに依存しない標準の方法を定義しています。一般に、SOAPフォルトはアプリケーション例外に類似しています。SOAPフォルトは、ビジネス・ロジック・エラーや予期せぬ状況を報告するために受信側によって生成されます。
JAX-WSでは、Java WebサービスによってスローされるJava例外(java.lang.Exception
)がSOAPフォルトにマップされ、フォルトの理由を通知するためにクライアントに返されます。SOAPフォルトのタイプは、次のいずれかになります。
モデル化: Webサービスのデプロイ時に、Javaコードのビジネス・ロジックから明示的にスローされ、WSDLファイルのwsdl:fault
定義にマップされる例外にマップされます。この場合、SOAPフォルトは事前に定義されています。
非モデル化: WSDLにビジネス・ロジック・フォルトが定義されていない場合に、実行時に生成される例外(java.lang.RuntimeException
など)にマップされます。この場合、Java例外は汎用的なSOAPフォルト例外であるjavax.xml.ws.soap.SOAPFaultException
として表されます。
フォルトは、リクエスト/レスポンス・メッセージングが使用中の場合にのみ送信者に返されます。Webサービス操作が一方向として構成されている場合、SOAPフォルトは送信者には返されませんが、後続の処理のために格納されます。
図19-1に示すように、JAX-WSはSOAPプロトコル・バインディングでSOAPフォルト処理を行います。SOAPバインディングは、例外をSOAPフォルト・メッセージにマップします。
SOAPメッセージでエラーおよびステータス情報を送信するには、SOAP <Fault>
要素を使用します。<Fault>
要素は本体要素の子要素です。SOAPメッセージの本体には<Fault>
要素を1つだけ含めることができます。
次の項では、SOAP 1.2および1.1のSOAP <Fault>
要素のコンテンツを定義します。
SOAP 1.2の <Fault>
要素には、表19-1に定義されているサブ要素が含まれます。
表19-1 SOAP 1.2 <Fault>要素のサブ要素
サブ要素 | 説明 | 必須/省略可能 |
---|---|---|
|
フォルト・エラー・コードに関する情報。
これらのサブ要素は次のように定義されています。 |
必須 |
|
フォルトに関する詳細情報を示すコード値。SOAP仕様で事前に定義されている一連のコード値は次のとおりです。
|
必須 |
|
フォルトに関する詳細情報を示すサブコード値。このサブ要素は、再帰的構造をとることができます。 |
省略可能 |
|
フォルトに関する判読可能な記述。
|
必須 |
|
フォルトを発生させたアクター(SOAPノード)に関する情報。 |
省略可能 |
|
フォルトが発生したときにアクターが実行していたロール。 |
省略可能 |
|
アプリケーション固有の情報(スローされた例外など)。 |
省略可能 |
次の例では、SOAP 1.2のフォルト・メッセージを示します。
例19-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>
要素には、表19-2に定義されているサブ要素が含まれます。
表19-2 SOAP 1.1 <Fault>要素のサブ要素
サブ要素 | 説明 |
---|---|
|
フォルトに関する詳細情報を示す標準コード。SOAP仕様で事前に定義されている一連のコード値は次のとおりです。この一連のフォルト・コード値は、アプリケーションで拡張できます。 事前定義済のフォルト・コード値は次のとおりです。
|
|
フォルトに関する判読可能な記述。 |
|
フォルトを発生させたアクター(SOAPノード)に関連付けられているURI。RPCスタイルのメッセージングでは、アクターはWebサービスのURIです。 |
|
アプリケーション固有の情報(スローされた例外など)。この要素は、XML構造またはプレーン・テキストにすることができます。 |
次の例では、SOAP 1.1のフォルト・メッセージを示します。
例19-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サービス内からスローする必要があります。
例19-3では、Webサービスからスローされるカスタム例外の簡単な例を示します。この例外の名前はMissingName
で、入力引数が空の場合にスローされます。
例19-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 + "'"; } }
例19-4に、例外のクラスMissingName.java
を示します。
例19-4 カスタム例外クラス(MissingName)
package examples; import java.lang.Exception; public class MissingName extends Exception { public MissingName() { super("Your name is required."); } }
JAX-WSのJava-to-WSDLマッピングにより、java.lang.Exception
のサブクラスがwsdl:fault
メッセージにバインドされます。例19-4は、例19-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
句から導出されています(例19-3を参照)。
public String sayHelloWorld(String message) throws MissingName { ... }
フォルト・メッセージは、<binding>
要素のsayHelloWorld
操作にもマップされます。
<fault name="MissingName"> <soap:fault name="MissingName" use="literal" /> </fault>
例19-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>
例19-6は、MissingName
Java例外がスローされた場合に、生成されたSOAPメッセージでSOAPフォルトが通知される仕組みを示しています。
例19-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.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>
clientgen
を使用して、マップされたフォルトを含むWSDLファイルからWebサービス・クライアントを生成すると、必要な例外クラス(マップされた例外、フォルトBean、サービス実装クラス、クライアント実装クラスなど)が自動的に生成されますが、それらの例外クラスは変更する必要があります。次の項では、その手順について説明します。
clientgenの詳細は、『Oracle WebLogic Server WebLogic Webサービス・リファレンス』の clientgenに関する項を参照してください。
生成されたJava例外クラスの例を例19-7に示します。@WebFault
アノテーションは、このクラスをマップされた例外として指定しています。
例19-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クラスの例を例19-8に示します。このクラスには、フォルト・メッセージのgetterとsetterが定義されています。
例19-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; } }
生成されたクライアント側サービス実装クラスの例を例19-9に示します。
例19-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サービスの呼出しに関する項を参照してください。
例19-10に、クライアント実装クラスの例を示します。
例19-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
として表されます。
次の例では、モデル化されていないフォルトにマップされた例外を示します。
例19-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
メッセージが次のようにログ・ファイルに返されます。
例19-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メッセージの追加処理を実行できるようになります。詳細は、SOAPメッセージ・ハンドラの作成と使用を参照してください。
注意:
com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace
プロパティは、JDK 6.0の拡張としてサポートされています。このAPIはJDK 6.0キットの一部としては提供されないため、変更される可能性があります。
デフォルトでは、スタック・トレース全体(ネスト例外を含む)が、SOAPフォルト・メッセージの詳細に含まれます。たとえば、次の例は、スタック・トレースが含まれるSOAPフォルト・メッセージを示しています。
Java起動プロパティcom.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace
をfalse
に設定することで、スタック・トレースがSOAPフォルト・メッセージに含まれないようにすることができます。
スタック・トレースを無効にするには:
例19-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.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>
Webサービスで明示的にスローされるカスタム例外、およびビジネス・ロジックでキャッチされない例外のマッピングに使用されるSOAPFaultExceptions
に加えて、この他に2つの例外があります。これらの例外は、Webサービス・クライアントに通知される可能性があるため、確認しておく必要があります。
表19-3 その他の例外
例外 | 説明 |
---|---|
|
すべてのJAX-WS APIランタイム例外の基本例外。JAX-WS Javaクラス( |
|
クライアントが非同期呼出しからレスポンスを取得する際に、JAX-WS非同期呼出しで使用されます。 |