In questo articolo mi occuperò di descrivere la procedura per creare un Web Service client SOAP in Java.  Mi rivolgo quindi principalmente a sviluppatori Java che vogliano avvicinarsi a questo tipo di architettura e realizzare un’applicazione che si interfacci con un webservice esposto da altri sistemi software.

Come forse molti di voi sanno, Sme.UP ERP mette a disposizione degli strumenti per interrogare dei webservice. Il “ponte” dal server applicativo a questi webservice è Sme.UP Provider, che tramite dei plugin scritti in Java, si interfaccia e si occupa di tutta la comunicazione. Il cuore di questi plugin è il Web Service Client, di cui parlerò in questo articolo.

Per approfindire invece il verso contrarario, cioè esporre un webservice con Sme.UP ERP, per rendere disponibili dati del gestionale al mondo esterno, vi rimando all’articolo sul LOA39, che parla proprio di questo argomenti.

 

Definizioni

Partirò prima di tutto con qualche definizione necessaria per inquadrare l’argomento.

 

Cos’è un Web Service

Un Web Service è un sistema software designato a supportare interazioni macchina-macchina su una rete.

Precedentemente su questo blog si è parlato di Web Service, precisamente nell’articolo “Web Service in Sme.UP ERP” in cui ci si soffermava principalmente sull’architettura di tipo REST.

In questo articolo invece mi occuperò di Web Service di tipo SOAP (Simple Object Access Protocol).

 

Cos’è il protocollo SOAP

Il SOAP è un protocollo per lo scambio di messaggi tra componenti software che avviene secondo le regole della sintassi XML. Un Web Service di tipo SOAP si caratterizza per avere un’interfaccia descritta in un formato elaborabile da una macchina (specificamente WSDL) per far sì che gli altri sistemi interagiscano nel modo prescritto dalla sua descrizione usando messaggi SOAP, tipicamente convogliati usando HTTP.

Un messaggio SOAP è strutturato da un header ed un body.

 

Il segmento header è facoltativo e contiene meta-informazioni quali ad esempio il routing, la sicurezza, le transazioni e parametri richiesti da una procedura.

Il segmento body, invece, è obbligatorio e trasporta il contenuto informativo. Questo deve seguire uno schema definito dall’XML Schema.

Con il termine SOAP Envelope identifichiamo il documento XML che contiene il messaggio SOAP in tutte le sue componenti.

 

Cos’è un WSDL

Il Web Services Description Language (WSDL) è un documento XML in grado di descrivere le funzioni e i parametri di un Web Service. Questo documento è quindi una descrizione di come interagire con il servizio in questione ed è quindi usato per la creazione dei client dei servizi web.

Java mette a disposizione delle API JAX-WS (Java API for XML Web Services) che semplificano lo sviluppo delle applicazioni attraverso il supporto di un modello standard, annotation-based, per sviluppare Web Service application e client. Lo strumento wsimport, supportato da JAX-WS, elabora il file wsdl e genera le risorse java necessarie per creare un client di servizi Web.

 

Creazione di un client SOAP

Entriamo quindi nel merito dell’articolo: partiremo dal seguente wsdl di esempio ping.wsdl e creeremo le classi java con il comando wsimport.

<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns:tns="http://com/ibm/was/wssample/sei/ping/"

xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="PingService"

targetNamespace="http://com/ibm/was/wssample/sei/ping/">

<wsdl:types>

<xsd:schema

targetNamespace="http://com/ibm/was/wssample/sei/ping/"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="pingStringInput">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="pingInput" type="xsd:string" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>

</wsdl:types>

<wsdl:message name="pingOperationRequest">

<wsdl:part element="tns:pingStringInput" name="parameter" />

</wsdl:message>

<wsdl:portType name="PingServicePortType">

<wsdl:operation name="pingOperation">

<wsdl:input message="tns:pingOperationRequest" />

</wsdl:operation>

</wsdl:portType>

<wsdl:binding name="PingSOAP" type="tns:PingServicePortType">

<soap:binding style="document"

transport="http://schemas.xmlsoap.org/soap/http" />

<wsdl:operation name="pingOperation">

<soap:operation soapAction="pingOperation" style="document" />

<wsdl:input>

<soap:body use="literal" />

</wsdl:input>

</wsdl:operation>

</wsdl:binding>

<wsdl:service name="PingService">

<wsdl:port binding="tns:PingSOAP" name="PingServicePort">

<soap:address

location="http://localhost:9080/WSSampleSei/PingService" />

</wsdl:port>

</wsdl:service>

</wsdl:definitions>

Copiare questo file in un editor di testo e salvarlo con il nome ping.wsdl in una directory prescelta che chiameremo per convenzione mytemp.

Lanciare il comando wsimport da riga di comando partendo dalla cartella mytemp e passandogli come unico parametro obbligatorio la posizione del wsdl. Questo parametro può essere sia un percorso locale sia un URI.

Nel nostro caso il comando di esecuzione può avere il seguente schema:

cartella_installazione_jdk\bin\wsimport -keep ping.wsdl

Dove    -keep specifica se conservare i file di origine generati.

