AS400 legge tutti i database

Un AS400 per domare tutti i database

Proprio così, an AS400 to rule them all, dove “them” sono tutti i database relazionali che hanno un driver JDBC che, come spiegherò in seguito, possiamo utilizzare persino con il linguaggio RPG.

Alzi la mano chi lavora su IBM i / AS400 e ha avuto la necessità, almeno una volta, di utilizzare un database relazionale esterno (MySQL, PostgreSQL, Oracle, Microsoft SQL Server, etc). A me è capitato moltissime volte e immagino sia lo stesso per altri.

Le necessità sono varie:

  • migrazione da o verso un altro ERP
  • aggiornare un database esterno ad esempio quello di una soluzione di Business Intelligence esterna all’AS400
  • leggere informazioni dal database di un’applicazione esterna (esempio una webapp) da elaborare nel proprio ERP su AS400
  • etc

Anche le modalità per farlo sono varie:

  • web services
  • soluzioni ETL (Extract Tansform Load), come ad esempio Pentaho Data Integration, sviluppando e schedulando i job che leggono le informazioni dai database esterni e le scrivono in tabelle su AS400 o viceversa
  • accesso diretto dall’AS400!!!

Quest’ultima è la modalità di cui voglio scrivere in quest’articolo, ovvero la possibilità di accedere a database esterni all’AS400 tramite driver JDBC usando SQL e, udite udite, il vecchio “obsoleto” e tanto caro RPG.

Per far questo ci viene in aiuto il tool AppServer4RPG di Dieter Bender, che ci permette di utilizzare direttamente dall’AS400 qualunque database abbia un driver JDBC, ovvero quelli già citati prima: MySQL, MariaDB, PostgreSQL, Oracle, Microsoft SQL Server, DB2 e tanti altri.

Nell’esempio che descrivo di seguito accedo da un AS400 in Italia al database PostgreSQL presente su un server Linux in Francia.

Configurazione AppServer4rpg

Innanzitutto bisogna scaricare e decomprimere appserver4rpg.

Spostare sull’AS400 via FTP il file jvagate.savf e ripristinare la libreria JVAGATE dal SAVF col comando RSTLIB.

Rinominare la cartella precedentemente decompressa con il nome JVAGATE quindi spostarla nella root dell’IFS dell’AS400: /JVAGATE (ATTENZIONE: se avete la necessità di darle un altro nome basta che lo indichiate nell’area dati AS4RPGPATH della libreria precedentemente ripristinata).

Copiate in /JVAGATE/lib/ tutti i driver JDBC che vi servono (se non li avete cercateli e scaricateli da internet). Nel mio caso ho scaricato e copiato il driver JDBC di PostgreSQL: postgresql-42.1.1.jar

A questo punto bisogna modificare il file di configurazione /JVAGATE/conf/global.properties per indicare i riferimenti di ogni database esterno da raggiungere.

Nel mio caso ho aggiunto i riferimenti del mio database PostgreSQL:

ard.url.PGDWS=jdbc:postgresql://xxx.xxx.xxx.xxx:5432/dws
ard.driver.PGDWS=org.postgresql.Driver

dove

  • PGDWS: è il nome di fantasia che utilizzerò successivamente nel comando ADDRDBDIRE
  • url: è la stringa di connessione al database in cui “xxx.xxx.xxx.xxx” va sostituito con l’IP o l’hostname del database server e dws è il nome del database a cui voglio connettermi
  • driver: è l’indicazione di quale driver utilizzare per la connessione (quello riferito al JDBC driver precedentemente copiato nel percorso /JVAGATE/lib/)

I parametri sopra descritti sono quelli essenziali per definire la connessione, ma, oltre ad essi, si possono aggiungere altri parametri facoltativi. Tra questi ne segnalo due:

ard.properties.PGDWS.user=mIo-UtentE
ard.properties.PGDWS.password=Mia-PassWord

