Développement d'un service WSIF

Un service WSIF (Web Services Invocation Framework) est un service Web qui utilise WSIF.

Pourquoi et quand exécuter cette tâche

Pour développer un service WSIF, développez le service Web correspondant (ou partez d'un service Web existant), puis développez le client WSIF d'après le document WSDL qui définit ce service Web.

Deux exemples WSIF prégénérés sont également disponibles en téléchargement à partir de la page d'exemples WebSphere Application Server du site Web developerWorks :

  • l'exemple Address Book (carnet d'adresses),
  • l'exemple Stock Quote (cotation boursière).

Pour plus d'informations sur l'utilisation de ces exemples préconfigurés, consultez la documentation incluse dans le module à télécharger developerWorks. Notez que ces exemples ont été conçus pour fonctionner avec WebSphere Application Server version 5.

Pour développer un service WSIF, effectuez les étapes ci-dessous.

Procédure

  1. Implémentation du service Web.

    Utilisez les outils des services Web pour découvrir, créer et publier le service Web. Vous pouvez développer des services Web sous forme de beans Java, d'EJB (Enterprise JavaBeans) ou d'URL. Vous pouvez utiliser les outils des services Web pour créer un code Java squelette et un exemple d'application à partir d'un document WSDL. Par exemple, un bean enterprise peut être mis à disposition sous la forme d'un service Web, avec le protocole RMI-IIOP (Remote Method Invocation over Internet Inter-ORB Protocol) comme protocole d'accès. Il est aussi possible de désigner une classe Java comme service Web et d'utiliser comme protocole d'accès des appels natifs Java.

    [AIX Solaris HP-UX Linux Windows][z/OS]Vous pouvez utiliser l'outilWebSphere Studio Application Developer pour créer un service Web à partir d'une application Java ; le tutoriel de cet outil, fondé sur l'exemple de service StockQuote, explique comment procéder. L'application Java que vous utilisez dans ce scénario renvoie le dernier cours connu d'un titre (communiqué par un symbole), obtenu du site Web www.xmltoday.com. En utilisant l'assistant de services Web, vous générez un document WSDL de liaison appelé StockQuoteService-binding.wsdl et un document WSDL de service appelé StockQuoteService-service.wsdl à partir du bean StockQuoteService.java. Vous déployez ensuite le service Web sur un serveur Web, puis vous générez un proxy client pour ce service Web ainsi qu'un spécimen d'application qui accède à StockQuoteService à travers le proxy client. Vous testez le service Web StockQuote, vous le publiez à l'aide de l'outil IBM® UDDI Explorer, puis vous le découvrez dans le registre IBM UDDI Test.

    [IBM i]Vous pouvez utiliser l'outil WebSphere Development Studio pour System i (WDS) afin de créer un service Web à partir d'une application Java. Lorsque vous utilisez l'assistant de services Web, vous générez un document WSDL de liaison et un document WSDL de service à partir du bean Java. Vous pouvez ensuite déployer le service Web sur un serveur Web, puis générer un proxy client pour ce service Web ainsi qu'un modèle d'application qui accède au service via le proxy client. Vous pouvez tester le service, le publier à l'aide de l'outil IBM UDDI Explorer, puis le découvrir dans le Registre UDDI de test IBM.

  2. Développez le client WSIF.
    Utilisez les informations suivantes pour développer un client WSIF :

    L'exemple AddressBook est écrit pour une interaction synchrone. Si vous utilisez un fournisseur JMS, il est possible que votre client WSIF ait besoin d'agir de façon asynchrone. WSIF fournit deux fonctions clés qui répondent à ce besoin :

    • Un service de corrélation qui attribue des identificateurs aux messages afin qu'une demande puisse être mise en correspondance avec la réponse qui s'ensuit.
    • Un gestionnaire de réponse qui obtient la réponse du service Web à un moment ultérieur.
    Pour plus d'informations, voir WSIFOperation - Référence des interactions asynchrones.

Exemple : Utilisation de WSIF pour un appel dynamique du modèle de service Web AddressBook

