Bitcoins e IBMi / AS400 ? Funzionalità HTTP del DB2 for i da RPG !

0
197

bitcoin-495996_960_720Ecco un bel titolo civetta per portarti a leggere questo Post …

In realtà quello che andiamo a vedere in questo articolo non è una implementazione delle applicazioni Blockchain (la tecnologia che sta dietro al mondo dei Bitcoins e della Cryptocurrency in generale) per IBMi, ma vediamo qualche esempio delle funzionalità HTTP del DB2 for i che ci permettono di  … richiamare un WebService da SQL, salvarne il JSON tornato in un campo Blob del DB … fare il parsing del JSON per estrarne il contenuto.

In particolare presteremo attenzione a:

  • HTTPGETCLOB: Richiamo di un Rest Webservice con ritorno del JSON o XML in un Clob del DB
  • JSON2BSON: Trasformazione del Clob in un Blob
  • JSON_VAL: Per il parsing di un Blob JSON

Personalmente, prima dell’implementazione di queste UDF e UDTF nel DB2 for i ho sempre utilizzato la ottima utility HTTPAPI  del grande Scott Klement (grazie Scott !), ma l’arrivo di queste funzionalità semplifica di molto l’interfacciamento delle nostre applicazioni con i Webservices e quindi vorrei condividere le mie prime esperienze …

Ho fatto qualche test e riporto qui sotto un piccolo sorgente di un programma che chiama un API Rest WebService fornito da BitCoinAverage , salva il JSON ritornato in una temporary table con un campo Blob e ne estrae (JSON Parsing) il contenuto tornando i valori del cambio Bitcoin / Euro richiesto.

Naturalmente si tratta di un esempio … è più probabile che i miei clienti mi chiedano il cambio Euro/Dollaro o qualche altro servizio tipo invio di un SMS, recupero di un CSV, gestione di un file di Google Docs, DropBox o che altro .. ma poi, se non intitolavo Bitcoins e IBMi questo articolo l’avrebbe letto qualcuno ?

 

Vediamo qualche dettaglio:

Funzioni HTTPGETCLOB e JSON2BSON

dcl-proc store_data ;
// Declare cursor in main proc
exec sql
insert into qtemp.jsondata (
Select 'BitCoin-EUR' ,
'/tmp/',
systools.json2bson(json_info) as json_info
From (Values(SYSTOOLS.HTTPGETCLOB(
replace(trim('https://api.bitcoinaverage.com/ticker/EUR/'),
' ','%20'),'')))
x(json_info) );
end-proc;

In questa procedura usiamo le due funzioni HTTP insieme … SYSTOOLS.HTTPGETCLOB richiama il WebService di BitCoinAverage che ritorna un JSON … SYSTOOLS.JSON2BSON trasforma il JSON in un Blob che andiamo a salvare in una temporary table

 

Funzione JSON_VAL

dcl-proc Extract_data ;
exec sql
select
JSON_VAL(JSON_INFO,'24h_avg','f') AS Avg_Rate ,
JSON_VAL(JSON_INFO,'ask','f') AS Ask_Rate,
JSON_VAL(JSON_INFO,'bid','f') AS Bid_Rate,
JSON_VAL(JSON_INFO,'last','f') AS Last_Rate,
JSON_VAL(JSON_INFO,'timestamp','s') AS Timest_String
into
:Avg_Rate,
:Ask_Rate,
:Bid_Rate,
:Last_Rate,
:Timest_String
from qtemp.jsondata
where file_name='BitCoin-EUR';
END-PROC;

In questa procedura vediamo invece la funzionalità JSON_VAL che ci permette di fare il parsing dei valori richiesti.

 

Funzioni HTTP e CCSID e Decimal Point

Per poter utilizzare le funzioni HTTP della Systools bisogna settare il CCSID del job al valore 37 (US) (CHGJOB CCSID(37)) altrimenti vengono tornati degli errori …

