| Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング 11g リリース1(10.3.4) B61633-02 |
|
![]() 前 |
![]() 次 |
ここでは、XMLメッセージ・レベルで処理を行うWebサービス・プロバイダベース・エンドポイントおよびディスパッチ・クライアントを開発する方法を説明します。
JAXB生成のクラスを使用する方が単純で処理速度が速く、エラーになる可能性も低いですが、場合によってはXMLメッセージ・コンテンツを直接処理するために独自のビジネス・ロジックを生成する必要があります。メッセージレベルのアクセスは、サーバー側ではWebサービス・プロバイダベース・エンドポイントを使用して、クライアント側ではディスパッチ・クライアントを使用して実行できます。
javax.xml.ws.Provider<T>インタフェースを使用して実装されるWebサービス・プロバイダベース・エンドポイントは、Javaサービス・エンドポイント・インタフェース(SEI)ベースのエンドポイントにかわる動的なエンドポイントを提供します。JavaオブジェクトとそのXML表現の変換の詳細を概念化するSEIベースのエンドポイントとは異なり、プロバイダ・インタフェースでは、JAXBバインディングなしでXMLメッセージ・レベルのコンテンツに直接アクセスできます。Webサービス・プロバイダベース・エンドポイントを開発する手順は、「Webサービス・プロバイダベース・エンドポイントの開発」で説明します。javax.xml.ws.Provider<T>インタフェースの詳細は、http://download.oracle.com/javaee/5/api/javax/xml/ws/Provider.htmlを参照してください。
javax.xml.ws.Dispatch<T>インタフェースを使用して実装されるWebサービスのディスパッチ・クライアントは、クライアントがXMLレベルでメッセージを処理できるようにします。Webサービスのディスパッチ・クライアントを開発する手順は、「Webサービス・ディスパッチ・クライアントの開発」で説明します。javax.xml.ws.Dispatch<T>インタフェースの詳細は、http://download.oracle.com/javaee/5/api/javax/xml/ws/Provider.htmlを参照してください。
ディスパッチ・クライアントとプロバイダ・エンドポイントは、WSDLが使用できるかぎり、次のような他のWebLogic Webサービス機能と連動して使用できます。
WS-Security
WS-ReliableMessaging
WS-MakeConnection
WS-AtomicTransaction
プロバイダベース・エンドポイントまたはディスパッチ・クライアントを使用してXMLレベルでメッセージを処理するとき、次の表に定義する使用モードの1つを使用します。使用モードは、「使用モードの指定(@ServiceModeアノテーション)」の説明に従ってjavax.xml.ws.ServiceModeアノテーションを使用して定義します。
表16-1 XMLメッセージ・レベルでの処理のための使用モード
| 使用モード | 説明 |
|---|---|
|
メッセージ |
メッセージ全体を直接処理します。たとえば、SOAPバインディングが使用される場合、SOAPエンベロープ全体にアクセスします。 |
|
ペイロード |
メッセージのペイロードのみを処理します。たとえば、SOAPバインディングが使用される場合、SOAP本体にアクセスします。 |
プロバイダベース・エンドポイントとディスパッチ・クライアントは、表16-2に定義されているメッセージ・フォーマットの1つを使用してメッセージを送受信できます。この表では、構成されているバインディング・タイプ(SOAP over HTTPまたはXML over HTTP)に対応する有効なメッセージ・フォーマットと使用モードの組合せも定義されます。
表16-2 XMLメッセージ・レベルでの処理でサポートされるメッセージ・フォーマット
| メッセージ・フォーマット | SOAP/HTTPバインディングでサポートされる使用モード | XML/HTTPバインディングでサポートされる使用モード |
|---|---|---|
|
|
メッセージ・モード: SOAPエンベロープ ペイロード・モード: SOAP本体 |
メッセージ・モード: ペイロード・モード: |
|
|
SOAP/HTTPバインディングの添付ファイルは |
メッセージ・モード: 添付ファイルの送信に |
|
|
メッセージ・モード: SOAPMessageオブジェクト ペイロードのみではなくSOAPメッセージ全体が受信されるため、ペイロード・モードでは有効ではありません。 |
クライアントがSOAP以外のメッセージをXML/HTTPバインディングで送信できるため、どちらのモードでも有効ではありません。 |
javax.xml.ws.Provider<T>インタフェースを使用して実装されるWebサービス・プロバイダベース・エンドポイントでは、JAXBバインディングを使用せずXMLメッセージ・レベルでコンテンツに直接アクセスできます。
次の手順では、Webサービス・プロバイダを実装するJWSファイルをプログラミングするための一般的な手順を説明します。
表16-3 Webサービス・プロバイダベース・エンドポイントを開発する手順
| # |
手順 | 説明 |
|---|---|---|
|
1 |
Webサービス・プロバイダベースJWSファイルで使用するJWSアノテーションをインポートします。 |
Webサービス・プロバイダベースJWSファイルの標準JWSアノテーションの内容は次のとおりです。 import javax.xml.ws.Provider; import javax.xml.ws.WebServiceProvider; import javax.xml.ws.ServiceMode; 必要であれば他のアノテーションをインポートします。サポートされるすべてのJWSアノテーションのリストは、『Oracle Fusion Middleware Oracle WebLogic Server WebLogic Webサービス・リファレンス』の"Webサービスのアノテーションのサポートに関する項を参照してください。 |
|
2 |
プロバイダベースの実装クラスを開発するときは、表16-2に定義されている、サポート対象のメッセージ・フォーマットの1つを指定します。 |
「メッセージ・フォーマットの指定」を参照してください。 |
|
3 |
必須の標準 |
「JWSファイルによるWebサービス・プロバイダの実装の指定(@WebServiceProviderアノテーション)」を参照してください。 |
|
4 |
標準 |
「使用モードの指定(@ServiceModeアノテーション)」を参照してください。 サービス・モードのデフォルトは |
|
5 |
|
|
次のサンプルJWSファイルは、単純なWebサービス・プロバイダがどのように実装されるかを示します。このサンプルの詳細は後の項で説明します。
サンプル全体の中でこのJWSファイルを確認するには、Oracle WebLogic Serverに含まれるWebサービス・サンプルのJava EEのためのJAX-WS Webサービスの作成に関する項を参照してください。
|
注意: RESTfulなWebサービスは、XML/HTTPバインディング・ベースのプロバイダ・エンドポイントを使用して構築できます。RESTfulなWebサービスでのプロバイダベース・エンドポイントのプログラミング例は、「XML over HTTPを使用するWebサービスのプログラミング」を参照してください。 |
例16-1 Webサービス・プロバイダを実装するJWSファイルの例
package examples.webservices.jaxws;
import org.w3c.dom.Node;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.Service;
import java.io.ByteArrayInputStream;
/**
* A simple Provider-based Web service implementation.
*
* @author Copyright (c) 2010, Oracle and/or its affiliates.
* All Rights Reserved.
*/
// The @ServiceMode annotation specifies whether the Provider instance
// receives entire messages or message payloads.
@ServiceMode(value = Service.Mode.PAYLOAD)
// Standard JWS annotation that configures the Provider-based Web service.
@WebServiceProvider(portName = "SimpleClientPort",
serviceName = "SimpleClientService",
targetNamespace = "http://jaxws.webservices.examples/",
wsdlLocation = "SimpleClientService.wsdl")
public class SimpleClientProviderImpl implements Provider<Source> {
//Invokes an operation according to the contents of the request message.
public Source invoke(Source source) {
try {
DOMResult dom = new DOMResult();
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(source, dom);
Node node = dom.getNode();
// Get the operation name node.
Node root = node.getFirstChild();
// Get the parameter node.
Node first = root.getFirstChild();
String input = first.getFirstChild().getNodeValue();
// Get the operation name.
String op = root.getLocalName();
if ("invokeNoTransaction".equals(op)) {
return sendSource(input);
} else {
return sendSource2(input);
}
}
catch (Exception e) {
throw new RuntimeException("Error in provider endpoint", e);
}
}
private Source sendSource(String input) {
String body =
"<ns:invokeNoTransactionResponse
xmlns:ns=\"http://jaxws.webservices.examples/\"><return>"
+ "constructed:" + input
+ "</return></ns:invokeNoTransactionResponse>";
Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));
return source;
}
private Source sendSource2(String input) {
String body =
"<ns:invokeTransactionResponse
xmlns:ns=\"http://jaxws.webservices.examples/\"><return>"
+ "constructed:" + input
+ "</return></ns:invokeTransactionResponse>";
Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));
return source;
}
}
プロバイダベースの実装クラスを開発するときは、表16-2に定義されている、サポート対象のメッセージ・フォーマットの1つを指定します。
たとえば、「Webサービス・プロバイダベース・エンドポイントを実装するJWSファイルの例」に示すプロバイダの実装例では、SimpleClientProviderImplクラスはProvider<Source>インタフェースを実装し、入力と出力の両方の型がjava.xml.transform.Sourceオブジェクトであることを示します。
public class SimpleClientProviderImpl implements Provider<Source> {
. . .
}
次のコードの抜粋のように、標準のjavax.xml.ws.WebServiceProviderアノテーションを使用して、JWSファイルがWebサービス・プロバイダを実装することをクラス・レベルで指定します。
@WebServiceProvider(portName = "SimpleClientPort",
serviceName = "SimpleClientService",
targetNamespace = "http://jaxws.webservices.examples/",
wsdlLocation = "SimpleClientService.wsdl")
この例では、サービス名はSimpleClientServiceであり、生成されるWSDLファイルのwsdl:service要素にマップされます。ポート名はSimpleClientPortであり、生成されるWSDLのwsdl:port要素にマップされます。生成されるWSDLで使用される対象ネームスペースはhttp://jaxws.webservices.examples/です。WSDLの場所(SimpleClientService.wsdl)はWebサービス・プロバイダに対してローカルです。
@WebServiceProviderアノテーションの詳細は、https://jax-ws.dev.java.net/nonav/2.1.5/docs/annotations.htmlを参照してください。
javax.xml.ws.ServiceModeアノテーションを使用して、Webサービス・プロバイダベース・エンドポイントが、メッセージ全体を受信するか(Service.Mode.MESSAGE)、メッセージ・ペイロードのみを受信するか(Service.Mode.PAYLOAD)を指定します。
例:
@ServiceMode(value = Service.Mode.PAYLOAD)
指定しない場合、@ServiceModeアノテーションのデフォルトはService.Mode.PAYLOADです。
有効なメッセージ・フォーマットと使用モードの組合せのリストは、表16-2を参照してください。
@ServiceModeアノテーションの詳細は、https://jax-ws.dev.java.net/nonav/2.1.4/docs/annotations.htmlを参照してください。
Provider<T>インタフェースによって、実装クラスに定義する必要がある1つのメソッドが定義されます。
T invoke(T request)
Webサービス・リクエストが受信されると、invoke()メソッドが呼び出され、指定のメッセージ・フォーマットを使用するメソッドにメッセージまたはメッセージ・ペイロードを入力として提供します。
たとえば、「Webサービス・プロバイダベース・エンドポイントを実装するJWSファイルの例」に示すプロバイダの実装例では、invokeメソッドが入力としてSourceパラメータを受け取り、Sourceレスポンスを返すように、クラスによって定義されています。
public Source invoke(Source source) {
try {
DOMResult dom = new DOMResult();
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(source, dom);
Node node = dom.getNode();
// Get the operation name node.
Node root = node.getFirstChild();
// Get the parameter node.
Node first = root.getFirstChild();
String input = first.getFirstChild().getNodeValue();
// Get the operation name.
String op = root.getLocalName();
if ("invokeNoTransaction".equals(op)) {
return sendSource(input);
} else {
return sendSource2(input);
}
}
catch (Exception e) {
throw new RuntimeException("Error in provider endpoint", e);
}
}
プロバイダベース・エンドポイントがWSDLファイルから生成される場合、<provider> WSDL拡張を使用してポートをプロバイダとしてマークできます。次に例を示します。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings wsdlLocation="SimpleClientService.wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions" >
<package name="provider.server"/>
<provider>true</provider>
</bindings>
javax.xml.ws.Dispatch<T>インタフェースを使用して実装されるWebサービス・ディスパッチ・クライアントでは、クライアントがXMLレベルでメッセージを処理できます。
次の手順では、Webサービス・ディスパッチ・クライアントをプログラミングするための一般的な手順を説明します。
表16-4 Webサービス・プロバイダベース・エンドポイントを開発する手順
| # |
手順 | 説明 |
|---|---|---|
|
1 |
Webサービス・プロバイダベースJWSファイルで使用するJWSアノテーションをインポートします。 |
Webサービス・プロバイダベースJWSファイルの標準JWSアノテーションの内容は次のとおりです。 import javax.xml.ws.Service; import javax.xml.ws.Dispatch; import javax.xml.ws.ServiceMode; 必要であれば他のアノテーションをインポートします。サポートされるすべてのJWSアノテーションのリストは、『Oracle Fusion Middleware Oracle WebLogic Server WebLogic Webサービス・リファレンス』の"Webサービスのアノテーションのサポートに関する項を参照してください。 |
|
2 |
|
「ディスパッチ・インスタンスの作成」を参照してください。 |
|
3 |
Webサービス・オペレーションを呼び出します。 |
Webサービス・オペレーションは同期(一方向または双方向)または非同期(ポーリングまたは非同期ハンドラ)で呼び出すことができます。「Webサービス・オペレーションの呼出し」を参照してください。 |
次のサンプルは、基本的なWebサービス・ディスパッチ・クライアントがどのように実装されるかを示します。このサンプルの詳細は後の項で説明します。
例16-2 Webサービス・ディスパッチ・クライアントの例
package jaxws.dispatch.client;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.URL;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.ws.soap.SOAPBinding;
public class WebTest extends TestCase {
private static String in_str = "wiseking";
private static String request =
"<ns1:sayHello xmlns:ns1=\"http://example.org\"><arg0>"+in_str+"</arg0></ns1:sayHello>";
private static final QName portQName = new QName("http://example.org", "SimplePort");
private Service service = null;
protected void setUp() throws Exception {
String url_str = System.getProperty("wsdl");
URL url = new URL(url_str);
QName serviceName = new QName("http://example.org", "SimpleImplService");
service = Service.create(serviceName);
service.addPort(portQName, SOAPBinding.SOAP11HTTP_BINDING, url_str);
System.out.println("Setup complete.");
}
public void testSayHelloSource() throws Exception {
setUp();
Dispatch<Source> sourceDispatch =
service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
System.out.println("\nInvoking xml request: " + request);
Source result = sourceDispatch.invoke(new StreamSource(new StringReader(request)));
String xmlResult = sourceToXMLString(result);
System.out.println("Received xml response: " + xmlResult);
assertTrue(xmlResult.indexOf("HELLO:"+in_str)>=0);
}
private String sourceToXMLString(Source result) {
String xmlResult = null;
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
OutputStream out = new ByteArrayOutputStream();
StreamResult streamResult = new StreamResult();
streamResult.setOutputStream(out);
transformer.transform(result, streamResult);
xmlResult = streamResult.getOutputStream().toString();
} catch (TransformerException e) {
e.printStackTrace();
}
return xmlResult;
}
}
javax.xml.ws.Serviceインタフェースは、Dispatchインスタンスの作成でファクトリとして機能します。ディスパッチ・インスタンスを作成するには、まずServiceインスタンスを作成する必要があります。その後、Service.createDispatch()メソッドを使用してディスパッチ・インスタンスを作成します。
例:
...
String url_str = System.getProperty("wsdl");
QName serviceName = new QName("http://example.org", "SimpleImplService");
service = Service.create(serviceName);
service.addPort(portQName, SOAPBinding.SOAP11HTTP_BINDING, url_str);
Dispatch<Source> sourceDispatch =
service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
...
前の例では、createDispatch()メソッドは次の3つのパラメータを取ります。
対象のサービス・エンドポイントの修飾された名前(QName)。
タイプ・パラメータTのクラス。この例では、javax.xml.transform.Sourceフォーマットが使用されます。有効な値は、表16-2を参照してください。
使用モード。この例では、メッセージ・ペイロードが指定されます。有効な使用モードは、表16-1を参照してください。
または、カスタム・アノテーション付きのJAXBクラスを使用してXMLメッセージで作動するように、JAXBコンテキストを渡すことができます。Service.createDispatch()メソッドの呼出しに使用できる有効なパラメータの詳細は、javax.xml.ws.Service Javadoc(https://jax-ws.dev.java.net/nonav/2.1.1/docs/api/javax/xml/ws/Service.html)を参照してください。
Dispatchインスタンスが作成されたら、それを使用してWebサービス・オペレーションを呼び出します。Webサービス・オペレーションは、同期(一方向または双方向)または非同期(ポーリングまたは非同期ハンドラ)で呼び出すことができます。同期および非同期の呼出し方法の詳細は、javax.xml.ws.Dispatch Javadoc(https://jax-ws.dev.java.net/nonav/2.1.1/docs/api/javax/xml/ws/Dispatch.html)を参照してください。
たとえば、次のコードの抜粋では、XMLメッセージはjavax.xml.transform.stream.StreamSourceオブジェクトとしてカプセル化され、同期invoke()メソッドに渡されています。レスポンスXMLはresult変数でSourceオブジェクトとして返され、XMLに変換されます。メッセージをXMLに戻すために使用されるsourcetoXMLString()メソッドは、例16-2に示しています。
... private static String request = "<ns1:sayHello xmlns:ns1=\"http://example.org\"><arg0>"+in_str+"</arg0></ns1:sayHello>"; Source result = sourceDispatch.invoke(new StreamSource(new StringReader(request))); String xmlResult = sourceToXMLString(result); ...