Questi due parametri ci permettono di definire l’utente e la password con cui viene fatta la connessione al database. Indicandoli nel file global.properties si evita di indicarli ad ogni connessione fatta da STRSQL o da RPG, ma soprattutto permettono di aggirare il problema delle connessioni con utente minuscolo. In pratica, quando viene fatta la CONNECT al database, l’AS invia sempre l’utente in MAIUSCOLO anche se lo indicate minuscolo (compreso indicarlo tra apici). In questo caso l’unico modo che ho trovato per aggirare il problema è indicare l’utente all’interno del file di configurazione global.properties.

Avviare il servizio su AS:

SBMJOB CMD(CALL PGM(JVAGATE/STRJVAGATE)) JOB(JVAGATE) JOBQ(QCTL)

ATTENZIONE: se si aggiunge un nuovo database al file global.properties o un nuovo JDBC driver è necessario riavviare il servizio su AS400.

Infine si aggiunge una voce all’indirizzario RDB che si riferisca a quanto configurato nel precedente file:

ADDRDBDIRE RDB(PGDWS) RMTLOCNAME(*ARDPGM) ARDPGM(JVAGATE/JDBCGATE)

Finalmente si può accedere al database esterno

Test con STRSQL

Accesso diretto tramite il tool STRSQL dell’AS400.

Connessione al database:

CONNECT TO PGDWS USER mio-utente USING 'Mia-PassWord'

ATTENZIONE: come descritto in precedenza, se l’utente del database è minuscolo, vi darà errore di connessione perchè l’AS lo passa sempre in maiuscolo. In questo caso dovete indicare utente e password all’interno del file di configurazione global.properties e di conseguenza non è necessario specificarli nell’istruzione CONNECT.

Esecuzione di qualunque istruzione SQL, ad esempio:

select id_zona3, cod_zona3, desc_zona3
from zone
where cod_zona3 like 'IT%'
limit 100;

risultato:

SQL AS400

Disconnessione dal Database

rollback
DISCONNECT CURRENT

Test con RPG

Ora vediamo come accedere al database esterno direttamente da un programma RPG.

Il sorgente dev’essere ovviamente di tipo SQLRPGLE.

Di seguito il sorgente di un semplice esempio in cui ci si connette al database e si legge una tabella con SQL:

H DECEDIT('0,') DATEDIT(*DMY.)                                   
*--------------------------------------------------------------*
D sql_stm         S         32700                              
*                                                              
D S_ID           S             9 0 INZ                        
D S_COD           S             6   INZ                        
D S_DESC         S             40   INZ                        
*                                                              
D USR             S             10   inz('mio-utente')              
D PWD             S             10   inz('Mia-PassWord')          
*--------------------------------------------------------------*
/free                                                          
  Exec Sql CONNECT TO PGDWS USER :USR USING :PWD;              
                                                               
  sql_stm = 'select +                                          
    id_zona3, cod_zona3, desc_zona3 +                          
    from zone +                                            
    where cod_zona3 like ''IT%'' +                            
    limit 20';                                                
                                           
  Exec Sql Prepare SPG from :sql_stm;    
  Exec Sql Declare CPG cursor for SPG;    
                                           
  Exec Sql Open CPG;                      
/end-free                                  
*                                          
C                   DO       *HIVAL        
C/EXEC SQL                                  
C+ FETCH CPG INTO :S_ID, :S_COD, :S_DESC    
C/END-EXEC                                  
C                   if       SqlCod<>0    
C                   leave                  
C                   endif                  
*                                          
/free                                      
    // mostro le info lette dal DB esterno
    dsply ('ID:     ' + %char(S_ID));      
    dsply ('Codice: ' + %char(S_COD));    
    dsply ('Desc.: ' + %char(S_DESC));    
    dsply ('---------------------------------------');            
/end-free                                                        
*                                                                
C                   ENDDO                                          
*                                                                
/free                                                            
  Exec Sql Close CPG;                                            
  Exec Sql ROLLBACK;                                            
  Exec Sql DISCONNECT CURRENT;                                  
