Indice del libro

Obiettivi di apprendimento

  • Comprendere cosa sono i web service e a cosa servono
  • Comprendere cos'è SOAP e per quali web service lo utilizzano
  • Conoscere il linguaggio di descrizione dei web service e come leggere un file WSDL
  • Conoscere lo standard Universal Description, Discovery and Integration (UDDI)
  • Capire come utilizzare Java per connettersi a un servizio web

I web service (servizi web) sono una nuova generazione di applicazioni web. Sono applicazioni modulari, autosufficienti e autodescrittive, che possono essere pubblicate, localizzate e richiamate attraverso il web. I web service eseguono funzioni di qualsiasi tipo, da semplici richieste a processi aziendali complicati. Una volta distribuito un web service, altre applicazioni (e altri web service) possono rilevare e richiamare il servizio distribuito. I web service utilizzano XML per descrivere richiesta e risposta, e usano HTTP per il trasporto in rete.

Panoramica dei web service

modifica

La principale differenza tra un web service e un'applicazione web riguarda la collaborazione. Le applicazioni web sono semplicemente applicazioni aziendali localizzate o richiamate tramite protocolli web. Allo stesso modo, i web service eseguono anche funzioni di calcolo da remoto su una rete. Tuttavia, i web service utilizzano protocolli internet con lo scopo specifico di abilitare il coordinamento tra macchina e macchina interoperativa.

I web service sono emersi come soluzione ai problemi associati al calcolo distribuito. Il calcolo distribuito è l'uso di sistemi multipli per eseguire una funzione piuttosto che avere un unico sistema per eseguirla. Le precedenti tecnologie utilizzate nel calcolo distribuito, principalmente CORBA (Common Object Request Broker Architecture) e DCOM (Distributed Component Object Model), presentavano alcune limitazioni. Ad esempio, nessuno dei due ha raggiunto la completa indipendenza dalla piattaforma o un facile trasporto sui firewall. Inoltre, DCOM non è indipendente dal fornitore, essendo un prodotto Microsoft.

Alcune delle esigenze primarie per uno standard di calcolo distribuito erano:

  • supporto multipiattaforma per la comunicazione interna e quella Business to Business;
  • massima concordanza possibile con l'infrastruttura internet esistente;
  • Scalabilità, sia nel numero che nella complessità dei nodi;
  • internalizzazione;
  • tolleranza di fallimento;
  • indipendenza del fornitore;
  • idoneità a richieste banali e non banali.

Nel corso del tempo, i sistemi informativi aziendali sono diventati altamente configurati e differenziati. Ciò ha inevitabilmente reso l'interazione con il sistema estremamente costosa e lunga. Gli sviluppatori hanno allora iniziato a comprendere i vantaggi di standardizzare lo sviluppo dei web service. L'uso degli standard web sembrava essere un passo intuitivo e logico per raggiungere questi obiettivi. Gli standard web fornivano già un mezzo indipendente dalla piattaforma per la comunicazione di sistema e venivano prontamente accettati dagli utenti del sistema di informazione.

Il risultato finale è stato lo sviluppo dei web service. Un web service costituisce un ambiente distribuito, in cui è possibile accedere agli oggetti in remoto tramite interfacce standardizzate. Utilizza un modello a tre livelli, che definisce un fornitore di servizi, un utilizzatore di servizi e un broker di servizi. Ciò consente al web service di essere un rapporto libero, in modo che se un fornitore di servizi fallisce, il broker può sempre indirizzare i consumatori verso un altro. Allo stesso modo, ci sono molti broker e i consumatori possono quindi sempre trovarne uno disponibile. Per la comunicazione, i web service utilizzano standard web aperti: TCP/IP, HTTP e SOAP, quest'ultimo basato su XML.

