WSIF サービスの開発
Web Services Invocation Framework (WSIF) サービスは、WSIF を使用する Web サービスです。
このタスクについて
WSIF サービスを開発するには、まず Web サービスを開発 (または既存の Web サービスを使用) し、次にその Web サービスを記述する Web サービス記述言語 (WSDL) 文書に基づいて WSIF クライアントを開発します。
作成済みの次の 2 つの WSIF サンプルを developerWorks® Web サイトの WebSphere® Application Server サンプル・ページからダウンロードすることもできます。
- Address Book サンプル。
- Stock Quote サンプル。
作成済みサンプルの使用方法について詳しくは、 developerWorks のダウンロード・パッケージに含まれている資料を参照してください。 これらのサンプルは、WebSphere Application Server バージョン 5 で動作するように作成されていることに注意してください。
WSIF サービスを開発するには、以下のステップを実行します。
手順
例: WSIF を使用した AddressBook サンプル Web サービスの動的呼び出し
これは、WSIF を使用して AddressBook サンプル Web サービスを動的に呼び出すコード例です。
try {
String wsdlLocation="clients/addressbook/AddressBookSample.wsdl";
// The starting point for any dynamic invocation using wsif is a
// WSIFServiceFactory. Create one through the newInstance
// method.
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
// Once you have a factory, you can use it to create a WSIFService object
// corresponding to the AddressBookService service in the wsdl file.
// Note: because you only have one service defined in the wsdl file, you
// do not have to use the namespace and name of the service and can pass
// null instead. This also applies to the port type, although values have
// been used in the following example for illustrative purposes.
WSIFService service = factory.getService(
wsdlLocation, // location of the wsdl file
null, // service namespace
null, // service name
"http://www.ibm.com/namespace/wsif/samples/ab", // port type namespace
"AddressBookPT" // port type name
);
// The AddressBook.wsdl file contains the definitions for two complexType
// elements within the schema element. Map these complexTypes
// to Java classes. These mappings are used by the Apache SOAP provider
service.mapType(
new javax.xml.namespace.QName(
"http://www.ibm.com/namespace/wsif/samples/ab/types",
"address"),
Class.forName("com.ibm.www.namespace.wsif.samples.ab.types.WSIFAddress"));
service.mapType(
new javax.xml.namespace.QName(
"http://www.ibm.com/namespace/wsif/samples/ab/types",
"phone"),
Class.forName("com.ibm.www.namespace.wsif.samples.ab.types.WSIFPhone"));
// You now have a WSIFService object. The next step is to create a WSIFPort
// object for the port you want to use. The getPort(String portName) method
// allows us to generate a WSIFPort from the port name.
WSIFPort port = null;
if (portName != null) {
port = service.getPort(portName);
}
if(port == null) {
// If no port name was specified, attempt to create a WSIFPort from
// the available ports for the port type specified on the service
port = getPortFromAvailablePortNames(service);
}
// Once you have a WSIFPort, you can create an operation. Execute
// the addEntry operation and therefore attempt to create a WSIFOperation
// corresponding to it. The addEntry operation is overloaded in the wsdl i.e.
// there are two versions of it, each taking different parameters (parts).
// This overloading requires that you specify the input and output message
// names for the operation in the createOperation method so that the correct
// operation can be resolved.
// Because the addEntry operation has no output message, you use null for its name.
WSIFOperation operation =
port.createOperation("addEntry", "AddEntryWholeNameRequest", null);
// Create messages to use in the execution of the operation. This should
// be done by invoking the createXXXXXMessage methods on the WSIFOperation.
WSIFMessage inputMessage = operation.createInputMessage();
WSIFMessage outputMessage = operation.createOutputMessage();
WSIFMessage faultMessage = operation.createFaultMessage();
// Create a name and address to add to the addressbook
String nameToAdd="Chris P. Bacon";
WSIFAddress addressToAdd =
new WSIFAddress (1,
"The Waterfront",
"Some City",
"NY",
47907,
new WSIFPhone (765, "494", "4900"));
// Add the name and address to the input message
inputMessage.setObjectPart("name", nameToAdd);
inputMessage.setObjectPart("address", addressToAdd);
// Execute the operation, obtaining a flag to indicate its success
boolean operationSucceeded =
operation.executeRequestResponseOperation(
inputMessage,
outputMessage,
faultMessage);
if (operationSucceeded) {
System.out.println("Successfully added name and address to addressbook¥n");
} else {
System.out.println("Failed to add name and address to addressbook");
}
// Start from fresh
operation = null;
inputMessage = null;
outputMessage = null;
faultMessage = null;
// This time you will lookup an address from the addressbook.
// The getAddressFromName operation is not overloaded in the
// wsdl and therefore you can specify the operation name
// without any input or output message names.
operation = port.createOperation("getAddressFromName");
// Create the messages
inputMessage = operation.createInputMessage();
outputMessage = operation.createOutputMessage();
faultMessage = operation.createFaultMessage();
// Set the name to find in the addressbook
String nameToLookup="Chris P. Bacon";
inputMessage.setObjectPart("name", nameToLookup);
// Execute the operation
operationSucceeded =
operation.executeRequestResponseOperation(
inputMessage,
outputMessage,
faultMessage);
if (operationSucceeded) {
System.out.println("Successful lookup of name '"+nameToLookup+"' in addressbook");
// You can get the address that was found by querying the output message
WSIFAddress addressFound = (WSIFAddress) outputMessage.getObjectPart("address");
System.out.println("The address found was:");
System.out.println(addressFound);
} else {
System.out.println("Failed to lookup name in addressbook");
}
} catch (Exception e) {
System.out.println("An exception occurred when running the sample:");
e.printStackTrace();
}
}
上記のコードは以下のサンプル・メソッドを参照します。
WSIFPort getPortFromAvailablePortNames(WSIFService service)
throws WSIFException {
String portChosen = null;
// Obtain a list of the available port names for the service
Iterator it = service.getAvailablePortNames();
{
System.out.println("Available ports for the service are: ");
while (it.hasNext()) {
String nextPort = (String) it.next();
if (portChosen == null)
portChosen = nextPort;
System.out.println(" - " + nextPort);
}
}
if (portChosen == null) {
throw new WSIFException("No ports found for the service!");
}
System.out.println("Using port " + portChosen + "¥n");
// An alternative way of specifying the port to use on the service
// is to use the setPreferredPort method. Once a preferred port has
// been set on the service, a WSIFPort can be obtained through getPort
// (no arguments). If a preferred port has not been set and more than
// one port is available for the port type specified in the WSIFService,
// an exception is thrown.
service.setPreferredPort(portChosen);
WSIFPort port = service.getPort();
return port;
}
Web サービスは以下のクラスを使用します。
WSIFAddress:
public class WSIFAddress implements Serializable {
//instance variables
private int streetNum;
private java.lang.String streetName;
private java.lang.String city;
private java.lang.String state;
private int zip;
private WSIFPhone phoneNumber;
//constructors
public WSIFAddress () { }
public WSIFAddress (int streetNum,
java.lang.String streetName,
java.lang.String city,
java.lang.String state,
int zip,
WSIFPhone phoneNumber) {
this.streetNum = streetNum;
this.streetName = streetName;
this.city = city;
this.state = state;
this.zip = zip;
this.phoneNumber = phoneNumber;
}
public int getStreetNum() {
return streetNum;
}
public void setStreetNum(int streetNum) {
this.streetNum = streetNum;
}
public java.lang.String getStreetName() {
return streetName;
}
public void setStreetName(java.lang.String streetName) {
this.streetName = streetName;
}
public java.lang.String getCity() {
return city;
}
public void setCity(java.lang.String city) {
this.city = city;
}
public java.lang.String getState() {
return state;
}
public void setState(java.lang.String state) {
this.state = state;
}
public int getZip() {
return zip;
}
public void setZip(int zip) {
this.zip = zip;
}
public WSIFPhone getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(WSIFPhone phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
WSIFPhone:
public class WSIFPhone implements Serializable {
//instance variables
private int areaCode;
private java.lang.String exchange;
private java.lang.String number;
//constructors
public WSIFPhone () { }
public WSIFPhone (int areaCode,
java.lang.String exchange,
java.lang.String number) {
this.areaCode = areaCode;
this.exchange = exchange;
this.number = number;
}
public int getAreaCode() {
return areaCode;
}
public void setAreaCode(int areaCode) {
this.areaCode = areaCode;
}
public java.lang.String getExchange() {
return exchange;
}
public void setExchange(java.lang.String exchange) {
this.exchange = exchange;
}
public java.lang.String getNumber() {
return number;
}
public void setNumber(java.lang.String number) {
this.number = number;
}
}
WSIFAddressBook:
public class WSIFAddressBook {
private Hashtable name2AddressTable = new Hashtable();
public WSIFAddressBook() {
}
public void addEntry(String name, WSIFAddress address)
{
name2AddressTable.put(name, address);
}
public void addEntry(String firstName, String lastName, WSIFAddress address)
{
name2AddressTable.put(firstName+" "+lastName, address);
}
public WSIFAddress getAddressFromName(String name)
throws IllegalArgumentException
{
if (name == null)
{
throw new IllegalArgumentException("The name argument must not be " +
"null.");
}
return (WSIFAddress)name2AddressTable.get(name);
}
}
次に示すコードは、対応する Web サービス用の WSDL ファイルです。
<?xml version="1.0" ?>
<definitions targetNamespace="http://www.ibm.com/namespace/wsif/samples/ab"
xmlns:tns="http://www.ibm.com/namespace/wsif/samples/ab"
xmlns:typens="http://www.ibm.com/namespace/wsif/samples/ab/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/"
xmlns:java="http://schemas.xmlsoap.org/wsdl/java/"
xmlns:ejb="http://schemas.xmlsoap.org/wsdl/ejb/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<xsd:schema
targetNamespace="http://www.ibm.com/namespace/wsif/samples/ab/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="phone">
<xsd:element name="areaCode" type="xsd:int"/>
<xsd:element name="exchange" type="xsd:string"/>
<xsd:element name="number" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="address">
<xsd:element name="streetNum" type="xsd:int"/>
<xsd:element name="streetName" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:int"/>
<xsd:element name="phoneNumber" type="typens:phone"/>
</xsd:complexType>
</xsd:schema> </types>
<message name="AddEntryWholeNameRequestMessage">
<part name="name" type="xsd:string"/>
<part name="address" type="typens:address"/>
</message>
<message name="AddEntryFirstAndLastNamesRequestMessage">
<part name="firstName" type="xsd:string"/>
<part name="lastName" type="xsd:string"/>
<part name="address" type="typens:address"/>
</message>
<message name="GetAddressFromNameRequestMessage">
<part name="name" type="xsd:string"/>
</message>
<message name="GetAddressFromNameResponseMessage">
<part name="address" type="typens:address"/>
</message>
<portType name="AddressBookPT">
<operation name="addEntry">
<input name="AddEntryWholeNameRequest"
message="tns:AddEntryWholeNameRequestMessage"/>
</operation>
<operation name="addEntry">
<input name="AddEntryFirstAndLastNamesRequest"
message="tns:AddEntryFirstAndLastNamesRequestMessage"/>
</operation>
<operation name="getAddressFromName">
<input name="GetAddressFromNameRequest"
message="tns:GetAddressFromNameRequestMessage"/>
<output name="GetAddressFromNameResponse"
message="tns:GetAddressFromNameResponseMessage"/>
</operation>
</portType>
<binding name="SOAPHttpBinding" type="tns:AddressBookPT">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="addEntry">
<soap:operation soapAction=""/>
<input name="AddEntryWholeNameRequest">
<soap:body use="encoded"
namespace="http://www.ibm.com/namespace/wsif/samples/ab"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
</operation>
<operation name="addEntry">
<soap:operation soapAction=""/>
<input name="AddEntryFirstAndLastNamesRequest">
<soap:body use="encoded"
namespace="http://www.ibm.com/namespace/wsif/samples/ab"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
</operation>
<operation name="getAddressFromName">
<soap:operation soapAction=""/>
<input name="GetAddressFromNameRequest">
<soap:body use="encoded"
namespace="http://www.ibm.com/namespace/wsif/samples/ab"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="GetAddressFromNameResponse">
<soap:body use="encoded"
namespace="http://www.ibm.com/namespace/wsif/samples/ab"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<binding name="JavaBinding" type="tns:AddressBookPT">
<java:binding/>
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="typens:address"
formatType="com.ibm.www.namespace.wsif.samples.ab.types.WSIFAddress"/>
<format:typeMap typeName="xsd:string" formatType="java.lang.String"/>
</format:typeMapping>
<operation name="addEntry">
<java:operation
methodName="addEntry"
parameterOrder="name address"
methodType="instance"/>
<input name="AddEntryWholeNameRequest"/>
</operation>
<operation name="addEntry">
<java:operation
methodName="addEntry"
parameterOrder="firstName lastName address"
methodType="instance"/>
<input name="AddEntryFirstAndLastNamesRequest"/>
</operation>
<operation name="getAddressFromName">
<java:operation
methodName="getAddressFromName"
parameterOrder="name"
methodType="instance"
returnPart="address"/>
<input name="GetAddressFromNameRequest"/>
<output name="GetAddressFromNameResponse"/>
</operation>
</binding>
<binding name="EJBBinding" type="tns:AddressBookPT">
<ejb:binding/>
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="typens:address"
formatType="com.ibm.www.namespace.wsif.samples.ab.types.WSIFAddress"/>
<format:typeMap typeName="xsd:string" formatType="java.lang.String"/>
</format:typeMapping>
<operation name="addEntry">
<ejb:operation
methodName="addEntry"
parameterOrder="name address"
interface="remote"/>
<input name="AddEntryWholeNameRequest"/>
</operation>
<operation name="addEntry">
<ejb:operation
methodName="addEntry"
parameterOrder="firstName lastName address"
interface="remote"/>
<input name="AddEntryFirstAndLastNamesRequest"/>
</operation>
<operation name="getAddressFromName">
<ejb:operation
methodName="getAddressFromName"
parameterOrder="name"
interface="remote"
returnPart="address"/>
<input name="GetAddressFromNameRequest"/>
<output name="GetAddressFromNameResponse"/>
</operation>
</binding>
<service name="AddressBookService">
<port name="SOAPPort" binding="tns:SOAPHttpBinding">
<soap:address
location="http://myServer/wsif/samples/addressbook/soap/servlet/rpcrouter"/>
</port>
<port name="JavaPort" binding="tns:JavaBinding">
<java:address className="services.addressbook.WSIFAddressBook"/>
</port>
<port name="EJBPort" binding="tns:EJBBinding">
<ejb:address className="services.addressbook.ejb.AddressBookHome"
jndiName="ejb/samples/wsif/AddressBook"
classLoader="services.addressbook.ejb.AddressBook.ClassLoader"/>
</port>
</service>
</definitions>