05 - Web Services05a - Varie Web Service con IBM i

Consumare web services REST con autenticazione basic

Capita sempre più spesso di imbattersi nella richiesta di dover gestire integrazioni anche spinte con altre applicazioni, installate potenzialmente su qualsiasi tipo di piattaforma. Da un lato questo genere di attività spaventa molto perché siamo tutti abituati a gestire localmente sul nostro server preferito qualunque esigenza nota e demandare a terzi o ad altri linguaggi il problema ma ahimè (anzi per fortuna!) ormai i sistemi informativi delle aziende non si basano unicamente su un solo server e sempre più utilizzano anche sistemi ibridi con parte delle applicazioni eseguite localmente ed altre distribuite nella nuvola o in siti remoti. Nessun problema possiamo gestire le esigenze più disparate. In questo articolo vediamo come chiamare un servizio web utilizzando RPG e gestendo il risultato (positivo o negativo) della chiamata.

Introduzione

Un buon metodo per colloquiare con questo ecosistema eterogeneo è utilizzare i servizi web (web services). Infatti con un unico protocollo (http/https) riusciamo a fare ciò che in precedenza dovevamo gestire con connessioni tra DB, file di testo, file semaforo o peggio ancora con librerie di files “di frontiera“. Un ulteriore grandissimo vantaggio dell’utilizzo dei web services è la sincronia: quando il client consuma un servizio remoto contatta un componente sw che risiede sul server e nel momento esatto della chiamata conosce la risposta. Il sistema operativo infatti gestisce tutto il colloquio tra client e server quindi è in grado di segnalare problemi di comunicazione, autenticazione, … In questo modo potenzialmente potrei inserire una chiamata ad un servizio perfino interattivamente comunicando all’utente il dato chiesto ad un’applicazione sita dall’altra parte del globo o notificandolo del fatto che l’applicazione contattata per avere il dato non risponde.

Esempio

Vediamo ora un esempio di come il linguaggio RPG è in grado di generare una chiamata ad un servizio utilizzando un’autenticazione HTTP di tipo basic e gestire il risultato della chiamata che potrebbe essere XML o JSON. Prima di tutto occorre avere l’url (variabile myUrl) da contattare e le credenziali per l’autenticazione (variabile myLogin) in formato utente:password.

Per prima cosa definiamo le variabili che utilizzeremo in questo esempio.

D myClob          S                   SQLType(CLOB:1000000) inz;    
D myData          S          30000A   varying       
D myHeader        S           1000A   varying       
D myLogin         S            200A   varying       
D myLoginBase64   S            200A   varying       
D myUrl           S            300A   varying     

Adesso generiamo la stringa contenente le credenziali codificata in base64 utilizzando una funzione messa a nostra disposizione da IBM nella libreria SYSTOOLS.

myLogin = 'petris:passW0rdS3gr3t4';

SQL_query = 'SELECT SYSTOOLS.BASE64ENCODE(CAST('''+ %trim(myLogin) + ''' AS VARCHAR(200) CCSID 1208)) FROM SYSIBM.SYSDUMMY1';

exec sql PREPARE SQL_statement FROM :SQL_query;

DECLARE SQL_cursor CURSOR FOR SQL_statement;

OPEN SQL_cursor;

FETCH NEXT FROM SQL_cursor INTO :myLoginBase64;

CLOSE SQL_cursor;

Qualora riceveste l’errore SQL0332 relativa alla conversione di caratteri è possibile che il Vostro job stia girando con parametro CCSID(65535). Per rivolvere Vi basterà modificare il valore di questo parametro prima che giri la query ed al limite modificandolo al contrario successivamente.

A questo punto popoliamo una variabile stringa con testo xml che utilizzeremo per passare al server le nostre credenziali di accesso

myHeader = '<httpHeader><header name="Authorization" value="Basic ' + %trim(myLoginBase64) + '"/></httpHeader>';

Non ci resta che eseguire la chiamata utilizzando un’altra funzione contenuta nella libreria SYSTOOLS e verificare la risposta del server:

myUrl = 'http://nnn.nnn.nnn.nnn:nnnn/reports/report?id=KJFD556XDS';

// chiamata ws con autenticazione
exec sql SELECT SYSTOOLS.HTTPGETCLOB(:myUrl, :myHeader) INTO :myClob FROM SYSIBM.SYSDUMMY1;

// chiamata ws senza autenticazione
 exec sql SELECT SYSTOOLS.HTTPGETCLOB(:myUrl, '') INTO :myClob FROM SYSIBM.SYSDUMMY1;

// gestione del risultato 
myData = %subst(myClob_data:1:myClob_len);
exsr parseMyData;   

// la routine parseMyData potrà utilizzare la funzione JSON_TABLE in caso il risultato sia restituito in formato JSON, 
// diversamente potrà utilizzare la built-in function xml-into per gestire dati in formato xml

Conclusione

In questo caso ho chiamato un report del mio prodotto di Business Intelligence al termine di una elaborazione del mio gestionale per fare in modo che i dati del report vengano aggiornati non appena il calcolo è finito ma lo stesso concetto lo posso applicare per qualsiasi altra necessità.

Nel mio caso un esempio di risposta potrà essere: {“Status”: 200,”Text”: “Report updated successfully”}

Che la chiamata si chiuda con successo o meno la struttura del messaggio rimarrà invariata (cambieranno solo i valori di Status e Text) e mi gestirò il risultato con la funzione JSON_TABLE. Nel caso in cui la comunicazione non vada a buon fine o l’indirizzo sia errato o ancora l’autenticazione non non si completi ci penserà il motore SQL a notificarmi il problema riscontrato (es. codice SQL4302). A quel punto basterà recuperare il testo del messaggio dal file messaggi QSQLMSG ed il gioco è fatto.

In questo esempio il sistema restituisce un errore HTTP 401 ma il motore gestisce una qualsiasi risposta con un qualsiasi messaggio. Il dettaglio dei codici errore HTTP si può trovare su wikipedia ( https://it.wikipedia.org/wiki/Codici_di_stato_HTTP)

About author

Head of Application development & Systems integration da sempre lavoro su "i". Programmatore, analista, project manager, sistemista, ... tanti cappelli ma un'unica piattaforma preferita. Collaboro con la community FAQ400 perchè credo fermamente nel lavoro di squadra e auspico una crescita continua e costante dell'ecosistema di cui mi sento parte.

1 Comment

Rispondi a Danilo Cussini Annulla risposta

%d blogger hanno fatto clic su Mi Piace per questo: