Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング 11g リリース1(10.3.6) B61633-04 |
|
![]() 前 |
![]() 次 |
この章では、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/" 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>
例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>
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/") 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/") @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
メッセージが次のようにログ・ファイルに返されます。
SOAPメッセージ・ハンドラを使用して、SOAPフォルトの処理プロセスをカスタマイズできます。SOAPメッセージ・ハンドラは、Webサービスのリクエストとレスポンスの両方でSOAPメッセージをインターセプトするメカニズムです。SOAPメッセージ・ハンドラを作成すると、WebサービスおよびクライアントがSOAPメッセージの追加処理を実行できるようになります。詳細は、第17章「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.disableCaptureStackTrace
をfalse
に設定することで、スタック・トレースがSOAPフォルト・メッセージに含まれないようにすることができます。
スタック・トレースを無効にするには:
WL_HOME
user_projects/domains
domainName
/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サービス・クライアントに通知される可能性があるため、確認しておく必要があります。