Voici un exemple de code client permettant d'appeler de manière dynamique l'exemple de service AddressBook via l'API WSIF :

    try {
        String wsdlLocation="clients/addressbook/AddressBookSample.wsdl";

        // Le point de départ de tout appel dynamique à l'aide de WSIF est
        // un objet WSIFServiceFactory. Nous en créons un avec la méthode
        // newInstance.
        WSIFServiceFactory factory = WSIFServiceFactory.newInstance();

        // Une fois en possession d'une fabrique, utilisez-la pour créer un objet
        // WSIFService correspondant au service AddressBookService dans le fichier WSDL.
        // Remarque : Comme un seul service est défini dans le fichier WSDL, il
        // est inutile d'indiquer l'espace de noms (namespace) et le nom du service
        // et "null" peut être passé pour ces paramètres. Cette remarque s'applique aussi
            // au type de port, même si des valeurs ont été utilisées plus bas à des fins
        // d'illustration.
        WSIFService service = factory.getService(
            wsdlLocation,    // emplacement du fichier WSDL 
            null,            // espace de noms des services
            null,            // nom du service
           "http://www.ibm.com/namespace/wsif/samples/ab", // port type namespace
            "AddressBookPT" // port type name
        );

        // Le fichier AddressBook.wsdl contient les définitions de deux éléments complexType
        // à l'intérieur de l'élément schema. Mappez ces types
        // complexes vers des classes Java. Ces mappages sont utilisés par le fournisseur Apache SOAP.            
        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"));
            // Vous disposez maintenant d'un objet WSIFService. L'étape suivante vise à créer
            // un objet WSIFPort pour le port à utiliser. La méthode
                  // getPort(String portName) nous permet de générer un WSIFPort à partir du
            // nom de port.
        WSIFPort port = null;

        if (portName != null) {
            port = service.getPort(portName);
        }
        if (port == null) {
            // Si aucun nom de port n'a été spécifié, tentons de créer un WSIFPort à partir
            // des ports disponibles pour le type de port spécifié dans le service.
            port = getPortFromAvailablePortNames(service);
        }

        // Une fois en possession d'un WSIFPort, vous pouvez créer une opération. Exécutez
        // l'opération addEntry puis créez un objet WSIFOperation correspondant à cette
        // opération. L'opération addEntry est surchargée dans le fichier wsdl, à savoir qu'il en 
		// existe deux versions, chacune recevant en entrée des paramètres
(parties) différents. 
		// Cette surcharge vous oblige à spécifier les noms des messages d'entrée et de sortie 
		// de l'opération dans la méthode createOperation afin que
l'opération correcte 
		// puisse être résolue.
        // L'opération addEntry n'ayant pas de message de sortie, utilisez "null" comme nom.
        WSIFOperation operation =
            port.createOperation("addEntry", "AddEntryWholeNameRequest", null);

        // Créons les messages à utiliser dans l'exécution de l'opération. Pour cela, nous
        // appelons les méthodes createXXXXXMessage sur l'objet WSIFOperation.
        WSIFMessage inputMessage = operation.createInputMessage();
        WSIFMessage outputMessage = operation.createOutputMessage();
        WSIFMessage faultMessage = operation.createFaultMessage();

        // Créons un nom et une adresse à ajouter au carnet d'adresses
        String nameToAdd="Chris P. Bacon";
        WSIFAddress addressToAdd = 
            new WSIFAddress (1, 
                "The Waterfront",
                "Some City",
                "NY",
                47907,
                new WSIFPhone (765, "494", "4900"));

        // Ajoutons le nom et l'adresse au message d'entrée
        inputMessage.setObjectPart("nom", nameToAdd);
        inputMessage.setObjectPart("adresse", addressToAdd);

        // Exécutons l'opération et récupérons en retour un fanion indiquant si
        // elle a réussi ou échoué.
        boolean operationSucceeded =
            operation.executeRequestResponseOperation(
                inputMessage,
                outputMessage,
                faultMessage);

        if (operationSucceeded) {
            System.out.println("Le nom et l'adresse ont été ajoutés au carnet d'adresses\n");
        } else {
            System.out.println("Impossible d'ajouter le nom et l'adresse au carnet d'adresses");
        }

        // Remettons tout à zéro
        operation = null;
        inputMessage = null;
        outputMessage = null;
        faultMessage = null;

        // Cette fois, vous rechercherez une adresse dans le carnet d'adresses.
        // L'opération getAddressFromName n'est pas surchargée dans le fichier WSDL et,
        // par conséquent, nous pouvez spécifier son nom, sans
        // indiquer les noms des messages d'entrée et de sortie.
        operation = port.createOperation("getAddressFromName");

        // Créons les messages
        inputMessage = operation.createInputMessage();
        outputMessage = operation.createOutputMessage();
        faultMessage = operation.createFaultMessage();

        // Spécifions le nom à rechercher dans le carnet d'adresses
        String nameToLookup="Chris P. Bacon";
        inputMessage.setObjectPart("name", nameToLookup);

        // Exécutons l'opération
        operationSucceeded =
            operation.executeRequestResponseOperation(
                inputMessage,
                outputMessage,
                faultMessage);

        if (operationSucceeded) {
            System.out.println("Recherche du nom '"+nameToLookup+"' effectuée dans le carnet d'adresses");

            // Vous pouvez obtenir l'adresse trouvée en interrogeant le message de sortie
            WSIFAddress addressFound = (WSIFAddress)  outputMessage.getObjectPart("adresse");
            System.out.println("L'adresse trouvée était :");
            System.out.println(addressFound);
        } else {
            System.out.println("Echec de la recherche du nom dans le carnet d'adresses");
        }

    } catch (Exception e) {
        System.out.println("Une exception s'est produite lors de l'exécution de l'exemple :");
        e.printStackTrace();
    }
}

