Quante volte capita di sentirsi chiedere di interfacciare Sme.UP  a dei WebServices messi a disposizione dal cliente o dai fornitori del cliente e vedersi recapitare un malloppo di documentazione sul come interfacciarsi?
La prima domanda che viene spontanea è quella di chiedersi cosa è un WebService (da ora in poi chiamato WS)? Dopodichè altrettanto spontanea è : Posso interfacciarmi con Sme.UP?  Dopo essersi dati la risposta alla domanda precedente la successiva è: Si ok, ma da che parte comincio?

Bene, spero che questo articolo possa dare una spiegazione a tutte queste domande o invitarvi a pensarne altre a cui il laboratorio possa rispondere.

Dubbi e come affrontare la cosa

Cosa stiamo facendo?
Cosa ci sta richiedendo il cliente?
Come trovo le informazioni che mi servono in un mare di documentazione?
Cosa sono i WS?
Come devo muovermi?
Cosa significa interfacciarsi ad un WS?

Tutte domande lecite, che a mio modo di vedere però sono l’insieme di molti più problemi agglomerati che qui cercherò di trattare in maniera indipendente per circoscrivere il problema di una determinata domanda. Questo perchè molte volte le domande in sè, racchiudono già a che livello è il problema. Vediamo ora di analizzare il tutto.

I concetti di base

La prima cosa fondamentale è capire i concetti di fondo! Infatti la prima regola fondamentale è: “Se non capisco le basi sicuramente avrò grossi problemi durante la realizzazione”!

Nel seguente caso il cliente mi sta chiedendo di accedere a dei dati mediante una chiamata al suo WebService.
Ok, fermiamoci. Siamo tutti in grado di capire cosa significhi in primis la parola “WebService” ed in secundis cosa significhi “effettuare una chiamata”?

Se la risposta è negativa rimando ai 2 paragrafetti “Cosa è REST API” e “Struttura di un’applicazione REST API”  descritti qui.
Oppure se qualcuno volesse andare leggermente più a fondo potrebbe servire anche leggere  Web Service REST (e SOAP) con LOA38 oppure Web Service SOAP, WSDL e LOA38.