/end-free                                                        
C                   SETON                                       LR
*--------------------------------------------------------------*      

ATTENZIONE: compilare il sorgente con le seguenti opzioni:

  • COMMIT(*CS)
  • OPTION(*SQL)

Risultato dell’esecuzione:

RPG AS400

Altri esempi li ha forniti il buon Dieter Bender nella cartella JVATEST.LIB che trovate nel file decompresso all’inizio.

Note particolari

Logging

Questo tool genera log molto verbosi in /JVAGATE/logs/. Di default genera un file log per ogni giorno e NON elimina i file dei giorni precedenti. Se lo utilizzate in modo massiccio vi troverete presto con GigaByte di log.

Per evitare questo problema si possono introdurre delle politiche di Log Rotation un po’ più stringenti modificando il file di configurazione /JVAGATE/conf/log4j.properties.

Commentare le due istruzioni indicate sotto e aggiungere le nuove istruzioni con le vostre preferenze:

...
# VERSIONE ORIGINALE (genera un file di log per ogni giorno ... SENZA LIMITI)
#log4j.appender.MeinDaRoFiAppender=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.MeinDaRoFiAppender.datePattern='.'yyyy-MM-dd
# Versione con Log Rotation basato sulla dimensione e con numero di file limitato
log4j.appender.MeinDaRoFiAppender=org.apache.log4j.RollingFileAppender
log4j.appender.MeinDaRoFiAppender.MaxBackupIndex=20
log4j.appender.MeinDaRoFiAppender.MaxFileSize=10MB
...

dove:

  • MaxBackupIndex indica il numero massimo di file di log da tenere
  • MaxFileSize indica la dimensione massima di ogni file

quindi, con i parametri sopra indicati, i log occuperanno al massimo 10MB per 20 file, ovvero 200MB.

Proprietà STRSQL

