Java e As400 Introduzione all’uso della IBM Toolbox for Java Furlani Francesco f.furlani@smsgroup.it SMS GROUP srl - Pesaro
IBM Toolbox for Java IBM® Toolbox for Java™ rappresenta un insieme di packages che permettono a programmi Java di accedere ai dati/risorse su un servers iSeries™. Queste classi permettono di scrivere applicazioni client/server, servelt, applet. Inoltre, è possibile eseguire in maniera nativa su iSeries applicazioni Java utilizzando la iSeries Java virtual machine (JVM). IBM Toolbox è disponibile nelle seguenti forme Programma su licenza 5722-JC1 a versione V5R4 installabile dalla versione V5R2 Comprende una versione ottimizzata per esecuzioni su iSeries Versione open source denominata JTOpen utilizzabile da un client esterno
IBM Toolbox for Java L’IBM Toolbox for Java è formata da un insieme di jar files. Ciascun jar è formato da classi che assolvono specifici compiti. Requisiti per l’installazione su una workstation dell’IBM Toolbox for Java Installazione di una J2SE 1.4 o superiore Copiare i jar files della toolbox necessari nel proprio CLASSPATH
Package del IBM Toolbox Access classes Permette di accedere e gestire alle risorse iSeries HTML classes Permette di creare forms HTML e tabelle Micro classes Permette di creare applicazioni java per dispositivi mobili per poter accedere ai dati e alle risorse iSeries ReportWriter classes Permette di create documenti PDF da datasource XML Resource classes Fornisce un framework per accedere alle risorse iSeries Security classes Fornisce connessioni sicure al server iSeries Servlet classes Permette di repererire e formattare dati in una servlet Utility classes Funzioni di sistema e utilità Vaccess classes Permette, tramite Swing, di rappresentare le risorse iSeries
IBM Toolbox for Java Access package Permette di accedere alle risorse iSeries Comandi, Programmi, Spool, Code Dati, ecc.. Utilizzabile da un programma standalone, da una applet o da una servlet
IBM Toolbox for Java Access package
IBM Toolbox for Java Access package Questa è lista delle classi che permettono l’accesso alle risorse iSeries: AS400 - manages sign-on information, creates and maintains socket connections, and sends and receives data SecureAS400- enables you to use an AS400 object when sending or receiving encrypted data AS400JPing - allows your Java program to query the host servers to see which services are running and which ports are in service BidiTransform - enables you to do your own conversions of bidirectional text Command Call - runs iSeries batch commands Connection Pool - manages a pool of AS400 objects, which is used to share connections and manage the number of connections a user can have to an iSeries server Data Area - creates, accesses, and deletes data areas Data Conversion - converts and handles data, and describes the record format of a buffer of data Data Queues - creates, accesses, changes, and deletes data queues Digital certificates - manages digital certificates on iSeries servers Environment variable - manages iSeries environment variables Event log - provides a way to log exceptions and messages independent of the device used to display them Exceptions - throws errors when, for example, device errors or programming errors occur FTP - provides you with a programmable interface to FTP functions
IBM Toolbox for Java Access package Integrated file system - accesses files, opens files, opens input and output streams, and lists the contents of directories Java application call - calls a Java program on an iSeries server that runs on the iSeries Java virtual machine JDBC - accesses DB2 UDB for iSeries data Jobs - accesses iSeries jobs and job logs Messages - accesses messages and message queues on the iSeries system NetServer configuration - accesses and modifies the state and configuration of the iSeries NetServer Permission - displays and changes object authorities on an iSeries server Print - manipulates iSeries print resources Product license - manage licenses for iSeries products Program call - calls an iSeries program Record-level access - creates, reads, updates, and deletes iSeries files and members Service program call - calls an iSeries service program System status - displays system status information and allows access to system pool information System values - retrieves and changes system values and network attributes Trace - logs trace points and diagnostic messages Users and groups - accesses iSeries users and groups User space - accesses an iSeries user space
IBM Toolbox for Java Access package – Data Conversion Le classi adibite alla conversione dati permettono di convertire dati numerici e alfanumerici tra i formati iSeries e Java. La conversione di rende necessaria in quanto su iSeries è utilizzata la codifica EBCDIC. Data Description Queste classi sono costruite sulla “data conversion” permettono di convertire tutti i campi di un record con una singola chiamata ad un metodo. La classe RecordFormat permette di descrivere i dati che saranno gestiti, ossia permette di di specifare i dati che verranno passati in una coda dati, come parametro di un comando.
IBM Toolbox for Java Access package – Data Conversion AS400DataType Rappresenta una interfaccia che definisce i metodi richiesti per la conversione dati. Un programma java implementerà questa interfaccia quando ci sarà la necessità di convertire singoli “pezzi” di dati. Esistono classi che convertono i seguenti tipi di dati: Numerici Testo Es: AS400Bin4 AS400Text Ecc…
IBM Toolbox for Java Access package – Data Conversion Conversione specificando un formato record (RecordFormat) Esistono delle classi che permettono di convertire i dati di un record in un colpo solo invece di convertire singolarmente i campi che formano il record. Per esempio, nel caso di un programma Java che legga dati da un coda dati la quale contiene un array di byte che potrebbe essere “formattato” utilizzando diversi tipi di dati iSeries. Il pgm Java potrebbe convertire il struttura letta campo per campo oppure potrebbe creare un RecordFormat che descrive la struttura dell’array. In questo caso la conversione potrebbe essere fatta direttamenta sul record. La conversione per RecordFormat si usa principalmente quando si lavora con code dati, program call e accesso al db a livello di record.
IBM Toolbox for Java Access package – Data Conversion Esempio di conversione di un dato numerico // Create a buffer to hold the server data type. Assume the buffer is filled with numeric // data in the server format by data // queues, program call, etc. byte[] data = new byte[100]; // Create a converter for this server data type. AS400Bin4 bin4Converter = new AS400Bin4(); // Convert from server type to Java object. //The number starts at the beginning of the buffer. Integer intObject = (Integer) bin4Converter.toObject(data,0); // Extract the simple Java type from the Java object. int i = intObject.intValue();
IBM Toolbox for Java Access package – Data Conversion Esempio di conversione di un testo I dati vengono convertiti utilizzando la classe AS400Text Questa classe si preoccupa di gestire la conversione da EBCDIC Quando viene costruito l’oggetto AS400Text deve essere specificata la lunghezza della stringa da convertire.
IBM Toolbox for Java Access package – Data Conversion For example, assume that a DataQueueEntry object returns iSeries text in EBCDIC. The following example converts this data to Unicode so that the Java program can use it: // ... Assume the data queue work has already been done to retrieve the text from the iSeries and the data has been // put in the following buffer. int textLength = 100; byte[] data = new byte[textLength]; // Create a converter for the iSeries data type. Note a default converter is being built. This converter assumes the iSeries // EBCDIC code page matches the client's locale. If this is not true the Java program can explicitly specify the EBCDIC // CCSID to use. However, it is recommended that you specify a CCSID whenever possible (see the Notes: below). AS400Text textConverter = new AS400Text(textLength) // Note: Optionally, you can create a converter for a specific CCSID. Use an AS400 object in case the program is running // as a Toolbox for Java proxy client. int ccsid = 37; AS400 system = ...; // AS400 object AS400Text textConverter = new AS400Text(textLength, ccsid, system); // Note: You can also create a converter with just the AS400 object. This converter assumes the iSeries code page matches // the CCSID returned by the AS400 object. AS400Text textConverter = new AS400Text(textLength, system); // Convert the data from EBCDIC to Unicode. If the length of the AS400Text object is longer than the number of // converted characters, the resulting String will be blank-padded out to the specified length. String javaText = (String) textConverter.toObject(data);
IBM Toolbox for Java Access package Per poter accedere all’iSeries è necessario identificarsi Si utilizza la classe com.ibm.as400.access.AS400 Qualunque programma deve usare una istanza di questa classe per poter accedere a qualunque risorsa Funzionalità Autenticazione tramite Utente/Password o Kerberos Gestione dei default user ID Cache passwords Prompt per password Cambio password Reperimento versione e release del sistema operativo La classe SecureAS400 permette di criptare la connessione ed evitare di spedire in chiaro userID e password AS400 sistema = new AS400( “192.168.x.x”, user, password );
IBM Toolbox for Java Access package L’oggetto AS400 creato contiene le connessioni ai jobs server su iSeries. Ogni connessione ad un server iSeries determinerà l’esecuzione di opportuni jobs sul server. Un server fornisce l’accesso ai seguenti servizi: JDBC Program call and command call Integrated file system Print Data queue Record-level access
IBM Toolbox for Java Access package – Command Call Le classi CommandCall permetto ad un programma Java di invocare un comando iSeries non interattivo. Il risultato della invocazione del comando è disponibile analizzando il contenuto dell’oggetto AS400Message Il formato è il seguente: Stringa comando da eseguire Oggetto AS400 che rappresenta il sistema sui cui verrà eseguito il comando AS400 sys = new AS400("mySystem.myCompany.com”); CommandCall cmd = new CommandCall(sys); cmd.run("CRTLIB MYLIB"); AS400Message[] messageList = cmd.getMessageList(); sys.disconnectService(AS400.COMMAND);
IBM Toolbox for Java Access package - DataArea La classe DataArea è una classe astratta che rappresenta l’oggetto iSeries Data Area. Questo classe ha quattro sottoclassi che supportano i seguenti tipi di dati: character data, decimal data, logical data, local data areas che contengono character data. ESEMPIO: AS400 system = new AS400("MyServer"); QSYSObjectPathName path = new QSYSObjectPathName("MYLIB", "MYDATA", "DTAARA"); DecimalDataArea dataArea = new DecimalDataArea(system, path.getPath()); dataArea.create(); dataArea.clear(); dataArea.write(new BigDecimal("1.2")); BigDecimal data = dataArea.read(); dataArea.delete();
IBM Toolbox for Java Access package – Data Queues Code Dati La classe DataQueue permette ad un programma Java di interagiere con le code dati su un server iSeries. Le code dati hanno le seguenti caratteristiche: Le code dati permettono veloci comunicazioni fra jobs e eccellenti doti di sincronizzazione tra di essi Piu’ jobs contemporaneamente possono accedere alle code dati Il formato dei dati nelle code dati è libero Le code dati possono essere utilizzate sia in maniera sincrona che asincrona I dati nelle code dati possono essere gestiti sia in modo LIFO che FIFO che Keyed (chiave associata al dato)
IBM Toolbox for Java Access package – Data Queue Esempio di lettura di una coda dati // Create an AS400 object AS400 sys = new AS400("mySystem.myCompany.com"); // Create the DataQueue object DataQueue dq = new DataQueue(sys, "/QSYS.LIB/MYLIB.LIB/MYQUEUE.DTAQ"); // read data from the queue DataQueueEntry dqData = dq.read(); // get the data out of the DataQueueEntry object. byte[] data = dqData.getData(); // ... process the data // Disconnect sys.disconnectService(AS400.DATAQUEUE);
IBM Toolbox for Java Access package – Integrated file system Integrated file system (IFS) Per IFS si intende l'integrated File System ovvero , quel sistema di gestione dello spazio dischi di AS400 per il quale è possibile creare Directory e sottodirectory e files , esattamente come su una macchina Unix Un particolare interesse hanno le directory QDLS e QSYS.LIB. La QDLS , è la directory in cui AS400 memorizza le cartelle (o folder) , a cui , da lato AS400 , si accede attraverso il/i comandi WRKFLR e WRKDOC e che contengono gli oggetti in formato PC o i documenti di Office Vision. La QSYS.LIB , è la directory in cui sono AS400 memorizza il suo data Base Relazionale Nativo , DB2/400 , ed è circa come la directory in qui SQL Server memorizza le sue tabelle . Le classi che gestiscono l’accesso all’integrated file system permetteno ad un programma Java di accedere ai files memorizzati nell’ integrated file system di un iSeries come se accedesse ad un normale stream file Le classi che gestiscono l’integrated file system classes sono state scritte perchè il package java.io non fornisce tuttle le funzionaliltà e particolarità che si trovano su un iSeries
IBM Toolbox for Java Access package – Integrated file system Integrated file system (IFS) La classe principale per poter utilizzare IFS è la classe IFSFile. Con questa classe è possibile creare o cancellare un file o una directory. Oltre a questa classe esistono anche le classi IFSFileInputStream, IFSFileOutputStream, IFSRandomAccesFile come nel package java.io. In pratica queste classi hanno le stesse funzionalità della classi del package java.io ma hanno in aggiunta dei metodi che rispecchiano le particolarità dell’iSeries o semplicemente sono classi ottimizzate // Lista files con estensione .txt contenuti in una directory. AS400 system = new AS400("mySystem.myCompany.com”); // Create the file object. IFSFile directory = new IFSFile(system, “/”); // Generate a list of extension .txt String[] names = directory.list("*.txt"); // Display the names. if (names != null) for (int i = 0; i < names.length; i++) System.out.println(names[i]); else System.out.println("No .txt files");
IBM Toolbox for Java Access package – Print Per stampe si intende l’insieme di oggetti iSeries formati da files di spool, code di output, stampanti, printer files. // This source is an example of IBM Toolbox for Java "PrintObjectInputStream". try{ byte[] buf = new byte[2048]; int bytesRead; AS400 sys = new AS400(); SpooledFile splf = new SpooledFile( sys, "MICR", 17, "QPRTJOB", "QUSER", "020791" ); InputStream in = splf.getInputStream(null); do { // read up to buf.length bytes of raw spool data into our buffer. The actual bytes read will be returned. // The data will be a binary printer data stream that is the contents of the spooled file. bytesRead = in.read( buf ); if( bytesRead != -1 ) { // process the spooled file data. System.out.println( "Read " + bytesRead + " bytes" ); } } while( bytesRead != -1 ); in.close(); } catch( Exception e ) { // exception }
IBM Toolbox for Java Access package – ProgramCall ProgramCall class La classe ProgramCall permette ad un programma Java di invocare un programma iSeries. Il programma iSeries puo’ essere un programma scritto in RPG, RPG/ILE o altro linguaggio. Per passare dei parametri (input, output, input/output) si utilizza la classe ProgramParameter. Al termine dell’esecuzione del programma iSeries i parametri di output conterranno i dati ritornati mentre nel caso di terminazione anomala, interrogando la classe AS400Message si avrà il dettaglio dei messaggi collegati alla terminazione anomala. I parametri richiesti sono i seguenti: Il programa e i parametri necessari Una istanza dell’oggetto AS400 che rappresenta il sistema dove eseguire il programma
IBM Toolbox for Java Access package – ProgramCall //ESEMPIO ProgramCall senza parametri // Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a program object. I choose to set the program to run later. ProgramCall pgm = new ProgramCall(sys); // Set the name of the program. Because the program does not take any parameters, pass null for the // ProgramParameter[] argument. pgm.setProgram(QSYSObjectPathName.toPath("MYLIB", "MYPROG", "PGM")); // Run the program. My program has no parms. If it fails to run, the failure is returned as a set of messages // in the message list. if (pgm.run() != true) { // If you get here, the program failed to run. Get the list of messages to determine why the program didn't run. AS400Message[] messageList = pgm.getMessageList(); // ... Process the message list. } // Disconnect since I am done running programs sys.disconnectService(AS400.COMMAND);
IBM Toolbox for Java Access package – ProgramCall ProgramParameter Si usa la classe ProgramParameter per passare i parametri da un programma Java ad un programma iSeries e viceversa. I dati di input vengono impostati utilizzando il metodo setInputData(). Dopo l’esecuzione del programma i dati di output possono essere reperiti utilizzando il metodo getOutputData().Ogni parametro viene passato come un array di byte. Il programma Java dovrà convertire questo array di byte. Si utilizzeranno le classi di “data conversion” per convertire i dati tra formati Java e iSeries. I Parametri vengono aggiunti alla ProgramCall come oggetti di una lista
IBM Toolbox for Java Access package – ProgramCall // Create an AS400 object AS400 sys = new AS400("mySystem.myCompany.com"); // My program has two parameters. Create a list to hold these parameters. ProgramParameter[] parmList = new ProgramParameter[2]; // First parameter is an input parameter byte[] key = {1, 2, 3}; parmList[0] = new ProgramParameter(key); // Second parameter is an output parameter. A four-byte number is returned. parmList[1] = new ProgramParameter(4); // Create a program object specifying the name of the program and the parameter list. ProgramCall pgm = new ProgramCall(sys, "/QSYS.LIB/MYLIB.LIB/MYPROG.PGM", parmList); // Run the program. if (pgm.run() != true) { AS400Message[] messageList = pgm.getMessageList(); } else { // Create a converter for this iSeries data type AS400Bin4 bin4Converter = new AS400Bin4(); // Convert from iSeries type to Java object. The number starts at the beginning of the buffer. byte[] data = parmList[1].getOutputData(); int i = bin4Converter.toInt(data); } // Disconnect since I am done running programs sys.disconnectService(AS400.COMMAND);
Esempio // // JSMServer.java // SMS GROUP Pesaro import java.net.*; import java.io.*; import com.ibm.as400.access.*; public class JSMServer extends Thread { protected Socket client; static AS400 sys; public JSMServer (Socket socket) { System.out.println("-->Connessione da:"+socket.getInetAddress().getHostName()+ " - "+socket.getInetAddress().getHostAddress()); client=socket; } public void run() try { InputStream is=client.getInputStream(); OutputStream os=client.getOutputStream();
Esempio PrintStream p=new PrintStream(os); int x; ByteArrayOutputStream command=new ByteArrayOutputStream(); String prezzoCommand=new String("PREZZO"); String quitCommand=new String("QUIT"); while ((x=is.read())!=-1) { if (x==64) if (!quitCommand.equalsIgnoreCase(command.toString())) os.write(prezzo(command.toString()).getBytes()); } else { p.println("terminazione!"); try { Thread.sleep(100); sys.disconnectService(AS400.COMMAND); } finally { break; } command.reset(); } else if (x!=10) /*Carriage return */ command.write(x);
Esempio catch (IOException ex) { ex.printStackTrace(); } finally { System.out.println("Connessione chiusa "+client.getInetAddress()); try { client.close(); } catch (IOException ex) } public static void main(String args[]) throws IOException int port=0; Socket client; if (args.length == 0) System.out.println("Uso: java JSMServer numero-porta"); } else if (args.length >= 1) port = Integer.parseInt(args[0]); System.out.println("Server in avvio sulla porta:"+port); ServerSocket server = new ServerSocket(port,100); System.out.println("Server avviato sulla porta:"+server.getLocalPort()); System.out.println("Connessione iSeries in avvio");
Esempio try { sys = new AS400(“as400",“USER",“PASSWORD"); System.out.println("Connessione iSeries avviata"); } catch (Exception ex) { ex.printStackTrace(); System.out.println("Ready.."); while (true) System.out.println("In attesa di connessione..."); client=server.accept(); System.out.println("Richiesta connessione da:"+client.getInetAddress().getHostName()); (new JSMServer(client)).start(); private String prezzo(String CodArt) String tmpPrezzo=""; // Definizione parametri ProgramParameter[] parmList = new ProgramParameter[4]; // Data String Data="20041215"; AS400Text txt8 = new AS400Text(8); parmList[0] = new ProgramParameter(txt8.toBytes(Data),8);
Esempio // Cliente String CodiceCliente="000001"; AS400Text txt6 = new AS400Text(6); parmList[1] = new ProgramParameter(txt6.toBytes(CodiceCliente),6); // Articolo String CodiceArticolo=CodArt; AS400Text txt15 = new AS400Text(15); parmList[2] = new ProgramParameter(txt15.toBytes(CodiceArticolo),15); // Prezzo: valore di ritorno String prezzo=""; AS400Text txt13 = new AS400Text(13); parmList[3] = new ProgramParameter(txt13.toBytes(prezzo),13); ProgramCall pgm = new ProgramCall(sys,"/QSYS.LIB/SMS_OBJSTD.LIB/C0699C.PGM",parmList); // Run the program. if (pgm.run() != true) { AS400Message[] messageList = pgm.getMessageList(); } else { tmpPrezzo= (String)txt13.toObject( parmList[3].getOutputData()); } // Disconnect since I am done running programs} catch (Exception ex) { ex.printStackTrace(); } return tmpPrezzo; }
IBM Toolbox for Java Access package – JDBC JDBC(TM) è un insieme di API incluse nella piattaforma Java che permettono ai programmi Java di connettersi ad un ampio range di database. L’ IBM Toolbox for Java JDBC driver permette di utilizzare le JDBC API interfaces In modo tale da poter sottomettere delle istruzioni SQL e processare I risultati. Esiste un secondo driver, chiamato “IBM Developer Kit for Java JDBC driver” , in breve 'native JDBC driver’: Quale driver usare? Si usa il Toolbox JDBC driver quando il programma Java risiede in un sistema e il database in un altro (es. Ambiente client/server) Si usa the native JDBC driver quando sia il programma Java che il database risiedono sullo stesso sistema
IBM Toolbox for Java Access package – JDBC IBM Toolbox for Java JDBC driver supporta le seguenti versioni: JDBC 1.2 API (the java.sql package) is included in the Java Platform 1.1 core API and JDK 1.1. JDBC 2.1 core API (the java.sql package) is included in both the Java 2 Platform, Standard Edition (J2SE) and the Java 2 Platform Enterprise Edition (J2EE). JDBC 2.0 Optional Package API (the javax.sql package) is included in J2EE and is available as a separate download from Sun. These extensions were formerly named the JDBC 2.0 Standard Extension API. JDBC 3.0 API (the java.sql and javax.sql packages) is included in J2SE, Version 1.4.
IBM Toolbox for Java Access package – JDBC Proprietà specificate nella connessione driver utente password, lista delle Librerie, transaction isolation, formato data e ora ottimizzazione delle query,, …. ecc..
IBM Toolbox for Java Access package – JDBC AS400JDBCConnection class La classe AS400JDBCConnection fornisce una connessione JDBC verso uno specifico database DB2 UDB for iSeries. Per creare una istanza di questo oggetto è sufficiente richiamare il metodo getConnection. Es: DriverManager.getConnection()
IBM Toolbox for Java Access package – JDBC Usando la classe AS400JDBCConnection è possibile eseguire le seguenti operazioni: Creare uno Statement (Statement, PreparedStatement) Gestire i Commit e Rollbacksul database e rilasciare i lock sulle tabelle del database Chiudere la connessione terminando automaticamente le connessioni alle risorse utilizzate Impostare il livello di “transaction isolation” Avere le informazioni sulle tabelle utilizzando i metadata Impostare l’autocommit in on o off Ottenere il job identifier corrispondente al lavoro su sistema
IBM Toolbox for Java Access package – JDBC //Load the IBM ToolBox for Java JDBC driver DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver()); // Connect to the server. Connection c = DriverManager.getConnection("jdbc:as400://mySystem"); // Create a Statement object. Statement s = c.createStatement(); // Run an SQL statement that creates a table in the database. s.executeUpdate("CREATE TABLE MYLIBRARY.MYTABLE (NAME VARCHAR(20), ID INTEGER)"); // Run an SQL statement that inserts a record into the table. s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('DAVE', 123)"); s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('CINDY', 456)"); // Run an SQL query on the table. ResultSet rs = s.executeQuery("SELECT * FROM MYLIBRARY.MYTABLE"); // Close the Statement and the Connection. s.close(); c.close();
IBM Toolbox for Java Access package – JDBC Nell’esempio è stato necessario specificare la libreria che contiene la tabella nella forma <nome_libreria>.<nome_tabella> Se la connessione fosse stata fatta Connection c = DriverManager.getConnection("jdbc:as400://mySystem/MYLIBRARY"); non sarebbe stato necessario specificare la libreria negli SQL
Tips & Tricks Tabelle sotto giornale Comando CRTSQLPKG per creare la libreria che contiene le tabelle Comando STRJRNPF per mettere sotto giornale le tabelle Parametri sulla connessione (transaction isolation) L’istruzione SQL ALTER TABLE DROP COLUMN potrebbe non funzionare! aggiungere il messaggio CPA32B2 alle risposte di sistema ADDRPYLE SEQNBR(3001) MSGID(CPA32B2) RPY('I') impostare nella JOBD associata all'utente QUSER il valore INQMSGRPY(*SYSRPYL)
Gestione dei membri di una tabella Alternative: Utilizzare il comando OVRDBF Utilizzare l’istruzione SQL “CREATE ALIAS”