[技術分享] 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