| Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング 11g リリース1 (10.3.6) B61633-05 |
|
![]() 前 |
![]() 次 |
この章では、Java API for XML Web Services (JAX-WS)を使用したWebLogic Webサービスで、メッセージの処理中に発生する例外をSimple Object Access Protocol (SOAP)フォルトを使用して処理する方法について説明します。
この章の内容は以下のとおりです。
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フォルトは送信者には返されませんが、後続の処理のために格納されます。
図16-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>要素には、表16-1に定義されているサブ要素が含まれます。
表16-1 SOAP 1.2 <Fault>要素のサブ要素
| サブ要素 | 説明 | 必須/省略可能 |
|---|---|---|
|
|
フォルト・エラー・コードに関する情報。
これらのサブ要素は次のように定義されています。 |
必須 |
|
|
フォルトに関する詳細情報を示すコード値。SOAP仕様で事前に定義されている一連のコード値は次のとおりです。
|
必須 |
|
|
フォルトに関する詳細情報を示すサブコード値。このサブ要素は、再帰的構造をとることができます。 |
省略可能 |
|
|
フォルトに関する判読可能な記述。
|
必須 |
|
|
フォルトを発生させたアクター(SOAPノード)に関する情報。 |
省略可能 |
|
|
フォルトが発生したときにアクターが実行していたロール。 |
省略可能 |
|
|
アプリケーション固有の情報(スローされた例外など)。 |
省略可能 |
次の例では、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>要素には、表16-2に定義されているサブ要素が含まれます。
表16-2 SOAP 1.1 <Fault>要素のサブ要素
| サブ要素 | 説明 |
|---|---|
|
|
フォルトに関する詳細情報を示す標準コード。SOAP仕様で事前に定義されている一連のコード値は次のとおりです。この一連のフォルト・コード値は、アプリケーションで拡張できます。 事前定義済のフォルト・コード値は次のとおりです。
|
|
|
フォルトに関する判読可能な記述。 |
|
|
フォルトを発生させたアクター(SOAPノード)に関連付けられているURI。RPCスタイルのメッセージングでは、アクターはWebサービスのURIです。 |
|
|
アプリケーション固有の情報(スローされた例外など)。この要素は、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を示します。
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.com/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://examples.com/"
name="HelloWorldService">
<types>
<xsd:schema>
<xsd:import namespace="http://examples.com/"
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>
例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.com/">
<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例外クラスの例を例16-7に示します。@WebFaultアノテーションは、このクラスをマップされた例外として指定しています。
例16-7 生成されたJava例外クラスの例
package examples.client;
import javax.xml.ws.WebFault;
@WebFault(name = "MissingName", targetNamespace = "http://examples.com/")
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クラスの例を例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.com/")
@XmlSeeAlso({
ObjectFactory.class
})
public interface HelloWorld {
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "sayHelloWorld",
targetNamespace = "http://examples.com/",
className = "examples.client.SayHelloWorld")
@ResponseWrapper(localName = "sayHelloWorldResponse",
targetNamespace = "http://examples.com/",
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.com/", "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メッセージが次のようにログ・ファイルに返されます。
SOAPメッセージ・ハンドラを使用して、SOAPフォルトの処理プロセスをカスタマイズできます。SOAPメッセージ・ハンドラは、Webサービスのリクエストとレスポンスの両方でSOAPメッセージをインターセプトするメカニズムです。SOAPメッセージ・ハンドラを作成すると、WebサービスおよびクライアントがSOAPメッセージの追加処理を実行できるようになります。詳細は、第17章「SOAPメッセージ・ハンドラの作成と使用」を参照してください。
|
注意:
|
デフォルトでは、スタック・トレース全体(ネスト例外を含む)が、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.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.disableCaptureStackTraceをfalseに設定することで、スタック・トレースがSOAPフォルト・メッセージに含まれないようにすることができます。
スタック・トレースを無効にするには:
WL_HOMEuser_projects/domainsdomainName/startWebLogic.cmdファイルで、次のエントリをみつけます。WL_HOMEは、WebLogic Serverのメイン・インストール・ディレクトリです。
set JAVA_OPTIONS=%SAVE_JAVA_OPTIONS%
エントリを次のように編集します。
set JAVA_OPTIONS=-Dcom.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace=false %SAVE_JAVA_OPTIONS%
startWebLogic.cmdファイルを保存します。
Webサービスで明示的にスローされるカスタム例外、およびビジネス・ロジックでキャッチされない例外のマッピングに使用されるSOAPFaultExceptionsに加えて、この他に2つの例外があります。これらの例外は、Webサービス・クライアントに通知される可能性があるため、確認しておく必要があります。