Un problema che invece non sono riuscito a risolvere è quello del Decimal Point … essendo su un IBMi in lingua italiana con la virgola come separatore … i valori ritornati da JSON_VAL vengono arrotondati … anche settando  decedit(‘.’) nella specifica H (ctl-opt) o settando in SQL il punto (SET DECPMT=*PERIOD) la cosa non si risolve … probabilmente va impostato qualcosa lato System.propieties di Java … Qualcuno sa come fare ?

 

Conclusioni

Le funzioni HTTP del DB2 for i aprono un mondo di possibilità e semplificano l’interfacciamento del nostro amato IBMi AS400 al resto del mondo … e questo apre le speranze, per chi le avesse perse, sul futuro del IBMi e di chi ci ha sempre lavorato sopra.

 

Sorgente della utility

ctl-opt dftactgrp(*no) decedit('.');
//-------------------------------------------------------
// Test HTTPGETBLOB: Reading Bitcoin Exchange Rate
// via API Rest, JSON, SQL UDF
//-------------------------------------------------
dcl-s Avg_Rate packed(9:2);
dcl-s Ask_Rate packed(9:2);
dcl-s Bid_Rate packed(9:2);
dcl-s Last_Rate packed(9:2);
dcl-s Timest_String varchar(50);
dcl-pr qCmdExc ExtPgm('QCMDEXC');
Cmd char(1000) options(*varsize) const ;
CmdLenn packed(15:5) const ;
END-PR;
DCL-S Cmd char(1000);
// Change CCSID for HTTP Functions
Cmd='CHGJOB CCSID(37)';
qCmdExc(Cmd:%len(Cmd));
// Create a temporary table to store JSON Data
create_temp_table();
// Call Rest API and store JSON data to temp table
store_data();
// Read and parse data from JSON in a BLOB field
extract_data();
// Display some output values
DSPLY Avg_Rate;
// Reset Current JOB to DEFAULT Values
Cmd='CHGJOB CCSID(*USRPRF)';
qCmdExc(Cmd:%len(Cmd));
// Exit
*inlr = *on ;
//---------------------------
// store_data
// Call BitCoinAverage API to retrieve current BitCoin Rate
// and store JSON in my temp table (in a Blob Field)
//---------------------------
dcl-proc store_data ;
// Declare cursor in main proc
exec sql
insert into qtemp.jsondata (
Select 'BitCoin-EUR' ,
'/tmp/',
systools.json2bson(json_info) as json_info
From (Values(SYSTOOLS.HTTPGETCLOB(
replace(trim('https://api.bitcoinaverage.com/ticker/EUR/'),
' ','%20'),'')))
x(json_info) );
end-proc;
//---------------------------
// extract_data
// Extract data from Blob Table, parse JSON for specific values
//---------------------------
dcl-proc Extract_data ;
exec sql
select
JSON_VAL(JSON_INFO,'24h_avg','f') AS Avg_Rate ,
JSON_VAL(JSON_INFO,'ask','f') AS Ask_Rate,
JSON_VAL(JSON_INFO,'bid','f') AS Bid_Rate,
JSON_VAL(JSON_INFO,'last','f') AS Last_Rate,
JSON_VAL(JSON_INFO,'timestamp','s') AS Timest_String
into
:Avg_Rate,
:Ask_Rate,
:Bid_Rate,
:Last_Rate,
:Timest_String
from qtemp.jsondata
where file_name='BitCoin-EUR';
END-PROC;
//---------------------------------
// Create_Temp_Table
// Create a temp table to store JSON Data
// returned from Rest API "call" ....
// Useful to debug this service
//---------------------------------
DCL-PROC Create_Temp_Table;
exec sql
CREATE OR REPLACE TABLE QTEMP.JSONDATA
( FILE_NAME VARCHAR(64) CCSID 1144 NOT NULL,
IFS_COPY_PATH VARCHAR(256) CCSID 1144 NOT NULL,
JSON_INFO BLOB(64K) NOT NULL);
exec sql
delete from qtemp.jsondata
where file_name='BitCoin-EUR' ;
END-PROC;

Referenze

Accessing web services Using IBM DB2 for i HTTP UDFs and UDTFs

MC Press Online – TechTip: Store and Parse JSON Data Natively with DB2 for i