Dopo aver compreso questo,  vediamo cosa è necessario avere e saper padroneggiare per effettuare una chiamata ad un WS in Sme.UP:

  • Script LOA38 (che serve ad indicare a “Sme.UP” verso chi richiedere (o inviare) i dati e come deve inviare (o riceverli)) :
  • PGM con chiamata £K11 (che è il servizio che conterrà la chiamata vera e propria (mediante utilizzo della /copy £K11) con invio richiesta dati o ricezione dei dati)
  • Gestione della risposta (dato che il WS può rispondere sia in XML che in JSON per questo  serviranno dei parser (può rispondere anche in altro modo, ma non sarà di trattazione in questo articolo) .
    In Sme.UP per il json si usa la /copy £K37 mentre per l’xml la /copy £K19.
    Come spiegato prima, se non si conoscono i concetti, dare uno sguardo a Articolo £K37Documentazione K37 o Documentazione K19

Più avanti vedremo il loro utilizzo. Ora focalizziamoci solo sul comprendere

La Documentazione fornitaci

Dopo aver ben chiaro cosa ci viene richiesto e cosa dobbiamo mettere in gioco per accontentare il cliente è possibile iniziare a vedere come assolvere il problema.
Riportiamo un caso semplice e specifico di richiesta da parte di un nostro cliente per capire come possiamo approcciare il problema.
(N.B: per rispetto della privacy alcune informazioni nel pdf fornitoci sono state oscurate/modificate)

 

Dopo aver letto con attenzione tutto il documento nella mia testa scaturiscono queste osservazioni (e spero non solo nella mia):

  • D: Dato che devo richiamare un WS, qual’è il server ed il servizio sul server che devo richiamare? In che modo devo richiamarlo?
    R: Essendo una chiamata di “richiesta dati semplice” sarà di tipo GET (quindi basterà scrivere in modo corretto la URL), il server da richiamare sarà http://ws.cliente.com/ ed il servizio sul server che ci restituirà i dati sarà http://ws.cliente.com/Api/eventws/chkFascio.
  • D: Ci sono parametri variabili o fissi? In caso quali sono?
    R: In questo caso la documentazione ci viene MOLTO in aiuto perché ci dichiara esplicitamente quali sono i campi richiesti e quali sono quelli obbligatori e quali no. I campi variabili sono “id_fascio” (obbligatorio) e “articolo” (opzionale).
  • D: Come risponde il server (con Json o xml)?
    R: Guardando come è il formato di risposta delle chiamate vedo subito che si tratta di un json. Questo implica che dovrò sicuramente usare un parser json per leggerlo.
  • D: In che modo quindi dovrò richiamare il server?
    R: Anche in questo caso la documentazione ci facilita tantissimo la trasposizione dell’informazione in Sme.UP e le URL che dovrò richiamare sono (in base se viene passato articolo o no):
    http://ws.cliente.com/Api/eventws/chkFascio?id_fascio=<valore>&articolo=<valore>
    oppure
    http://ws.cliente.com/Api/eventws/chkFascio?id_fascio=<valore>
  • D: Come compilo il LOA38? Cosa deve fare il mio servizio per fare la chiamata?
    R: Tutto questo lo vedremo tra poco….

Parallelizzazione e propedeuticità

Nel caso della creazione da zero di un progetto per la fruizione di contenuti di un WS, è possibile parallelizzare il lavoro, stando però attenti alla propedeuticità necessaria agli strumenti.
Infatti avremo questi piccoli vincoli:

  • Prima di poter effettuare delle chiamate (ovvero eseguire il nostro PGM) dovrà essere stato configurato lo script LOA38
  • Prima di poter effettuare delle chiamate (ovvero eseguire il nostro PGM) dovrà essere stato caricato lo script LOA38 nel provider/gateway. Nel provider è necessario il riavvio del provider, mentre nel gateway è sufficiente ricaricare lo script.
  • All’interno dello script LOA38 è necessario conoscere la coda del provider/gateway
  • All’interno del PGM è necessario conoscere lo script del loa38_XX inteso come XX.SEZ.SUB (XX.YYY.ZZZ)

Quindi conoscendo queste restrizioni avremo che solitamente il flusso corretto è:

CREAZIONE PROVIDER/GATEWAY > SCRITTURA LOA38 > CARICAMENTO LOA38 NEL PROVIDER/GATEWAY > SCRITTURA PGM > GESTIONE RISPOSTA

Iniziamo!

Partendo dal fatto che si da per scontato che sia stato preparato un provider/gateway, per prima cosa vediamo come è strutturato un LOA38:

SCRIPT LOA38
Provider Gateway

Vediamo insieme il significato di questi campi:

  • ::A38.SUPPRV
    • DataQ: indica la coda del provider o del gateway che si occuperà di fare la chiamata.
    • Active: (1 o 0) indica se lo script è attivo e quindi in grado di fare una chiamata o è spento.
  • ::SEZ
    • Cod: (XXX) indica il codice univoco di questa sezione in questo preciso script loa38.
    • Txt: testo a piacere per dare un nome alla sezione
  • ::A38.CLSSEZ
    • Class: indica la classe del plugin specifico utilizzato da questa sezione. Nel caso di chiamate LOA38 è impostato fisso a : “com.smeup.wscspi.httpdelegate.HttpDelegatePlugin
    • Log: (Yes o No)
    • Url: indica la URL che verrà composta per l’interrogazione, comprensiva delle parti variabili che vedremo tra poco.
    • HttpMode: (GET o POST o PUT o DELETE) inserire la tipologia di richiesta che dovrà essere effettuata
    • HttpAuth: (none o basic) indica il tipo di autenticazione utilizzato nella richiesta. Tipo basic è se devo inviare USERNAME e PASSWORD, mentre il più comune è lasciare none e gestire l’autenticazione in altro modo.
    • CntGrp: (SOLO NEL GATEWAY) indica il groupId del plugin. Nel caso di chiamate LOA38 è impostato fisso a : “com.smeup
    • CntArt: (SOLO NEL GATEWAY)  indica l’artifact del plugin. Nel caso di chiamate LOA38 è impostato fisso a : “WSCSPI-httpdelegate”
    • CntVer: (SOLO NEL GATEWAY) indica la versione del plugin.
  • ::A38.CNFSEZ
    • Name: (HttpDebug) nome della variabile da impostare per abilitare (o disattivare) la modalità debug del plugin.
    • Value: (true/false) valore della variabile da impostare per abilitare (o disattivare) la modalità debug del plugin.
  • ::SUB
    • Cod: (XXX) indica il codice univoco di questa subsezione in questo preciso script loa38.
    • Txt: testo a piacere per dare un nome alla subsezione
  • ::A38.SUBMET
    • Value: (XXX) Nome del metodo di questo preciso script loa38
    • Txt: testo a piacere per dare un nome al metodo
  • ::A38.SUBVAR
    • Name: indica nome della variabile A38
    • Txt: descrizione della variabile A38
    • TpVar: (Hea o Int) indica la tipologia di variabile. Hea è usata quando bisogna inviare delle variabili dette di Header, mentre Int per variabili [A38.] che sono state usate nella url.
    • DftVal: se si vuole dare un default value alla variabile

 

Nel nostro caso quindi avremo una configurazione di questo tipo, ipotizzando di creare uno script SCP_SET/LOA38_X1 e che la coda del provider sia PRVL01 :

::A38.SUPPRV DtaQ="PRVL01" Active="1" 

::SEZ Cod="001" Txt="Fascio letto da terminale" 
::A38.CLSSEZ Class="com.smeup.wscspi.httpdelegate.HttpDelegatePlugin" Log="Yes" Url="http://ws.cliente.com/Api/eventws/chkFascio?id_fascio=[A38.FASCIO][A38.ARTICOLO]" HttpMode="GET" HttpAuth="none"  

::A38.CNFSEZ Name="HttpDebug" Value="true" 
 
::SUB Cod="001" Txt="Fascio letto da terminale" 
::A38.SUBMET Value="001" Txt="Metodo" 
::A38.SUBVAR Name="FASCIO" Txt="Fascio" TpVar="Int" DftVal="" 
::A38.SUBVAR Name="ARTICOLO" Txt="Articolo" TpVar="Int" DftVal=""

Come è possibile vedere ho pensato di impostare la url così:
http://ws.cliente.com/Api/eventws/chkFascio?id_fascio=[A38.FASCIO][A38.ARTICOLO]
dove [A38.FASCIO] è una variabile di tipo Int (che in questo contesto significa Interno all’Url) e mi sta ad indicare il solo valore del fascio (come da documentazione sarà ad esempio “554”), mentre [A38.ARTICOLO] è una variabile di tipo Int che gestirò a livello di PGM che mi sta ad indicare la stringa ed il valore dell’articolo (come da documentazione sarà ad esempio “&articolo=212D”).
Questo perché ho voluto racchiudere in una sola sezione di script entrambe le chiamate.

Nulla mi vieta di spezzare le 2 chiamate in due sezioni differenti, in quel caso le due url sarebbero semplicemente:

::SEZ Cod=”001″
…Url=”http://ws.cliente.com/Api/eventws/chkFascio?id_fascio=[A38.FASCIO]&articolo=[A38.ARTICOLO]”

::SEZ Cod=”002″
…Url=”http://ws.cliente.com/Api/eventws/chkFascio?id_fascio=[A38.FASCIO]”

In questo caso le variabili [A38.FASCIO] e [A38.ARTICOLO] conterrebbero i soli codici delle variabili (ovvero da documentazione  “554” e “212D”).

NB: Tengo a precisare che in questo caso la chiamata è esente da campi di header perchè la documentazione non li richiedeva. Nel caso avessimo dovuto per esempio fare una chiamata di POST per inviare dei dati (magari un file di json) al WS,  avremmo sicuramente dovuto inserire l’header “Content-Type” che ha un valore fisso che è “application/json”. In questo caso sarebbe bastato inserire nello script in fondo alle variabili anche:

::A38.SUBVAR Name=”Content-Type” Txt=”Contenuto del messaggio” TpVar=”Hea” DftVal=”application/json”.

 

PGM CHIAMATA

Una volta impostato lo script fare un pgm che crea una chiamata con K11 è abbastanza semplice, avremo una cosa di questo tipo

D    §SCRIPTNAME   S  11    INZ('X1.001.001')
D    TXT           S 100    DIM(20) CTDATA PERRCD(1) _NOTXT
[...]
 * Recupero valore variabili
C    EVAL      §FASCIO='554'
C    EVAL      §ARTICOLO='212D'
 * Chiamata a WS
C    CLEAR          £K11S_NM
C    CLEAR          £K11S_VA
C    EVAL      £K11I_FU='SND' 
C    EVAL      £K11I_ME='FIL' 
C    EVAL      £K11I_SB=§SCRIPTNAME
C    EVAL      £K11S_NM(1)='FASCIO'
C    EVAL      £K11S_VA(1)=%TRIM(§FASCIO)
 *
C    IF        §ARTICOLO<>''
C    EVAL      £K11S_NM(2)='ARTICOLO'
C    EVAL      £K11S_VA(2)=%TRIM(TXT)
C    EVAL      £K11S_VA(2)=£G49P('SOS':'SSI':£K11S_VA(2):
                    '<Art>':%TRIM(§ARTICOLO))
C    ELSE
C    EVAL      £K11S_NM(2)='ARTICOLO'
C    EVAL      £K11S_VA(2)=''
C    ENDIF
 *
C    EXSR £K11 

[...]

** TXT
 &articolo=<Art>

NB: Voglio porre particolare attenzione ed enfasi al fatto che se nel LOA38 è stata dichiarata una variabile nel ::A38.SUBVAR anche se dispone già di un default-value o che sia vuota deve comunque essere dichiarata.
Ed è per questo che nell’IF in cui vado a sincerarmi che l’articolo sia stato settato, anche nel caso sia vuoto sono tenuto obbligatoriamente a dichiararlo (vedi £K11S_NM(2)=’ARTICOLO’) ed in questo caso a dargli un valore vuoto (vedi £K11S_VA(2)=”). Nel caso avesse un default-value basterà inserire solo la dichiarazione.

PGM GESTIONE RISPOSTA

Dato che questo WS dichiara di ricevere in risposta un JSON, andremo a salvare la risposta su IFS per poi utilizzare la K37 per andarla a leggere

* Chiamata a WS
[..]
*
C    IF        £K11O_35=*ON
C    LEAVESR
C    ENDIF
 * Salvataggio risposta in IFS
C    EVAL      $FILTEMP='/SMEDOC/UTE/SCIMAM/Test.json'
C    EVAL      £K11I_FU='DAT' 
C    EVAL      £K11I_ME='POS' 
C    EVAL      £K11I_KY=£K11O_KY 
C    EXSR      £K11 
 *
C    DO        *HIVAL 
C    EVAL      £K11I_FU='DAT
C    EVAL      £K11I_ME='LET
C    EXSR      £K11       
C    IF        £K11SO='' OR £K11O_35=*ON
C    LEAVE 
C    ENDIF 
C    EVAL      §RISPOSTA=%TRIM(£K11SO)      
 * scrivo file 
C    EVAL      £G80FU='WRITE' 
C    EVAL      £G80ME='*STMF' 
C    EVAL      £G80PH=%TRIM($FILTEMP)
C    EVAL      £G80ST=§RISPOSTA 
C    EVAL      £G80CP='*DFT' 
C    EVAL      £G80UN='1' 
C    EVAL      £G80EO='*NONE' 
C    EXSR      £G80
[...]
C    CLEAR §RISPOSTA 
C    ENDDO 
C    EVAL £G80FU='CLOSE' 
C    EVAL £G80ME='*STMF' 
C    EVAL £G80PH=%TRIM($FILTEMP) 
C    EXSR £G80 [...]

Utilizziamo quindi ora la K37 per estrarre i dati (ipotizziamo di dover utilizzare “Colata1” “PesoFascio” e “DataReg”) scriveremo quindi:

 [...]
* Estrazione dati da file Json su IFS 
* Colata 1
C    EVAL     £K37I_FU='GET' 
C    EVAL     £K37I_ME='ATR' 
C    EVAL     £K37I_PF=$FILTEMP 
C    EVAL     £K37I_PA='Colata1'
C    EXSR     £K37
C    EVAL    §COLATA=%TRIM(£K37O_AL)
* PesoFascio
C    EVAL    £K37I_FU='GET' 
C    EVAL    £K37I_ME='ATR' 
C    EVAL    £K37I_PF=$FILTEMP 
C    EVAL    £K37I_PA='PesoFascio'
C    EXSR    £K37
C    EVAL    §PFASC=%TRIM(£K37O_NU)
* PesoFascio
C    EVAL    £K37I_FU='GET' 
C    EVAL    £K37I_ME='ATR' 
C    EVAL    £K37I_PF=$FILTEMP 
C    EVAL    £K37I_PA='DataReg'
C    EXSR    £K37
C    EVAL    §PFASC=%TRIM(£K37O_AL)
[...]

 

TEST CHIAMATE

Una volta scritto lo script LOA38 e averlo caricato su un provider o gateway è possibile effettuare delle chiamate di test (senza bisogno di scrivere alcun pgm) per essere sicuri del risultato voluto.
Per fare questo basterà recarsi sulla api della £K11 scrivendo nello spotlight “API £K11”.
Fatto questo recarsi sotto la voce “SIMULAZIONE” per ritrovarsi dinnanzi ad un input-panel dove basterà inserire i dati richiesti dal LOA38 e premere su “CONFERMA” per vedersi rispondere il json di risposta sulla destra in caso positivo o il tipo di errore in caso negativo.