A livelli superiori potrebbero essere aggiunte tecnologie come XAML, XLANG (supporto transazionale per transazioni web complesse che coinvolgono più web service) e XKMS (lavoro in corso di Microsoft e Verisign per supportare l'autenticazione e la registrazione).

Il protocollo SOAP (Simple Object Access Protocol) è un metodo per inviare informazioni da e verso i web service in un formato estensibile. SOAP può essere utilizzato per inviare informazioni o chiamate di procedure remote codificate come XML. Essenzialmente, SOAP funge da metodo di comunicazione universalmente accettato con i web service. Le aziende aderiscono alle convenzioni SOAP al fine di semplificare il processo di interazione con i web service.

<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP:Header>

  <!-- SOAP header -->

 </SOAP:Header>
 <SOAP:Body SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

  <!-- SOAP body -->

 </SOAP:Body>
</SOAP:Envelope>
 
Struttura SOAP

Un messaggio SOAP può contenere un metodo di richiesta per richiamare un web service, oppure può contenere informazioni di risposta a una richiesta del web service.

L'adesione a questo layout nello sviluppo di web service indipendenti offre notevoli vantaggi alle aziende. A causa del fatto che le applicazioni web sono progettate per essere utilizzate da una miriade di attori, gli sviluppatori vogliono che siano facilmente adottabili. L'utilizzo di standard di comunicazione consolidati e familiari riduce in ultima analisi la quantità di impegno che gli utenti impiegano per interagire in modo efficace con un web service.

Il SOAP Envelope viene utilizzato per definire e organizzare il contenuto contenuto nei messaggi del web service. In primo luogo, il SOAP Envelope serve per indicare che il documento specificato verrà utilizzato per l'interazione di servizio. Contiene un'opzionale SOAP Header e un SOAP Body. I messaggi vengono inviati nel SOAP Body e la SOAP Header viene utilizzata per inviare altre informazioni che non sarebbero previste nel corpo. Ad esempio, se l'attributo SOAP:actor è presente nell'intestazione SOAP, indica chi è il destinatario del messaggio.

Una transazione di web service comporta una richiesta SOAP e una risposta SOAP. L'esempio che utilizzeremo è un web service fornito da Weather.gov. L'input è composto da latitudine, longitudine, una data di inizio, quanti sono i giorni delle informazioni di previsione desiderate e il formato dei dati. La richiesta SOAP sarà simile a questa:

  <?xml version="1.0" encoding="UTF-8" standalone="no"?/>
  <SOAP-ENV:Envelope
      SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
     
     <SOAP-ENV:Body>
        <m:NDFDgenByDayRequest xmlns:SOAPSDK1="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl">
           <latitude xsi:type="xsd:decimal">33.955464</latitude>
           <longitude xsi:type="xsd:decimal">-83.383245</longitude>
           <startDate xsi:type="xsd:date"></startDate>
           <numDays xsi:type="xsd:integer">1</numDays>
           <format>24 Hourly</format>
        </m:NDFDgenByDayRequest>
     </SOAP-ENV:Body>
     
  </SOAP-ENV:Envelope>

Lo startDate è stato lasciato vuoto perché questo otterrà automaticamente i dati più recenti. Il tipo di dati del formato non è definito perché è definito nel documento WSDL.

La risposta SOAP è simile a questa.

  <?xml version="1.0" encoding="UTF-8" standalone="no"?/>
  <SOAP-ENV:Envelope
      SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
     
     <SOAP-ENV:Body>
        <NDFDgenByDayResponse xmlns:SOAPSDK1="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl">
           <dwmlByDayOut xsi:type="xsd:string">.....</dwmlByDayOut>
        </NDFDgenByDayResponse>
     </SOAP-ENV:Body>
     
  </SOAP-ENV:Envelope>

SOAP gestisce i dati codificandoli dal lato del mittente e decodificandoli dal lato del destinatario. I tipi di dati gestiti da SOAP si basano sulla specifica dello schema XML W3C. I tipi semplici includono stringhe, numeri interi, float e doppi, mentre i tipi composti sono costituiti da tipi primitivi.

  <element name="name" type="xsd:string" />
  <SOAP:Array SOAP:arrayType="xsd:string[2]">
     <string>Web</string>
     <string>Services</string>
  </SOAP:Array>

Poiché sono basati sul testo, i messaggi SOAP generalmente non hanno problemi a superare i firewall o altre barriere. Sono il modo ideale per passare informazioni da e verso i web service.

Descrizione del servizio: WSDL

modifica

WSDL (Web Service Description Language) è stato creato per fornire informazioni su come connettersi e interrogare un web service specifico. Questo documento aderisce anche a rigide regole di formattazione e organizzazione. Tuttavia, i metodi, i parametri e le informazioni sul servizio sono specifici dell'applicazione. I web service offrono funzionalità diverse e contengono informazioni indipendenti, ma sono tutti organizzati allo stesso modo. Creando un'architettura standard per questi servizi, gli sviluppatori possono effettivamente richiamarli e utilizzarli con estrema facilità. Per utilizzare un web service, uno sviluppatore può seguire gli standard di progettazione del WSDL per determinare facilmente tutte le informazioni e le procedure associate al suo utilizzo.

In sostanza, un documento WSDL funge da istruzione per l'interazione con un web service. Non contiene alcuna logica applicativa, dando al servizio un livello di autonomia. Ciò consente agli utenti di interagire efficacemente con il servizio senza doverne comprendere il funzionamento interno.

Di seguito è riportato un esempio di file WSDL per un web service che fornisce una temperatura, dato un codice postale statunitense.

<?xml version="1.0"?>
<definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:si="http://soapinterop.org/xsd" xmlns:tns="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
xmlns:typens="http://www.weather.gov/forecasts/xml/DWMLgen/schema/DWML.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" 
targetNamespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl>
 
 <types>
    <xsd:schema targetNamespace="http://www.weather.gov/forecasts/xml/DWMLgen/schema/DWML.xsd">
       <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
       <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
       <xsd:simpleType name="formatType">
          <xsd:restriction base="xsd:string">
             <xsd:enumeration value="24 hourly" />
             <xsd:enumeration value="12 hourly" />
          </xsd:restriction>
       </xsd:simpleType>
       <xsd:simpleType name="productType">
          <xsd:restriction base="xsd:string">
             <xsd:enumeration value="time-series" />
             <xsd:enumeration value="glance" />
          </xsd:restriction>
       </xsd:simpleType>
       <xsd:complexType name="weatherParametersType">
          <xsd:all>
             <xsd:element name="maxt" type="xsd:boolean" />
             <xsd:element name="mint" type="xsd:boolean" />
             <xsd:element name="temp" type="xsd:boolean" />
             <xsd:element name="dew" type="xsd:boolean" />
             <xsd:element name="pop12" type="xsd:boolean" />
             <xsd:element name="qpf" type="xsd:boolean" />
             <xsd:element name="sky" type="xsd:boolean" />
             <xsd:element name="snow" type="xsd:boolean" />
             <xsd:element name="wspd" type="xsd:boolean" />
             <xsd:element name="wdir" type="xsd:boolean" />
             <xsd:element name="wx" type="xsd:boolean" />
             <xsd:element name="waveh" type="xsd:boolean" />
             <xsd:element name="icons" type="xsd:boolean" />
             <xsd:element name="rh" type="xsd:boolean" />
             <xsd:element name="appt" type="xsd:boolean" />
          </xsd:all>
       </xsd:complexType>
    </xsd:schema>
</types>

<message name="NDFDgenRequest">  
   <part name="latitude" type="xsd:decimal"/>
   <part name="longitude" type="xsd:decimal" />
   <part name="product" type="typens:productType" />
   <part name="startTime" type="xsd:dateTime" />
   <part name="endTime" type="xsd:dateTime" />
   <part name="weatherParameters" type="typens:weatherParametersType" />
</message>

<message name="NDFDgenResponse">
   <part name="dwmlOut" type="xsd:string" />
</message>

<message name="NDFDgenByDayRequest">  
   <part name="latitude" type="xsd:decimal" />
   <part name="longitude" type="xsd:decimal" />
   <part name="startDate" type="xsd:date" />
   <part name="numDays" type="xsd:integer" />
   <part name="format" type="typens:formatType" />
</message>

<message name="NDFDgenByDayResponse">
   <part name="dwmlByDayOut" type="xsd:string" />
</message>

<portType name="ndfdXMLPortType">
   <operation name="NDFDgen">
      <documentation> Returns National Weather Service digital weather forecast data </documentation>
      <input message="tns:NDFDgenRequest" />
      <output message="tns:NDFDgenResponse" />
   </operation>
   <operation name="NDFDgenByDay">
      <documentation> Returns National Weather Service digital weather forecast data summarized over either 24- or 12-hourly periods </documentation>
      <input message="tns:NDFDgenByDayRequest" />
      <output message="tns:NDFDgenByDayResponse" />
   </operation>
</portType>

<binding name="ndfdXMLBinding" type="tns:ndfdXMLPortType">
   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
   <operation name="NDFDgen">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgen" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
   <operation name="NDFDgenByDay">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDay" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
</binding>

<service name="ndfdXML">
   <documentation>The service has two exposed functions, NDFDgen and NDFDgenByDay. 
                        For the NDFDgen function, the client needs to provide a latitude and 
                        longitude pair and the product type. The client also needs to provide 
                        the start and end time of the period that it wants data for. For the 
                        time-series product, the client needs to provide an array of boolean values 
                        corresponding to which weather values should appear in the time series product. 
                        For the NDFDgenByDay function, the client needs to provide a latitude and longitude 
                        pair, the date it wants to start retrieving data for and the number of days worth 
                        of data. The client also needs to provide the format that is desired.</documentation>
   <port name="ndfdXMLPort" binding="tns:ndfdXMLBinding">
      <soap:address location="http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php" />
   </port>
  </service>
</definitions>

Il file WSDL definisce un servizio, composto da diversi endpoint, chiamati porte. La porta è composta da un indirizzo di rete e un binding (associazione).

<service name="ndfdXML">
   <documentation>The service has two exposed functions, NDFDgen and NDFDgenByDay. 
                        For the NDFDgen function, the client needs to provide a latitude and 
                        longitude pair and the product type. The client also needs to provide 
                        the start and end time of the period that it wants data for. For the 
                        time-series product, the client needs to provide an array of boolean values 
                        corresponding to which weather values should appear in the time series product. 
                        For the NDFDgenByDay function, the client needs to provide a latitude and longitude 
                        pair, the date it wants to start retrieving data for and the number of days worth 
                        of data. The client also needs to provide the format that is desired.</documentation>
   <port name="ndfdXMLPort" binding="tns:ndfdXMLBinding">
      <soap:address location="http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php" />
   </port>
</service>

Il binding identifica il tipo e il protocollo di binding per ogni operazione. In questo caso, utilizza il binding di tipo Remote Procedure Call, utilizzando SOAP.

   <binding name="ndfdXMLBinding" type="tns:ndfdXMLPortType">
   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
   <operation name="NDFDgen">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgen" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
   <operation name="NDFDgenByDay">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDay" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
</binding>

I tipi di porta (portType) sono raccolte di operazioni astratte. In questo caso, l'operazione è getTemp.

   <portType name="ndfdXMLPortType">
      <operation name="NDFDgen">
         <documentation> Returns National Weather Service digital weather forecast data     </documentation>
         <input message="tns:NDFDgenRequest" />
         <output message="tns:NDFDgenResponse" />
      </operation>
      <operation name="NDFDgenByDay">
         <documentation> Returns National Weather Service digital weather forecast data summarized over either 24- or 12-hourly periods </documentation>
         <input message="tns:NDFDgenByDayRequest" />
         <output message="tns:NDFDgenByDayResponse" />
      </operation>
   </portType>

Infine, i messaggi vengono utilizzati dalle operazioni per comunicare - in altre parole, per passare parametri e valori di ritorno.

   <message name="NDFDgenByDayRequest">  
      <part name="latitude" type="xsd:decimal" />
      <part name="longitude" type="xsd:decimal" />
      <part name="startDate" type="xsd:date" />
      <part name="numDays" type="xsd:integer" />
      <part name="format" type="typens:formatType" />
   </message>

   <message name="NDFDgenByDayResponse">
      <part name="dwmlByDayOut" type="xsd:string" />
   </message>

Dal file WSDL, un utente dovrebbe essere in grado di accedere ai dati in un web service.

Per un'analisi più dettagliata di come questo particolare servizio web, visitare Weather.gov.[1]

Service Discovery: UDDI

modifica

Hai visto come è possibile utilizzare WSDL per condividere le definizioni di interfaccia per i web service; ma anzitutto, come si fa a trovare un web service? Esistono innumerevoli web service indipendenti sviluppati e gestiti da altrettante organizzazioni diverse. Adottando le pratiche e le metodologie del web service, gli sviluppatori hanno cercato di favorire il coinvolgimento e il riutilizzo creativo dei loro sistemi. È così diventato presto chiaro che c'era bisogno di un record numerato di questi servizi e delle rispettive posizioni. Queste informazioni consentono agli sviluppatori di sfruttare le migliori pratiche e i processi dei web service in modo rapido e semplice. Inoltre, disporre di un riferimento centrale delle attuali funzionalità del web service consente agli sviluppatori di evitare lo sviluppo di applicazioni ridondanti.

L'UDDI definisce i registri in cui i servizi possono essere pubblicati e trovati. La specifica UDDI è stata creata da Microsoft, Ariba e IBM. UDDI definisce una struttura dati e API (Application Programming Interface).

Nel modello a tre livelli menzionato prima, UDDI è il broker di servizi. La sua funzione è di consentire ai consumatori di servizi di trovare fornitori di servizi appropriati.

La connessione ai registri UDDI mediante Java può essere eseguita tramite l'API Java per i registri XML (JAXR). JAXR crea uno strato di astrazione, in modo che possa essere utilizzato con UDDI e altri tipi di registri XML, come ad esempio lo standard ebXML.

Utilizzo di Java con i web service

modifica

Per eseguire un messaggio SOAP è necessario utilizzare un'applicazione per comunicare con il fornitore di servizi. Grazie alla sua flessibilità, è possibile utilizzare quasi tutti i linguaggi di programmazione per eseguire il messaggio SOAP. Per i nostri scopi, tuttavia, ci concentreremo sull'utilizzo di Java per interagire con i web service.

L'utilizzo di Java con i web service richiede alcune librerie esterne.

  • Apache SOAP Toolkit
  • Java Mail Framework
  • JavaBeans Activation Framework
  • Parser Xerces XML

Passiamo a utilizzare Java per interrogare il web service di temperatura di cui abbiamo parlato in precedenza.

import java.io.*;
import java.net.*;
import java.util.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.*;
import org.apache.soap.rpc.*;

public class TempClient
{

 public static float getTemp (URL url, String zipcode) throws Exception 
 {

  Call call = new Call ();

  // Service uses standard SOAP encoding
  String encodingStyleURI = Constants.NS_URI_SOAP_ENC;
  call.setEncodingStyleURI(encodingStyleURI);

  // Set service locator parameters
  call.setTargetObjectURI ("urn:xmethods-Temperature");
  call.setMethodName ("getTemp");

  // Create input parameter vector
  Vector params = new Vector ();
  params.addElement (new Parameter("zipcode", String.class, zipcode, null));
  call.setParams (params);

  // Invoke the service ....
  Response resp = call.invoke (url,"");

  // ... and evaluate the response
  if (resp.generatedFault ()) 
  {
   throw new Exception();
  } 
  else 
  {
   // Call was successful. Extract response parameter and return result
   Parameter result = resp.getReturnValue ();
   Float rate=(Float) result.getValue();
   return rate.floatValue();
  }
 }

 // Driver to illustrate service invocation
 public static void main(String[] args)
 {
  try
  {
   URL url=new URL("http://services.xmethods.net:80/soap/servlet/rpcrouter");
   String zipcode= "30605";
   float temp = getTemp(url,zipcode);
   System.out.println(temp);
  }
  catch (Exception e) 
  {
   e.printStackTrace();
  }
 }
}

Questo codice Java nasconde tutto il SOAP all'utente. Richiama l'oggetto target con nome e URL, e imposta il parametro zipcode. Ma come appare la richiesta SOAP sottostante?

  <?xml version="1.0" encoding="UTF-8"?>
  <soap:Envelope xmlns:n="urn:xmethods-Temperature"
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

     <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <n:getTemp>
           <zipcode xsi:type="xs:string">30605</zipcode>
        </n:getTemp>
     </soap:Body>

  </soap:Envelope>

Come vedi, la richiesta SOAP utilizza i parametri passati dalla chiamata Java per compilare la SOAP Envelope e indirizzare il messaggio. Allo stesso modo, la risposta ritorna nel programma Java come "70.0". Anche la risposta SOAP è nascosta dal programma Java.

  <?xml version='1.0' encoding='UTF-8'?>
  <SOAP-ENV:Envelope 
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">

     <SOAP-ENV:Body>
        <ns1:getTempResponse xmlns:ns1="urn:xmethods-Temperature" 
            SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
           <return xsi:type="xsd:float">70.0</return>
        </ns1:getTempResponse>
     </SOAP-ENV:Body>

  </SOAP-ENV:Envelope>

Ecco un ulteriore esempio di utilizzo di Java e SOAP per interagire con i web service. Questo particolare web service è chiamato "US Zip Validator" e prende un codice di avviamento postale (in inglese ZipCode) come parametro, per restituire latitudine e longitudine corrispondenti. Quando si sviluppano applicazioni per interagire con i web service, il primo passaggio dovrebbe essere la revisione del documento WSDL.

Il documento WSDL per questo servizio si trova qui: http://www.webservicemart.com/uszip.asmx?WSDL

Questo documento conterrà tutte le istruzioni necessarie per interagire con il web service "US Zip Validator".

SOAPClient4XG

modifica

Modificato da Duncan McAllister, da: http://www.ibm.com/developerworks/xml/library/x-soapcl/

import java.io.*;
import java.net.*;
import java.util.*;

public class SOAPClient4XG {
    
    public static void main(String[] args) throws Exception {

        args = new String[2];
        
        args[0] = "http://services.xmethods.net:80/soap/servlet/rpcrouter";
        args[1] = "SOAPrequest.xml";
        
        if (args.length  < 2) {
            System.err.println("Usage:  java SOAPClient4XG " +
                               "http://soapURL soapEnvelopefile.xml" +
                               " [SOAPAction]");
				System.err.println("SOAPAction is optional.");
            System.exit(1);
        }

        String SOAPUrl      = args[0];
        String xmlFile2Send = args[1];

		  String SOAPAction = "";

				
        // Create the connection where we're going to send the file.
        URL url = new URL(SOAPUrl);
        URLConnection connection = url.openConnection();
        HttpURLConnection httpConn = (HttpURLConnection) connection;

        // Open the input file. After we copy it to a byte array, we can see
        // how big it is so that we can set the HTTP Cotent-Length
        // property. (See complete e-mail below for more on this.)

        FileInputStream fin = new FileInputStream(xmlFile2Send);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
    
        // Copy the SOAP file to the open connection.
        copy(fin,bout);
        fin.close();

        byte[] b = bout.toByteArray();

        // Set the appropriate HTTP parameters.
        httpConn.setRequestProperty( "Content-Length",
                                     String.valueOf( b.length ) );
        httpConn.setRequestProperty("Content-Type","text/xml; charset=utf-8");
		  httpConn.setRequestProperty("SOAPAction",SOAPAction);
        httpConn.setRequestMethod( "POST" );
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);

        // Everything's set up; send the XML that was read in to b.
        OutputStream out = httpConn.getOutputStream();
        out.write( b );    
        out.close();

        // Read the response and write it to standard out.

        InputStreamReader isr =
            new InputStreamReader(httpConn.getInputStream());
        BufferedReader in = new BufferedReader(isr);

        String inputLine;

        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);

        in.close();
    }

  // copy method from From E.R. Harold's book "Java I/O"
  public static void copy(InputStream in, OutputStream out) 
   throws IOException {

    // do not allow other threads to read from the
    // input or write to the output while copying is
    // taking place

    synchronized (in) {
      synchronized (out) {

        byte[] buffer = new byte[256];
        while (true) {
          int bytesRead = in.read(buffer);
          if (bytesRead == -1) break;
          out.write(buffer, 0, bytesRead);
        }
      }
    }
  } 
}

