lunedì 27 agosto 2012

Websphere MQ – Come ricevere Files


Questa la richiesta del cliente: “vorrei ricevere un file zip da un mio business partner; devo anche ereditare il nome del file, che deve essere lo stesso che impone il mittente, il tutto tramite Websphere MQ Series”.

Detta così sembra una banalità ma… i due requisiti nascondono qualche insidia.

Il sistema remoto non ha lo stesso sistema di encoding del mio sistema (il sistema remoto è un AIX e utilizza un encoding ASCII  mentre il sistema locale è un i5 con encoding EBCDIC; rischierei di scrivere uno zip file illeggibile o comunque non scompattabile).

L’altro potenziale ostacolo è dovuto al fatto che MQ nasce per veicolare messaggi (stream di bit) ma non di classificarli, attribuendo un nome o un titolo al messaggio o, meglio, esiste la possibilità di identificare il messaggio con un message_id, limitato però ad una lunghezza di 24 bytes, inutilizzabile per il nostro caso.

Decido di partire da questo requirement e trovo che è possibile (dalla Vers.6 di MQ) sfruttare il JMS per veicolare informazioni, in particolare esiste un particolare formato messaggio MQRFH2  che prevede, oltre ai dati del messaggio, un preambolo che trasporta informazioni (coppie key-value) e utilizza xml come contenitore.
Dall'MQ Explorer di window riesco a visualizzare la lista dei messaggi che ho in coda e vedo il formato MQRHF2




Controllando le proprietà del messaggio riesco a vedere le diverse cartelle presenti nell'Header: jms, mcd e usr; mentre le prime due sono ad uso esclusivo di mq la terza (usr) è completmente a disposizione per i dati utente

Utilizzerò quindi la struttura dati MQRHF2 per ricevere il messaggio in modo da circoscrivere la zona contenente le proprietà.

Questa sezione che contiene il valore del CCSID utilizzato per l'encoding delle stringhe xml; differentemente dai messaggi "tradizionali" le stringhe xml possono essere solo unicode, in particolare i ccsid ammessi (impostati dal sender) sono

1200 UCS2 open-ended
1208 UTF8
13488 UCS2 2.0 subset
17584 UCS2 2.1 subset (includes Euro symbol)

Sono quindi obbligato a convertire la stringa da Unicode a Ebcdic, per poter poi effettuare il parsing con una %xml; in questo caso utilizzo la iconv(), funzione del sistema operativo che, dati i puntatori a due stringhe (input e outut) e i ccsid di input e output provvede alla conversione richiesta.
La stringa che ottengo è qualcosa di simile a 
<usr><FileName dt="string">nomedelmiofile.zip</FileName></usr> 





la funzione %xml va a popolare la variabile che poi mi servirà per il salvataggio del file su IFS.


Questa prima MQGet viene effettuata in modalità browse, senza quindi consumare il messaggio (allocando un minimo di spazio per l'header): il motivo è dato dal fatto che devo preventivamente scoprire quanto spazio allocare al messaggio stesso (fino alla 5.4 le variabili possono essere dimensionate fino a 64k).

Una volta scoperta quindi la lunghezza del messaggio posso effettuare la MQGET in modalità input, che consuma effettivamente il messaggio, allocando preventivamente la quantità di memoria necessaria al messaggio.
con poche istruzioni imposto il CCSID del contenuto del messaggio (819) e alloco memoria  al puntatore.



Ora si tratta solamente di scrivere il file nell'IFS:

cancello eventualmente il file se preesistente e ne creo uno vuoto.

L'ultima istruzione di scrittura provvede a far coincidere il puntatore del file col puntatore dello stream scaricato da mq: in questo modo la scrittura genera un file a immagine del messaggio ricevuto


Da non dimenticare l'istruzione di deallocazione della memoria: dealloc Buffer_SBCS_


1 commento: