[技術分享] Hpe Nonstop主機上的現代化開發方式(中)

作者/莊佳哲

作者簡歷 作者現職凌群電腦金控軟體研發總處軟體工程師,主要負責期貨系統軟體,專長為COBOL、JAVA、C#軟體開發。 前言 在NonStop系統環境中,除了傳統的COBOL開發,NonStop也有支援現代的開發工具,像是Java、SQL/MX等等。本期將承接上期,接著介紹在NonStop系統上上如何使用Java操作Enscribe Files。 JToolkit JTookit是HPE提供的Java開發工具,其中包含了5種packages和ddl2java工具,各功能分別為:
  • com.hp.nonstop.io.process package:提供對NonStop process進行I/O的classes。
  • com.tandem.ext.enscribe:提供對Enscribe files進行I/O的classes。
  • com.tandem.ext.guardian:提供對Guardian files進行I/O的classes,包含$RECEIVE。
  • com.tandem.ext.util:提供給其他packages使用的utility functions
  • com.tandem.tsmp:提供執行Context-Free和Context-Sensitive的Pathsend操作。
  • ddl2java:將DDL中定義的檔案格式轉為對應的Java class。
一、JToolkit使用步驟 安裝位置: /usr/tandem/javaexth11 Java Library位置: /usr/tandem/javaexth11/lib/tdmext.jar ddl2java位置: /usr/tandem/javaexth11/bin/ddl2java 使用前先配置OSS系統環境變數: export _RLD_LIB_PATH=/usr/tandem//lib 例如: export _RLD_LIB_PATH=/usr/tandem/javaexth11/lib:$_RLD_LIB_PATH 若要使用JToolkit Library,再加入: export CLASSPATH=/usr/tandem/javaexth11/lib/tdmext.jar:$CLASSPATH ddl2java操作 一、建立DDL 在Guardian環境中建立DDL資料 範例檔案格式: DEFINITION TESTCOM. 02 COM-PK Heading "主鍵資料欄". 03 COM-EXCH-ID PIC X(07) Heading "期交所代碼". 03 COM-COMMODITY-ID PIC X(07) Heading "商品標的". 02 COM-NAME PIC X(30) Heading "商品中文名稱". 02 COM-CURRENCY PIC X(03) Heading "交易幣別". 02 COM-TICK-AMT PIC S9(06)V9(02) COMP Heading "契約價值". 02 COM-OPER-DATE PIC 9(08) Heading "修改日期". END. RECORD TESTCOM-R. FILE IS "TESTCOM" KEY-SEQUENCED MAXEXTENTS 100. DEFINITION IS TESTCOM. KEY IS COM-PK duplicates not allowed. END. 二、使用ddl2java工具,將DDL格式轉為Java class ddl2java指令說明: ddl2java -dpath [DDL路徑] -i [itemlist檔案位置] -p [Java Package名稱] -l [C/COBOL] -d [輸出位置] -e [DDL中PIC X和PIC N欄位的預設編碼] 其中itemlist需自行建立,內容格式為: item-type item-name,class-type[,language],char-string-type (1)item-type:DDL中要轉出的data item type,可為DEF[INITION]或REC[ORD] (2)item-name:DDL中RECORD NAME或DEFINITION NAME (3)指定要產生的JAVA CLASS類型,可為Input、Output、IO (4)language:可省略,可為C或COBOL,預設為COBOL (5)char-string-type:指定字串在從 Java 字串轉換為Guardian 格式時是否應以 null 結尾,以及 NonStop Kernel 格式的字串在轉換為 Java 字串之前是否應以 null 結尾,可為NT(以 null 結尾)或NN(不以null結尾) 例如:REC TESTCOM-R,IO,NN 指令範例: ddl2java -dpath /G/FU1/SAMDDL -i /java/sam/itemlist -p com.example.testjava -l COBOL -d /java/sam -e ISO8859-1 三、成功轉為Java class 轉出的Java class一部份內容: package com.example.testjava; import java.util.Vector; import java.util.Hashtable; import java.io.CharConversionException; import java.util.HashMap; import java.util.MissingResourceException; import com.tandem.ext.guardian.*; import com.tandem.ext.util.*; import java.math.BigDecimal; /** IO_Testcom_r class was generated for DDL Rec/Def: testcom on: 5/29/24 at: 14:26:48. This is an INPUT/OUTPUT class which can be used to read and write data.*/ public class IO_Testcom_r implements com.tandem.ext.guardian.GuardianInput, com.tandem.ext.guardian.GuardianOutput { protected int _numConversionErrors; protected boolean _allowErrors = false; protected HashMap _errorDetail; protected int _bufferLen = 60; public String com_exch_id; public String com_commodity_id; public String com_name; public String com_currency; public BigDecimal com_tick_amt; public String com_oper_date; …… 有了JToolkit Library和DDL轉出來的Java class就可以開始進行Enscribe Files的I/O操作。 Java I/O Enscribe Files 一、設定檔案位置並開啟檔案 EnscribeFile testcom = new EnscribeFile(fileName); //指定檔案路徑 //設定open file方式 EnscribeOpenOptions openAttr = new EnscribeOpenOptions(); openAttr.setAccess(EnscribeOpenOptions.READ_WRITE); //READ、WRITE方式 openAttr.setExclusion(EnscribeOpenOptions.SHARED); //SHARED方式 testcom.open(openAttr); System.out.println("Open File Successful! File:" + testcom.getFileName()); //IO_Testcom_r 此物件由ddl2java產出 IO_Testcom_r testcomR; int countRead = 0; 二、新增資料 testcomR = new IO_Testcom_r(); testcomR.setCom_exch_id("F000000"); testcomR.setCom_commodity_id("CAO T"); testcomR.setCom_name("TestCom"); testcomR.setCom_currency("TWD"); testcomR.setCom_tick_amt(BigDecimal.valueOf(1234)); SimpleDateFormat sdFormat = new SimpleDateFormat("yyyyMMdd"); Date now = new Date(); testcomR.setCom_oper_date(sdFormat.format(now)); try { testcom.write(testcomR); //寫入檔案 System.out.println("Add Record:" + testcomR.getCom_exch_id() + " " + testcomR.getCom_commodity_id() + " " + testcomR.getCom_name() + " " + testcomR.getCom_currency() + " " + testcomR.getCom_tick_amt() + " " + testcomR.getCom_oper_date()); } catch (EnscribeFileException ef) { System.out.println("Guardian error = " + ef.getErrorNum()); if (ef.getErrorNum() == GError.EBADERR) //Guardian error 10,資料已存在 System.out.println("Record Exists:" + testcomR.getCom_exch_id() + testcomR.getCom_commodity_id()); else if (ef.getErrorNum() == GError.ESECVIOL) //Guardian error 48,無操作權限 System.out.println("Security Violation, Please Check File Permissions!"); } 三、查詢資料 查詢全部資料: testcomR = new IO_Testcom_r(); do{ countRead = testcom.read(testcomR); if (countRead != -1) // -1 = EOF System.out.println(testcomR.getCom_exch_id() + " " + testcomR.getCom_commodity_id() + " " + testcomR.getCom_name() + " " + testcomR.getCom_currency() + " " + testcomR.getCom_tick_amt() + " " + testcomR.getCom_oper_date()); }while (countRead != -1); 使用Key查詢: testcomR = new IO_Testcom_r(); EnscribeKeyPositionOptions kpa = new EnscribeKeyPositionOptions(); String keyvalue; kpa.setKeySpecifier((short) 0); //0表示P Key keyvalue = "F000000CAO T"; //要查詢的Key值 kpa.setKeyValue(keyvalue); kpa.setPositioningMode(EnscribeKeyPositionOptions.POSITION_GENERIC); //GENERIC讀取方式 kpa.setKeyLength((short)14); //Key長度 kpa.setCompareLength(10); //要比對的長度 testcom.keyPosition(kpa); countRead = testcom.read(testcomR); if (countRead != -1) // -1 = EOF System.out.println(testcomR.getCom_exch_id() + " " + testcomR.getCom_commodity_id() + " " + testcomR.getCom_name() + " " + testcomR.getCom_currency() + " " + testcomR.getCom_tick_amt() + " " + testcomR.getCom_oper_date()); 四、更新資料 testcomR = new IO_Testcom_r(); keyvalue = "F000000CAO T"; kpa.setKeyValue(keyvalue); kpa.setPositioningMode(EnscribeKeyPositionOptions.POSITION_EXACT); kpa.setKeyLength((short)14); kpa.setCompareLength(14); testcom.keyPosition(kpa); testcom.readLock(testcomR); //讀取並lock檔案 System.out.println("Old Data:" + testcomR.getCom_exch_id() + " " + testcomR.getCom_commodity_id() + " " + testcomR.getCom_name() + " " + testcomR.getCom_currency() + " " + testcomR.getCom_tick_amt() + " " + testcomR.getCom_oper_date()); testcomR.setCom_tick_amt(BigDecimal.valueOf(4321.97)); testcomR.setCom_name(testcomR.getCom_name().trim().replaceAll(" Update", "") + " Update"); try { testcom.writeUpdateUnlock(testcomR); //更新資料並unlock }catch (EnscribeFileException ef){ System.out.println("Guardian error = " + ef.getErrorNum()); } 五、刪除資料 testcomR = new IO_Testcom_r(); keyvalue = "F000000CAO T"; kpa.setKeyValue(keyvalue); kpa.setPositioningMode(EnscribeKeyPositionOptions.POSITION_EXACT); kpa.setKeyLength((short)14); kpa.setCompareLength(14); testcom.keyPosition(kpa); testcom.readLock(testcomR); //讀取並lock檔案 try { testcom.deleteRecordUnlock(); //刪除並unlock檔案 }catch (EnscribeFileException ef){ System.out.println("Guardian error = " + ef.getErrorNum()); } (待續) 參考資料
  • NSJ 11 User Guide
  • HPE JToolkit for NonStop Server for Java 11 Programmer's Reference