Body
IBM Java Toolbox for i 实现IBM i消息通信消息机制是IBM i重要的系统管理之一。作业之间可以通过消息交互信息,管理员可以向登录用户广播消息,消息监控硬件异常并自动发送邮件等。另一方面,作为基于IBM i平台的Java应用程序编程接口,IBM Java Toolbox for i针对IBM i消息机制提供了强大的编程支持。本文的主要目标就是指导读者使用IBM Java Toolbox for i,实现IBM i 消息机制的相关功能。有关IBM Java Toolbox for i的基础知识,请参见另一篇技术文档“Toolbox for Java 和 JTOpen”。
从内容上,本文主要分为3部分。第1部分主要介绍IBM Java Toolbox for i针对IBM i消息队列的编程支持;第2部分主要介绍IBM Java Toolbox for i针对IBM i消息文件的编程支持;最后一部分是总结。
IBM Java Toolbox for i针对IBM i消息队列的编程支持消息机制是IBM i最重要的通信手段。按照通信的发送者与接收者划分,消息队列大致可分为:
• 工作站(*WRKSTN)
• 用户(*WRKUSR,*USRPRF)
• 作业(*EXT与程序消息队列组成)
• 系统操作员(QSYSOPR)
其中,QSYSOPR是一个最重要的消息队列。当系统发现异常、对设备进行某种操作,或发生一些较重要的事件时,都会将消息送到QSYSOPR消息队列中。
从另一个角度,按消息的用途与内容划分,IBM i消息队列中的消息大致可分为:
• Informational (*INFO):发送方的任务只是把消息告诉对方,无需应答。
• Inquiry (*INQ):发送消息后,等待接收方应答,然后发送方再决定下一步的行为。
• Reply (*RPY):只有收到Inquire消息后,接收方才可以响应Reply消息。
• Status (*STATUS):类似任务状态条,报告正在进行的任务状态。
• Diagnostic (*DIAG):该消息通常用于诊断程序中出现的非致命错误。
• Escape (*ESCAPE):因不可恢复的严重错误导致程序退出。
• Completion (*COMP):与Escape消息相反,提示程序成功运行完毕。
• Notify (*NOTIFY):报告程序异常中断,等待解决。Notify与Reply两种搭配使用。
• Request (*RQS):常用于发送消息,请求接收方执行CL命令。
那么不同的消息队列与消息是什么样的对应关系呢?我们使用表1来表示上述两者的映射关系。从表中可以看出,作业消息队列支持各种不同的消息,工作站、用户、系统管理员这三种消息队列则只支持Information、Inquiry、Completion、Diagnostic、Reply五种消息。
表 1. 消息类型 vs 消息队列类型(V=Valid)
消息类型消息队列类型
工作站用户作业系统管理员
InformationVVVV
InquiryVVVV
CompletionVVVV
DiagnosticVVVV
ReplyVVVV
RequestV
EscapeV
StatusV
NotifyV
介绍完IBM i消息队列的类型,IBM i消息的类型、以及两者的对应关系之后,我们进一步介绍IBM i消息机制的工作原理。
图1显示的是IBM i消息机制的工作原理。实际上,IBM i的消息机制是一种异步通信方式,非常类似电子邮件,消息相当于邮件,而消息队列,作为一种IBM i对象(类型为*MSGQ),则相当于邮箱,所有消息均会发送给消息队列。
图 1. IBM i消息机制的工作原理
至此,我们知道了IBM i消息机制的相关基本概念与大致工作原理。接下来,我们从面向对象程序设计的角度,详细说明IBM Java Toolbox for i针对IBM i消息队列的相关编程支持。
从面向对象程序设计的角度,IBM Java Toolbox for i使用如下三个Java类表示IBM I 消息队列相关的基本概念:
• AS400Message类——表示IBM i消息。
• MessageQueue类——表示IBM i消息队列。
• QueuedMessage类——作为AS400Message的子类,表示处于队列中的消息。
图2显示的是以上三者对应的类图:
图 2. IBM i消息队列相关的类图
下面,我们演示两个用户之间的请求应答通信。对比表1,消息队列的类型为用户,消息的类型为Inquiry,Reply,对应的工作原理图如图3所示:
图 3. 用户之间发送应答消息的工作原理
这里,我们创建两个用户User1,User2,系统会自动为这两个用户分别建立一个相应的消息队列。作为发送方,User1发送Inquiry消息至用户消息队列User2,收到消息后,User2将发送Reply消息至用户队列User1。
相关的代码如清单1所示:
清单 1. 用户之间发送应答消息
// 构造AS400对象,建立Java应用程序与IBM i服务器的连接。
AS400 sys = new AS400(system, “user1”, pwd);
// 用户USER2消息队列
MessageQueue queue = new MessageQueue(sys, "/QSYS.LIB/QUSRSYS.LIB/USER2.MSGQ");
// 清空USER2消息队列
queue.remove();
// 发送Inqury消息给USER2,并告知Reply消息队列为USER1。
String cmd = "SNDMSG MSG('How long will the ADMIN server be up today?') TOUSR(user2)
MSGTYPE(*INQ) RPYMSGQ(user1)";
CommandCall call = new CommandCall(sys, cmd);
// 调用相应的run方法,执行CL命令。
if (call.run()){
Enumeration e = queue.getMessages();
while (e.hasMoreElements()) {
// 列出消息队列USER2的消息
QueuedMessage msg = (QueuedMessage) e.nextElement();
System.out.println("[From " + msg.getSendingUserProfile() + ", Reply Status: " +
msg.getReplyStatus() + "]" + msg.getText() );
}
} else {
// 如果调用失败,则将错误消息封装成相关Java类AS400Message。
AS400Message[] messageList = call.getMessageList();
// ... 处理消息列表
}
// 作为好的编程习惯,释放连接
sys.disconnectService(AS400.COMMAND);
关于输出结果,我们运行相关的CL命令Display Message(DSPMSG),我们可以查看位于用户User2消息队列中的消息,如图4所示:
图 4. 显示User2消息队列中的消息
至此,我们已介绍IBM i消息的相关概念,工作原理,以及IBM Java Toolbox for i针对IBM i消息的编程支持。
IBM Java Toolbox for i针对IBM i消息文件的编程支持如前所述,按照消息用途的不同,我们可将IBM i消息分为Informational,Inquiry等9种。从消息内容划分,IBM i消息又可以分为两种:
• 立即型消息(Immediate Message)——立即型消息是临时产生的(如上述示例中SNDMSG发出的消息),并不需要永久存储在系统中。
• 预定义消息(Predefined Message)——预定义消息是预先建立起来的消息,他们被存放在一个消息文件(Message File)中,需要时可随时从消息文件中抓取出来。
系统发出的消息都是预定义消息。用户也可以创建自己的消息文件,以此来存储某些应用程序经常需要发送的消息。消息文件一种IBM i对象,类型为*MSGF。执行下列CL命令,可以查看所有消息文件,如图5所示。
WRKOBJ OBJ(*ALL) OBJTYPE(*MSGF)
图 5. 显示IBM i消息文件列表
从面向对象程序设计的角度,IBM Java Toolbox for i使用MessageFile类表示IBM i消息文件。
图6显示的是MessageFile类与AS400Message两者对应的类图:
图 6. IBM i消息文件相关的类图
作为样例,清单2演示的是如何创建一个消息文件,对应的业务逻辑如下:
1. 首先,我们创建一个消息文件MYMSGF,位于DEMO库。
2. 然后,我们插入了消息MSG0001的定义。
3. 最后,我们使用MessageFile将该消息读取。
清单 2. 创建消息文件
// 构造AS400对象,建立Java应用程序与IBM i服务器的连接。
AS400 sys = new AS400(system, “user1”, pwd);
// 创建一个DEMO库。
String cmdCrtlib = "CRTLIB DEMO";
// 创建消息文件
String cmdCrtMsgf = "CRTMSGF MSGF(DEMO/MYMSGF)";
// 添加消息定义
String cmdAddMsgd = "ADDMSGD MSGID(MSG0001) MSGF(DEMO/MYMSGF) MSG('Hello, World!')
SECLVL('Welcome to the world of IBM i!') ";
CommandCall call = new CommandCall(sys);
// 调用相应的run方法,执行CL命令。
call.run(cmdCrtlib);
call.run(cmdCrtMsgf);
call.run(cmdAddMsgd);
call.run(cmdSndPgmMSg);
// 打印消息文件中的消息定义
MessageFile messageFile = new MessageFile(sys);
messageFile.setPath("/QSYS.LIB/DEMO.LIB/MYMSGF.MSGF");
AS400Message message = messageFile.getMessage("MSG0001");
System.out.println(message.getText());
// 作为好的编程习惯,释放连接
sys.disconnectService(AS400.COMMAND);
关于输出结果,我们使用CL命令Display Object Description(DSPOBJD)可查看消息文件的名称以及相关属性,如图7所示。
待IBM i消息文件MYMSGF创建完成后,我们可以在CL程序使用CL命令Send Program Message (SNDPGMMSG),发送MSG0001消息至系统操作员,如下:
SNDPGMMSG MSGID(MSG0001) MSGF(DEMO/MYMSGF) TOMSGQ(*SYSOPR)
至此,我们已介绍IBM i消息文件的相关概念,工作原理,以及IBM Java Toolbox for i针对IBM i消息文件的编程支持。
总结作为IBM i最重要的通信手段,消息机制被广泛用于工作站,用户,系统操作员,应用程序与系统之间。IBM i 消息队列天生决定了IBM i消息是一种异步通信方式。IBM i消息文件提供了消息定义的模版,使得消息得到重用。IBM Java Toolbox for i针对以上三者提供了基于Java的编程支持。
参考资源• 参看文章“Toolbox for Java 和 JTOpen” ,了解IBM Java Toolbox for i的概要信息。
作者:皮光明