WSIF-Service entwickeln
Ein WSIF-Service (Web Services Invocation Framework) ist ein Web-Service, der WSIF verwendet.
Informationen zu diesem Vorgang
Wenn Sie einen WSIF-Service entwickeln möchten, müssen Sie zunächst den Web-Service erstellen (oder einen vorhandenen Web-Service verwenden) und dann den WSIF-Client ausgehend vom WSDL-Dokument für diesen Web-Service entwickeln.
Außerdem gibt es zwei bereits erstellte WSIF-Muster, die zum Download auf der Seite mit den Mustern zu WebSphere Application Server auf der developerWorks-Website zur Verfügung stehen.
- AddressBook
- StockQuote
Weitere Informationen zur Verwendung dieser Muster können Sie der Dokumentation entnehmen, die im developerWorks-Downloadpaket enthalten ist. Beachten Sie, dass diese Muster für WebSphere Application Server Version 5 geschrieben wurden.
Gehen Sie wie folgt vor, um einen WSIF-Service zu entwickeln:
Vorgehensweise
Beispiel: Mit WSIF den Beispiel-Web-Service "AddressBook" dynamisch aufrufen
Der folgende Beispielcode zeigt den dynamischen Aufruf des Beispiel-Web-Service AddressBook mit WSIF:
try {
String wsdlLocation="clients/addressbook/AddressBookSample.wsdl";
//Der Ausgangspunkt für dynamische Aufrufe mit WSIF ist eine
//WSIFServiceFactory. Hier wird eine solche mit der Methode
//newInstance erstellt.
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
//Anschließend kann mit der Factory ein WSIFService-Objekt erstellt werden,
//das dem Service AddressBookService in der wsdl-Datei entspricht.
// Anmerkung: Da in der wsdl-Datei nur ein Service definiert ist, müssen
//Namespace und Name des Service nicht verwendet werden. Stattdessen kann
//null übergeben werden. Dasselbe gilt für den Porttyp, obwohl hier zur
//Veranschaulichung Werte verwendet werden.
WSIFService service = factory.getService(
wsdlLocation, // Position der wsdl-Datei
null, // Service-Namespace
null, // Servicename
"http://www.ibm.com/namespace/wsif/samples/ab", // Namespace des portType
"AddressBookPT" // Name des portType
);
// Die Datei AddressBook.wsdl enthält die Definitionen für zwei complexType-Elemente
// innerhalb des Eintrags schema. Diese Elemente werden jetzt Java-Klassen zugeordnet.
// Diese Zuordnungen werden vom Apache-SOAP-Provider verwendet.
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"));
// Jetzt liegt ein WSIFService-Objekt vor. Als nächstes wird ein WSIFPort-
// Objekt für den zu verwendenden Port erstellt. Mit der Methode
// getPort(String portName) kann ein WSIFPort aus dem Portnamen erstellt werden.
WSIFPort port = null;
if (portName != null) {
port = service.getPort(portName);
}
if (port == null) {
// Wenn kein Portname angegeben wurde, kann versucht werden, einen WSIFPort aus den Ports
// zu erstellen, die für den Porttyp, der für den Service angegeben wurde, verfügbar sind.
port = getPortFromAvailablePortNames(service);
}
// Mit dem WSIFPort kann eine Operation erstellt werden. Hier soll die Operation
// addEntry ausgeführt und daher versucht werden, eine entsprechende WSIFOperation
// zu erstellen. Die Operation addEntry in der wsdl ist überladen. Es sind zwei
// Versionen mit unterschiedlichen Parametern (Abschnitten) vorhanden.
// Deshalb müssen die Namen der Ein- und Ausgabenachricht für die Operation
// in der Methode createOperation angegeben werden, damit die richtige Operation
// aufgelöst werden kann.
// Da die Operation addEntry keine Ausgabenachricht hat, wird als Name null verwendet.
WSIFOperation operation =
port.createOperation("addEntry", "AddEntryWholeNameRequest", null);
// Es werden Nachrichten für den Verlauf der Operation erstellt. Dazu werden die Methoden
// createXXXXXMessage für die WSIFOperation aufgerufen.
WSIFMessage inputMessage = operation.createInputMessage();
WSIFMessage outputMessage = operation.createOutputMessage();
WSIFMessage faultMessage = operation.createFaultMessage();
// Es werden ein Name und eine Adresse erstellt und zum Adressbuch hinzugefügt.
String nameToAdd="Chris P. Bacon";
WSIFAddress addressToAdd =
new WSIFAddress (1,
"The Waterfront",
"Some City",
"NY",
47907,
new WSIFPhone (765, "494", "4900"));
//Jetzt werden Name und Adresse zur Eingabenachricht hinzugefügt.
inputMessage.setObjectPart("name", nameToAdd);
inputMessage.setObjectPart("address", addressToAdd);
//Jetzt wird die Operation ausgeführt und eine Markierung zur erfolgreichen Ausführung empfangen.
boolean operationSucceeded =
operation.executeRequestResponseOperation(
inputMessage,
outputMessage,
faultMessage);
if (operationSucceeded) {
System.out.println("Name und Adresse wurden zum Adressbuch hinzugefügt\n");
} else {
System.out.println("Name und Adresse konnten nicht zum Adressbuch hinzugefügt werden");
}
// Erneuter Beginn
operation = null;
inputMessage = null;
outputMessage = null;
faultMessage = null;
// Jetzt wird im Adressbuch nach einer Adresse gesucht.
// Die Operation getAddressFromName ist in der wsdl nicht überladen,
// so dass einfach der Name der Operation ohne die Namen von Ein- oder
// Ausgabenachrichten angegeben werden kann.
operation = port.createOperation("getAddressFromName");
//Die Nachrichten werden erstellt.
inputMessage = operation.createInputMessage();
outputMessage = operation.createOutputMessage();
faultMessage = operation.createFaultMessage();
//Der im Adressbuch zu suchende Name wird angegeben.
String nameToLookup="Chris P. Bacon";
inputMessage.setObjectPart("name", nameToLookup);
// Die Operation wird ausgeführt.
operationSucceeded =
operation.executeRequestResponseOperation(
inputMessage,
outputMessage,
faultMessage);
if (operationSucceeded) {
System.out.println("Erfolgreiche Suche nach dem Namen '"+nameToLookup+"' im Adressbuch");
// Die gefundene Adresse kann durch Abfragen der Ausgabenachricht abgerufen werden.
WSIFAddress addressFound = (WSIFAddress) outputMessage.getObjectPart("address");
System.out.println("Folgende Adresse wurde gefunden:");
System.out.println(addressFound);
} else {
System.out.println("Der Name wurde nicht im Adressbuch gefunden");
}
} catch (Exception e) {
System.out.println("Beim Ausführen des Beispiels ist eine Ausnahme eingetreten:");
e.printStackTrace();
}
}
Der obige Code bezieht sich auf die folgende Beispielmethode:
WSIFPort getPortFromAvailablePortNames(WSIFService service)
throws WSIFException {
String portChosen = null;
// Es wird eine Liste der für den Service verfügbaren Portnamen abgerufen.
Iterator it = service.getAvailablePortNames();
{
System.out.println("Für den Service sind folgende Ports verfügbar: ");
while (it.hasNext()) {
String nextPort = (String) it.next();
if (portChosen == null)
portChosen = nextPort;
System.out.println(" - " + nextPort);
}
}
if (portChosen == null) {
throw new WSIFException("Keine Ports für den Service gefunden!");
}
System.out.println("Verwendet wird Port " + portChosen + "\n");
// Alternativ kann der Port für den Service auch mit der Methode
// setPreferredPort angegeben werden. Nachdem für den Service ein
// bevorzugter Port definiert wurde, kann mit getPort (ohne Argumente)
// ein WSIFPort abgerufen werden. Wenn kein bevorzugter Port definiert
// wurde und mehr als ein Port für den im WSIFService angegebenen Porttyp
// verfügbar ist, wird eine Ausnahme ausgelöst.
service.setPreferredPort(portChosen);
WSIFPort port = service.getPort();
return port;
}
Der Web-Service verwendet die folgenden Klassen:
WSIFAddress:
public class WSIFAddress implements Serializable {
//Instanzvariablen
private int streetNum;
private java.lang.String streetName;
private java.lang.String city;
private java.lang.String state;
private int zip;
private WSIFPhone phoneNumber;
//Konstruktoren
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 {
//Instanzvariablen
private int areaCode;
private java.lang.String exchange;
private java.lang.String number;
//Konstruktoren
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("Das Namensargument darf nicht " +
"null sein.");
}
return (WSIFAddress)name2AddressTable.get(name);
}
}
Der folgende Code entspricht der WSDL-Datei für den Web-Service:
<?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>