Dopo aver generato i file di modello dal comando wsimport, nella mytemp vengono generati i seguenti file:

com\ibm\was\wssample\sei\ping\ObjectFactory.java

com\ibm\was\wssample\sei\ping\package-info.java

com\ibm\was\wssample\sei\ping\PingServicePortType.java

com\ibm\was\wssample\sei\ping\PingService.java

com\ibm\was\wssample\sei\ping\PingStringInput.java

Tra queste classi dovremo identificare la classe che implementa l’interfaccia client che tipicamente conterrà l’annotazione javax.xml.ws.WebServiceRef con l’attributo wsdlLocation che specifica l’URI del documento WSDL. Questa interfaccia avrà un metodo per richiamare il proxy attraverso il quale si potrà invocare il metodo di comunicazione.

Nel nostro caso specifico la classe di chiama PingService. Quindi per creare un client basterà:

  1. creare un progetto java;
  2. includere nel progetto le classi create dal wsimport;
  3. creare una classe contenente un main;
  4. creare un’istanza della classe PingService;
  5. richiamare il metodo getPingServicePort() per ottenere il proxy;
  6. lanciare il metodo di comunicazione pingOperation();

Abbiamo così creato il nostro primo client SOAP in java. Facile no? 😊

 

Per saperne di più…

Come approfondimento vorrei parlarvi di due strumenti che mi sembrano di importanza rilevante soprattutto nell’ottica dell’integrazione del Client con le tecnologie fornite da Sme.UP ERP: la libreria JAXB e l’interfaccia SOAPHandler.

 

Libreria JAXB

JAXB è una tecnologia di bind XML-Java che consente la trasformazione tra schemi e oggetti Java e tra documenti istanza XML e istanze di oggetti Java. La tecnologia JAXB è composta da un’API di runtime e da strumenti associati che semplificano l’accesso a documenti XML. È possibile utilizzare gli strumenti e le API JAXB per stabilire associazioni tra classi Java e schemi XML. Uno schema XML definisce gli elementi di dati e la struttura di un documento XML. La tecnologia JAXB fornisce un ambiente di runtime che consente di convertire i propri documenti XML in oggetti Java e viceversa. Per accedere ai dati memorizzati in un documento XML, non è necessario comprenderne la struttura.

È possibile generare classi Java interamente annotate da un file XML Schema utilizzando il compilatore schema JAXB, lo strumento della riga comandi xjc. Utilizzare lo strumento del compilatore schema xjc per cominciare con una definizione schema XML (XSD) per creare una serie di JavaBeans associati ad elementi e tipi definiti nello schema XSD. Una volta presente la mappatura tra lo schema XML e le classi Java, i documenti dell’istanza XML possono essere convertiti in e da oggetti Java tramite l’API di runtime del collegamento JAXB. Le classi Java annotate risultanti contengono tutte le informazioni necessarie richieste dal runtime JAXB per analizzare l’XML per il marshaling e l’annullamento del marshaling. È possibile utilizzare le classi JAXB risultanti in applicazioni JAX-WS (Java API for XML Web Services) o nelle proprie applicazioni Java non JAX-WS per l’elaborazione dei dati XML.

 

Interfaccia SOAPHandler

Questa interfaccia è fondamentale per modificare il messaggio SOAP in uscita, ad esempio inserendo le credenziali di accesso nell’header, e per catturare il messaggio in entrata. Per associare un SOAPHandler all’istanza del Service, basterà seguire i seguenti passaggi:

  1. creare una classe MySOAPHandler che implementi l’interfaccia SOAPHandler;
  2. creare una seconda classe MyHandlerResolver che implementi l’interfaccia HandlerResolver;
  3. MyHandlerResolver dovrà implementare il metodo getHandlerChain nel quale verrà istanziata la classe MySOAPHandler e aggiunta all’handlerChain come segue:
     MySOAPHandler sh = new MySOAPHandler ();
    
     handlerChain.add(sh);
  4. All’istanza del Service fare un set dell’HandlerResolver. Riprendendo l’esempio precedente:
     PingService ps = new PingService();
    
     MyHandlerResolver hr = new MyHandlerResolver();
    
     setHandlerResolver(hr);

In questo modo nel metodo handleMessage implementato dalla classe MySOAPHandler sarà possibile manipolare il messaggio SOAP in uscita o salvarsi il messaggio di risposta.

@Override
public boolean handleMessage(SOAPMessageContext smc) {

   Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
   SOAPMessage message = smc.getMessage();

   if (outboundProperty.booleanValue()) {

//sono in uscita posso gestire il messaggio SOAP

      try {
         SOAPHeader header = message.getSOAPHeader();

//     to do modificare l’header ad esempio con credenziali di accesso

      } catch (Exception e) {
         e.printStackTrace();
      }

   } else {

//sono in entrata, stampo in console il messaggio

      try {
         message.writeTo(System.out);
      } catch (Exception ex) {
         ex.printStackTrace();
      }

   }
   return outboundProperty;
}

L’importanza di questo handler verrà ulteriormente approfondita nel prossimo articolo in cui tratterò l’integrazione di un Web Service Client con le tecnologie offerte da Smeup ERP.