Quando ci si connette ad un database esterno usando STRSQL viene automaticamente modificato un attributo della sessione, Convenzione di denominazione, che da *SYS diventa *SQL. Questo fa si che quando vi disconnettete e provate ad usare l’SQL con le altre tabelle dell’AS400 si comporterà in modo diverso da come siete abituati, ad esempio, non vedrà più la lista librerie, quindi se fate una SELECT senza specificare la libreria cercherà la tabella in una libreria con nome uguale al nome dell’utente (ulteriori dettagli sulle differenze tra SYS e SQL li potete trovare spiegati bene qui: https://blog.faq400.com/it/database-db2-for-i/naming-sys-vs-sql/).

Per ripristinare l’impostazione standard è sufficiente premete F13, scegliete l’opzione 1. Modifica attributi sessione e ripristinare la convenzione *SYS come da immagine seguente:

Conclusione

Come avrete intuito leggendo l’articolo, l’accesso ad un database relazionale esterno tramite driver JDBC è semplicissimo anche dall’AS400. Non resta che sfruttarlo 😉

Un ringraziamento particolare va a Dieter Bender che ha sviluppato questo comodo tool e l’ha rilasciato sotto licenza open-source GPLv2. Thanks Dieter.

(Letto 939 volte di cui 60 negli ultimi 30gg)
twitterlinkedinmailby feather

13 thoughts on “Un AS400 per domare tutti i database

  1. Buongiorno, vorrei utilizzare questa soluzione per accedere a un database MySql versione 8 con utente “produzione”, ma l’istruzione CONNECT TO non funziona perchè il primo carattere è minuscolo. Ho fatto e rifatto tutti i passaggi dell’articolo, ma senza risultati. Qualche suggerimento? Grazie.

    1. Ciao Renato,

      hai provato ad indicare le seguenti proprietà nel file /JVAGATE/lib/global.properties?

      ard.properties.XXXXX.user=mIo-UtentE
      ard.properties.XXXXX.password=Mia-PassWord

      dove “XXXXX” è il nome che hai dato al tuo database nel comando ADDRDBDIRE.

      Come spiegato sopra, servono proprio quando l’utente contiene delle minuscole.
      Indicando le credenziali nel file delle proprietà, NON serve indicarlo quando fail la CONNECT. Quindi la tua CONNECT diventa semplicemente:


      CONNECT TO XXXXX

      ciao

  2. L’installazione mette il file global.properties nella cartella /JVAGATE/CONF; bisogna copiarlo in /JVAGATE/LIB. Grazie per la risposta.

  3. Buongiorno. Da STRSQL funziona tutto, sia select, che insert into, che update che delete. Da RPG non riesco a fare nulla, non ricevo nessun errore, nulla. Ho provato a vedere il log ArdGateLog.log ma non riesco a vederci nulla.
    Potete aiutarmi? Grazie

    1. Ciao Renato,

      hai compilato il tuo RPG con i parametri COMMIT(*CS) OPTION(*SQL) ?

      Controlla anche il JOBLOG della sessione da cui richiami il programma perchè dovrebbe comunque darti degli errori SQL se non riesce ad eseguire le istruzioni che tu gli hai dato

  4. Buogiorno, complimenti per l’articolo davvero molto interessante.
    Devo leggere tabelle Microsoft SQL Server da AS400.
    Sul sitema AS400 ho già trovato installata la procedura.
    Ho trovato il file global.properties nella cartella /JVAGATE/CONF,
    Devo copiarlo e/o spostarlo in /JVAGATE/LIB?
    Grazie

  5. Salve,
    nel file global. properties ho inserito le seguenti righe:
    ard.url.PGDWS=jdbc:sqlserver://XXX.XXX.XXX.XXX/Testate
    ard.driver.PGDWS=com.microsoft.sqlserver.jdbc.SQLServerDriver
    ard.url.PGDWS=jdbc:sqlserver://XXX.XXX.XXX.XXX/Righe
    ard.driver.PGDWS=com.microsoft.sqlserver.jdbc.SQLServerDriver
    sono corrette?
    Dal sito Microsoft ho scaricato i seguenti driver:
    mssql-jdbc-8.4.1.jre8.jar
    mssql-jdbc-8.4.1.jre11.jar
    mssql-jdbc-8.4.1.jre14.jar
    Per fermare il servizio è sufficiente terminare il lavoro nel sottosistema?
    La stringa di connessione da riga comando?
    CONNECT TO PGDWS USER mio-utente USING ‘Mia-PassWord’
    Grazie infinite.

    1. Le stringhe relative all’URL non mi sembrano corrette per MS Sql Server.
      Dovrebbero essere qualcosa di simile a:

      jdbc:jtds:sqlserver://xxx.xxx.xxx.xxx:pppp/tuo-dbname

      dove:
      xxx.xxx.xxx.xxx è l’IP del tuo database server (puoi indicare anche l’hostname)
      pppp è la posta su cui è esposto il servizio (solitamente la 1433 per Sql Server)
      ma soprattutto devi indicare il dbname corretto a cui vuoi collegarti. Ho la sensazione che quello che hai indicato tu (Testate e Righe) siano i possibili nomi delle tabelle.

      Per quanto riguarda il comando di connessione è corretto ma fai attenzione nel caso in cui l’utente di connessione fosse “minuscolo” perchè l’AS lo invia sempre in MAISCOLO. In quel caso puoi mettere i parametri di connessione direttamente nel `global.properties` evitando di specificarli nel comando di connessione. Esempio:


      ard.properties.PGDWS.user=mIo-UtentE
      ard.properties.PGDWS.password=Mia-PassWord

      PS: forse dall’articolo non è chiaro ma “PGDWS” è un nome di fantasia. Puoi dargli il nome che vuoi, l’importante che poi usi lo stesso nome nel comando “ADDRDBDIRE”

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*

code