Questa classe Java fa riferimento a un documento XML (SOAPRequest.xml), che viene utilizzato come messaggio SOAP. Questo deve essere incluso nella stessa cartella del progetto dell'applicazione Java che richiama il servizio.

Dopo aver esaminato il documento WSDL "US Zip Validator", è chiaro che vorremmo richiamare il metodo "getTemp". Queste informazioni sono contenute nel SOAP Body e includono i parametri appropriati.

SOAPRequest.xml

modifica
<?xml version="1.0" encoding="UTF-8"?>
  <soap:Envelope xmlns:n="urn:xmethods-Temperature"
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

     <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <n:getTemp>
           <zipcode xsi:type="xs:string">30605</zipcode>
        </n:getTemp>
     </soap:Body>

  </soap:Envelope>

Dopo un'interazione riuscita, il fornitore di web service fornirà una risposta simile nel formato alla richiesta dell'utente. Quando si sviluppa in NetBeans, eseguire questo progetto ed esaminare la successiva risposta del messaggio SOAP nella finestra di output di Tomcat.

Web service con Netbeans

modifica

La versione di Netbeans utilizzata per questa spiegazione è 5.0.

Dopo l'apertura di Netbeans, fare clic sulla scheda "Runtime" nel riquadro di sinistra, quindi fare clic con il pulsante destro del mouse su "Web Services" e selezionare "Add Web Service". Nel campo "URL", inserisci l'indirizzo del file WSDL del servizio web, nel nostro esempio sopra riportato è "http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" e fai clic su Get Web Service Description. Questo farà apparire le informazioni del servizio web.

  1. http://www.weather.gov/xml/