Le code ci-dessus fait appel à l'exemple de méthode suivant :

    WSIFPort getPortFromAvailablePortNames(WSIFService service)
            throws WSIFException {
        String portChosen = null;
        
        // Obtenir la liste des noms de ports disponibles pour le service
        Iterator it = service.getAvailablePortNames();
        {
            System.out.println("Les ports disponibles pour le service sont : ");
            while (it.hasNext()) {
                String nextPort = (String) it.next();
                if (portChosen == null)
                    portChosen = nextPort;
                System.out.println(" - " + nextPort);
            }
        }
        if (portChosen == null) {
            throw new WSIFException("Aucun port trouvé pour le service !");
        }
        System.out.println("Utilisation du port " + portChosen + "\n");
        
        // Un autre moyen de spécifier le port à utiliser sur le service est de recourir
        // à la méthode setPreferredPort. Dès lors qu'un port préféré a été défini sur
        // le service, un objet WSIFPort peut être obtenu par un appel à getPort
        // (sans argument). Si aucun port préféré n'a été défini et que plusieurs ports
        // sont disponibles pour le type de port spécifié dans le WSIFService, une
        // exception est lancée. 
        service.setPreferredPort(portChosen);
        WSIFPort port = service.getPort();
        return port;
    }

Le service Web utilise les classes suivantes :

WSIFAddress :

public class WSIFAddress implements Serializable {

    //variables d'instance
    private int	streetNum;
    private java.lang.String	streetName;
    private java.lang.String	city;
    private java.lang.String	state;
    private int	zip;
    private WSIFPhone	phoneNumber;

    //constructeurs
    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 {

    //variables d'instance
    private int	areaCode;
    private java.lang.String	exchange;
    private java.lang.String	number;

    //constructeurs
    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("L'argument du nom ne doit pas être" +
                                               "null.");
        }
        return (WSIFAddress)name2AddressTable.get(name);
    }

}

Le code suivant constitue le fichier WSDL correspondant pour le service Web :

<?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>

Icône indiquant le type de rubrique Rubrique de tâche



Icône d'horodatage Dernière mise à jour: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twsf_devwes
Nom du fichier : twsf_devwes.html