级别: 初级 Brent Cooley (bcooley@us.ibm.com), IT 专家,Application Innovation Services, IBM Global Services Ellen Matheson McKay (ecmckay@ca.ibm.com), WebSphere 信息开发人员, IBM 多伦多实验室 Barry Searle (searle@ca.ibm.com), WebSphere Studio 开发人员, IBM 多伦多实验室
2004 年 6 月 01 日 这篇由五个部分组成的系列文章向您介绍如何将应用程序从 VisualAge for Java Common Connector Framework(CFF)迁移到 WebSphere Studio J2EE Connector Architecture(JCA/J2C)。第 5 部分将为您展示如何使用 WebSphere Studio Application Developer Integration Edition 来创建一个虚拟的 ServiceProxy 及 FormatHandler 和 DateBean 助手类,以及如何访问 FormatHandler Byte 数组。
引言
本文是一系列介绍从 IBM
®VisualAge
®for Java
™CCF 到 WebSphere
®Studio J2C 的迁移的文章的一部分,这一系列文章描述了将应用程序从 CCF CICS
®ECI、IMS
™或 WebSphere MQ 迁移到 J2C 的典型活动。这一系列文章包括以下几个部分:
本文的大部分内容
在概念上与前面的第 3 部分(CICS)和第 4 部分(IMS)文章内容相似,但还是有一些主要区别:
- 在 J2C 或 WebSphere Studio 中没有
MQ 连接器。
- 作为替代,必须迁移应用程序以使用 J2EE
Java 消息服务(Java Message Service,JMS)。
-
作为选择,您可以使用相同的 CCF 迁移助手(CCF Migration Assistant,CMA)来迁移
Record(但是
不能迁移 MQ
Command)。
(使用
CMA
Record局限性和指导原则
)。
- 或者,您可以使用 WebSphere Studio 工具手动重新创建您的 Record 和 FormatHandler 助手类。
- 使用 MQ/JMS
Command局限性和指导原则
来手动迁移您的 MQ
Command。
- 使用
应用程序局限性和指导原则
来手动迁移您的 MQ
应用程序。
- 增强您的 JMS 应用程序以使用附加的 JMS 特征:
- 例如
MQ 连接和队列的 JNDI 查找,以来避免使用硬编码值。
- 将您的 JMS
Command包装为一个 EJB,并将其作为 WebSphere Studio J2C/WSIF 服务导出。
- 允许其他当前和/或未来的 WebSphere Studio 服务使用它。
-
未来可能将 JMS 作为 J2C 下的传输来使用(例如,JMS 连接器)。
- 如果/当工业 J2C 将其合并(
没有任何人的委托声明)。
概述
VisualAge for Java 使用 Common Connector Framework(CCF)来简化访问主机 Enterprise Information Systems(EIS)的 Java 应用程序的创建和维护。这些 EIS 资源是典型的 Customer Information Control System(CICS)事务、Information Management System(IMS)事务或者 WebSphere MQ 消息队列。VisualAge for Java Enterprise Access Builder(EAB)能够提供创建 CFF 连接器对象(Java Command 和 Record 类)的工具以及使用这些 CCF 连接器对象的应用程序,从而支持 CFF 框架。
由于 CCF 框架的价值已被认可和接受,IBM 已经提交它以考虑将其制订为行业标准。经过评审和修改,它就成为了 J2EE Connector Architecture(J2C)。虽然 J2C 和它的前身 CCF 相类似,但还是存在许多显著的区别,迁移还是有很大价值的。因此,将现有的应用程序从 VisualAge for Java CCF 迁移到 WebSphere Studio J2C 是可取的(只要存在等价的 J2C)。本文包括三个主题:
- EAB 工具生成的 CCF
Record的 CMA 迁移(或 WebSphere Studio 从
CopyBooks重建)和
- EAB 工具生成的 CCF
MQ Command到
JMS Command的迁移和
- 开发人员编写的使用这些对象的
MQ 应用程序到
JMS 应用程序的迁移。
重要:如果您的 CCF IMS 命令和记录的数量还不到十来个,那么最好的方法就是在 WebSphere Studio 中手动重新生成 J2C 构件,并手动迁移您的应用程序。如果您有多于 100 个左右的 CCF 命令和记录,那么使用本文介绍的方法和 CCF Migration Assistant(CMA)是您迁移到 WebSphere Studio J2C 最简单的途径。如果您有 10 个至 100 个 CCF 命令和记录,那么推荐您阅读本文,然后自己决定采取哪种途径。
迁移帮助服务
如果您关心以下步骤的详细信息,或者它们需要花费多少工作量,请注意 IBM WebSphere Services 有各种各样的迁移帮助,顾客都可以购买到:
- WebSphere Application Server V3.5 =>V4 =>V5 应用程序迁移的现场培训或帮助
- CCF 应用程序迁移、工作描述和有效范围的现场评估
- 安装并熟悉 CCF Migration Assistant (CMA)程序
- 小应用程序或应用程序组件的试验性迁移
- 较大的应用程序的选择性迁移
要获取进一步的信息,请联系:
构件(服务)和应用程序(Web 或 Java)项目的最佳实践
VisualAge for Java MQ
Adder样本将生成的 CCF MQ AdderCommand 连接器构件、它的 ExecuteAdder 应用程序和它的 ExecuteAdderServer MQ 服务器样本放在一个项目中(因为总共只有九个 Java 文件)。它也使用来自 CICS-ECI 样本项目的 CCF 生成的 AdderRecord 构件。您的特定 VisualAge for Java CCF 应用程序可以只有一个 VisualAge for Java 项目,也可以有多个,这取决于您的 CCF 应用程序 VisualAge for Java 项目的组织方式。
迁移到 WebSphere Studio 的期间是保证正在进行迁移的项目结构遵循简单的“最佳实践”的最佳时间。我们建议您准备一个或多个 WebSphere Studio Service 项目来包含相关的 J2C Service 组,以及一个或多个 Web 或 Java 项目来包含您的应用程序(一般来说,您的整个应用程序中的的每个主要子系统都有一个 Web 或 Java 项目):
- 例如,您可能有一个 WebSphere Studio 服务项目——PersonnelServices——它包含一组访问 CICS 个人程序和 IMS 个人程序的服务。
- 另外,您可能还有一个使用 PersonnelServices 项目的 WebSphere Studio Web 项目——PersonnelWeb, 一个使用其他 InventoryServices 项目的 InventoryWeb 项目,以及一个通过前两个 Services 项目来访问管理程序的 AdminJava 项目。
- 这些服务和 Web 项目或 Java 项目组合在一起就构成了完整的应用程序。
一个小小的逻辑结构大大简化了对这些项目长时间的了解和维护。
从 CCF MQ 到 JMS 的迁移步骤
本文详细描述了如何将应用程序从 CCF MQ 迁移到 JMS 应用程序。
请仔细阅读这部分内容。
本文非常具体,并包含了数个功能。本文被仔细划分成几个部分,每部分都与您的迁移活动分段相匹配。如果您在阅读本文(或迁移您的应用程序)时产生疑惑,请回过头来重读这一部分。
-
设置VisualAge for Java 和 WebSphere Studio Application Developer,Integration Edition。
- 可选项:按照 VisualAge for Java 说明来确保 MQ
Adder样本工作正常(如果您要迁移它的话)。
- 可选项:您还可能想要设置一个小型本地 MQ 服务器,以更容易地进行本地测试
- 从 VisualAge for Java
导出CCF
Record类构件(或原始的
COBOL CopyBooks)和 CCF MQ 应用程序源代码。
-
导入 CCF
Record构件
(使用 WebSphere Studio
CMA)并将其迁移到 J2C。
- 选项 3A:使用
CCF Migration Assistant(CMA)来迁移 CCF
Record。
- 选项 3B:或使用 WebSphere Studio 工具(
向导或
BulkImporter)并利用
COBOL CopyBooks来手动重新创建
Record和
HelperClasses。
-
创建 JMS
Command构件
(使用 JMS Command 编码指导原则)。
- 选项 4A:使用最简单的
Command(用于连接和队列的硬编码值)。
- 选项 4B:或者使用一个更易维护的
JNDI Command(管理连接和队列的 JNDI 查找)。
-
导入并手动迁移 CCF MQ 应用程序(使用
CCF MQ 迁移到 JMS 应用程序编码指导原则)。
- 使用与 CCF 最兼容的
CompatibilityMethod方式。
- 或者使用新的
J2C 调用方式。
这种应用程序迁移活动包含了所有的应用程序生命周期维护,从而能够适应新的 JDK 级别、新的 Server API 等等。
-
部署和测试.
- 迁移的 JMS 构件和应用程序的
生命周期维护。
步骤 1. 设置 VisualAge for Java 和 WebSphere Studio
- 如
CCF 迁移概述文章所述,请确保您正确设置了 VisualAge for Java V3.5.3 或 V4.0:
- 本系统必须包括您的
CCF MQ 应用程序和生成的
MQ 构件(Command 和 Record)。
-
可选项:系统必须包括 CCF MQ
Adder 样本(如果您希望像本文所介绍的那样对它进行迁移的话)。
-
推荐:如果您将要迁移 CCF MQ
Adder样本,我们强烈推荐您更改主机 MQ 服务器程序
ExecuteAdderServer,以使它保持为多个请求运行,并捕获/处理异常。
while(args.length>=0) {
try {
// create a command to get a request message with
// op1 and op2 from the ADDER.REQUEST queue the command
// waits until a message is available in the queue
System.out.println("Getting request message...");
GetRequestCommand getRequest = new GetRequestCommand();
// execute the command
getRequest.execute();
// get operands op1 and op2 from the message record received
int op1 = getRequest.getOp1();
int op2 = getRequest.getOp2();
System.out.println("Request op1=" + op1 + " op2=" + op2);
int res = op1 + op2;
// create a command to put the reply message
PutReplyCommand putReply = new PutReplyCommand();
// pass the request descriptor from the request to the reply,
// to make this reply match the request
putReply.setRequestDescriptor(getRequest.getRequestDescriptor());
// write the result into the reply message record
putReply.setRes(res);
// execute the command
System.out.println("Putting reply message, res=" + res);
putReply.execute();
} catch (Exception e) {
System.out.println("AdderServer Exception="+e.getMessage() );
}
}
|
|
- 按照
CCF 迁移概述文章所描述的,请确保您正确设置了 WebSphere Studio Integration Edition,V5.0.1.1:
- 确保安装了必需的
FixPack和所有必需的
InterimFixes,如下所示:
-
注意版本 5.01 及 IF7+8(或后续版本)仅在使用 CMA 时是必需的。
-
注意:
CICS(或
IMS)J2C RAR:
我们将使用 CICS(或 IMS)J2C 服务工具来生成我们的 JMS
Record和
HelperClass,因此您需要安装一个(或另一个,或两个)RAR。本文使用 CICS 版本,但两者都可使用。您不会以使用任何 CICS(或 IMS)代码或运行时功能结束,因此不必担心您不知为何而需要它们。您将要以使用一个完全的
JMS实现作为结束,但是与 WebSphere Studio J2C 服务工具生成的
Record和
HelperClass一起!
- 遵循
CICS-ECI样本
中的安装说明
并确保所有必需的
资源适配器(在本文中为 CICS)都已经安装到适当的 RAR 项目中
(以下所示为 CicsEci、Ims 和 Hod3270项目):
- 可选项:确保安装了
CCF Migration Assistant(CMA)插件:
-
概述这篇文章描述了如何请求和获得 CMA 插件。
CMA 插件
不是并非WebSphere Studio 的一部分并且
不受支持——您不能调用 IBM 支持和请求帮助,或者向它报告相关的问题。
- 要获得该插件,请允许有一到两周的时间来完成以下的事情:
- 发送电子邮件到
searle@ca.ibm.com请求该插件。
- 我们返回给您包含“仅此状态”许可的电子邮件。
- 您返回给我们接受该许可的电子邮件。
- 我们返回给您包含当前 CMA 插件的电子邮件(或者 FTP 指令)。
- 以上步骤是必要的,它能够让您明确该插件是我们按“仅此状态”提供给您的,并且如果有什么最新的 CMA 的话,我们也将会发送给您。以下屏幕截图显示了在安装完 CMA 插件之后插件注册中心看起来的样子:
- 可选项:您可能还想设置一个小型的本地 MQ 服务器,以更容易地进行测试。

 |

|
步骤 2. 导出 VisualAge for Java CCF 构件和 CCF 应用程序
您可以将 CCF 构件类(和可选的源文件)及 CCF 应用程序源文件(和可选的类)一起导出到一个 Java Archive(JAR)文件中。事实上,如果您现在还采用将构件及应用程序导入到 WebSphere Studio,然后编辑源文件并重新编译所有的文件这种
不受支持的方法,那么上述过程将是最简单的。正如
CCF 迁移概述文章所提到的,这一过程看起来对大多数应用程序都有效,但事实上它是不受支持的,因为它还没有由 IBM 进行广泛的系统测试。由于有不同的 JDK 编译器级别、不同的支持库,所以它们可能还存在着一些小问题。
注意
XxxxBeanInfo助手类只用于 VisualAge for Java,在迁移的过程中不需要使用它。
在通常情况下,对于 CCF Migration Assistant(CMA)迁移过程,您需要将所有 CCF 生成的
Record迁移到 JAR 文件中。
- 如果您想要使用 CMA 程序来迁移您的 CCF
Record,则需要
XxxxRecord和
XxxxRecordType(
XxxxRecordInfo)类。
- 或者您想要使用 WebSphere Studio 工具手动重新创建
Record,则需要原始的
COBOL CopyBooks。
- 也可将源 Java 文件包括到导出的 JAR 中,但是 CMA 程序将忽略它们。
- 导出的 JAR 中还可以包括 MQ
XxxxCommand和/或任何
XxxxBeanInfo构件,但是它们将被 CMA 程序略过,并且将一个关于此影响的警告写入 CMA 日志中。
- 更为简洁的做法是仅导出
Record和
RecordType(
RecordInfo)类。
在您迁移 CCF MQ
Adder样本时,您可能需要将生成的 CCF
Record
类(从
CICS Adder
样本项目),以及可任选的未用过的 MQ
AdderCommand导出到一个名为
MQadderClasses的 JAR 文件中。因此,要导出
Adder构件,您需要执行以下操作:
- 展开
com.ibm.ivj.eab.sample.eci.adder 包,右键单击来选择必需的
AdderRecord和
AdderRecord多个文件。
- 作为可选项,还可以展开
com.ibm.ivj.eab.sample.mq.adder 包,然后右键单击未迁移的
AdderCommand多个文件。
- 然后单击
Export =>JAR file =>Next =>.class(如果愿意,也可把
.java文件选上,CMA 会忽略它们)。
- 在
Jar file 字段内,键入
C:\CCF\MQadderClasses.jar ,然后单击
Finish。这样就可导出 CCF 构件了。
类似地,对于 CCF 应用程序迁移,请选中
ExecuteAdder,并将它的一个
.java 源文件导出到
C:\CCF\MQadderExecute.jar 。
对于这个小样本,您可能更倾向于将所有必需的
.class和
.java 文件放在一起导出到
C:\CCF\MQadderEverything.jar 文件中。如果您想尝试不受支持的导入,然后在 WebSphere Studio 中对它进行编辑和重建,则这种方法就是最简单的。
也就是说,我们根本不会使用主机服务器程序(
ExecuteAdderServer、GetRequestCommand、PutReplyCommand),这是因为它们代表我们正在访问的“主机”企业服务器,该服务器不会移动。仅可以出于完整性考虑而包括它们。
不受支持:WebSphere Studio 源代码的导入以及 CCF 构件和应用程序的重建
大部分的 CCF 应用程序和 CCF 构件看起来都能够在 WebSphere Studio 中很好地重建,然后在 WebSphere Application Server 中成功地运行。但由于 Java 编译器级别的不同、使用其他最新的库文件以及系统 API 的改变等原因造成了它们
不能被测试和支持。因此,短期 CCF 应用程序维护的一个不受支持的方法是将 CCF 连接器安装到 WebSphere Studio 和 WebSphere Application Server 中(请参阅前面
关于局限性的文章,并注意实际安装 CCF 连接器时需要运行时许可并且需要在 WebSphere Application Server 中使用),然后将 EAB 生成的 CCF 构件(生成的 command 和 record 类的 Java 源代码)导出到 WebSphere Studio 中。
开发人员编写的 VisualAge for Java CCF 应用程序的 Java 源代码以及生成的 CCF 构件可以作为一个 JAR 文件导出,并可将其导入到某一 WebSphere Studio Java 项目中,与其他的 Java 程序一样。因为它们仅仅是 Java 源文件,同时 WebSphere Studio
不能重新生成任何的 CCF 构件,这样您就可以使用缺省的 WebSphere Studio Java 编辑器对它们进行编辑了。例如,假设您要将所有的 VisualAge for Java MQ Adder 文件导出到 MQadderEverything.jar 中,然后将其导入 WebSphere Studio,您就可以按照以下步骤来进行:
- 创建一个 Java 项目。单击
File =>New =>Project =>Java =>Java project =>Next,然后在
Project Name 字段中键入
CCFadderMQ ,并单击
Finish,这样就可创建一个 Java 项目了。
- 导入 CCF 源文件:
- 选择
CCFadderMQ项目,然后单击
File => Import => Zip file
=>Next。找到您的
C:\CCF\CCFadderEverything.jar ,然后单击
Finish将它植入到 Java 项目中。
- 如果您还导出了
XxxxBeanInfo文件(
AdderRecordBeanInfo或
AdderCommandBeanInfo、
PutReplyCommandBeanInfo或
GetRequestCommandBeanInfo),那么您可以选中它们并将其删除。
- 排除因依赖性而引起的错误:
- 您的 MQ CCF 应用程序需要创建和运行 MQ CCF 连接器
mqccf.jar。您可以创建一个项目
MqCcf,然后将该文件放在这个项目中以便共享使用,但由于我们只有一个 CCF MQ 项目,最简便的方法就是将它(作为一个
文件系统文件)导入到
CCFadderMQ 项目中。
-
注意:您所需要的
mqccf.jar安装在您的 VisualAge for Java 连接器安装中(通常安装到“
C:\IBM Connectors\classes\mqccf.jar ”)。
- 现在请单击
Libraries选项卡。
mqccf.jar和四个 WebSphere Application Server 主运行时 CCF jar(
ccf.jar、eablib.jar、j2ee.jar、recjava.jar)都必须在构建路径中。以下屏幕捕获显示了您的构建路径中应该存在的所有条目,而且在您的
Tasks 视图中不能有编译错误。
- 执行——请右键单击
AdderExecute类并选择
运行。这样在
控制台视图中就会有一个成功的 CCFadderMQ 执行结果。
- 注意我们在此项目中采取保持 3 MQ 主机服务器程序(
ExecuteAdderServer etc.、),这是因为通过这种方式也能够维护它们)。
- 部署和测试——您也可以将重新编译的
CCFadderMQ应用程序(及必要的 CCF 运行时 JAR)部署到一个远程的工作台上,然后运行它。

 |

|
步骤 3. 使用 CMA 将 CCF 记录迁移到 J2C(或者从 CopyBooks 重新创建)
- 将 CCF 构件作为一个
文件系统文件(使之成为一个 JAR)导入到期望的 Service 项目中:
- 选项 3A:对于 CMA 迁移,您必须导入由 VisualAge for Java 导出的
Record构件 JAR。
- 选项 3B:或者对于 WebSphere Studio 重新创建,您必须导入 VisualAge for Java(或原始的)
COBOL CopyBooks。
- 将这些构件从 CCF 迁移到 J2C。
- 选项 3A:使用 CMA 程序迁移 CCF
Record。
- 选项 3B:或者从
COBOL CopyBooks重新创建 J2C
Record和
FormatHandler助手类。
- 最后,在 WebSphere Studio 中进行正常的生命周期维护。
1. 选项 3A:将 CCF
RecordJAR 导入到 WebSphere Studio Service 项目
- WebSphere Studio CMA 插件:确保它
WebSphere Studio Setup期间安装。
- WebSphere Studio
CICSRAR 项目:确保它在
WebSphere Studio Setup期间安装。
- 注意只在运行 WebSphere Studio 工具来手动重建
Record(代替使用 CMA 对它们进行迁移)时才需要这一步。
- 注意此步骤
不需要最终 JMS 应用程序包含任何 CICS 代码或运行时。
- 创建您想要的 J2C Service 项目:
- 单击
File =>New =>Project =>Business Integration =>Service Project =>Next,并在
Project Name 中键入
JMSadderService ,然后单击
Finish。
- (作为一个文件系统文件)导入 CCF 构件 JAR:
- 选择新的
JMSadderService项目,然后单击
File =>Import =>File system =>Next。定位到您的
C:\CCF\MQadderClasses.jar文件,然后单击
Finish 导入并保留为 JAR 文件。
- 您现在可以向下跳到
CMA 迁移
Record
1. 选项 3B:将 COBOL CopyBooks 导入到 WebSphere Studio Service 项目
- 创建您所需的 J2C Service 项目:单击
File =>New =>Project =>Business Integration =>Service Project =>Next,然后在
Project Name 键入
JMSadderService 并单击
Finish。
- 导入 VisualAge for Java(或原始的)
COBOL CopyBook(作为一个文件系统文件):
选择新的
JMSadderService项目,并单击
File =>Import =>File system =>Next。定位到您的
C:\vaj40\eab\samples\com\ibm\ivj\examples\eab\adder\adder.ccp文件,然后单击
Finish 导入并保留为 JAR 文件。
- 您现在可以向下跳到
WebSphere Studio 重建
Record
2. 选项 3A - CMA 将 CCF
Record迁移到 J2C(Service)
Record
- 选择
MQadderClasses.jar并右键单击它,然后单击
Migrate CCF artifacts。
- VisualAge for Java 可以使用几种不同方式的访问器方法来生成代码。然而,我们将不使用产生的(CICS)
Command,因此迁移方式无关紧要。选择缺省的
shorten names compatibility option单选按钮并单击
Next。
- 我们又一次不使用产生的(CICS)
Command,因此该 JNDI 选项无关紧要。选择
Do not generate JNDI Name entry,然后单击
Finish。
- CMA 迁移将继续进行,然后结束(带有一个警告对话框)
警告对话框是因为 CCF MQ
Command不能被迁移(因为没有 J2C MQ 连接器,因此
Command是无效的,因此不能被例示或迁移)。要经常仔细阅读任何错误或警告对话,但是这一个是可以接受的。
结果是创建了
DummyCommand00000、
AdderRecord和
AdderRecordFormatHandlerJava 类,以及
WSDL元数据文件。
在这个阶段已经有了有用的
Record及
Format Handler助手类用于 MQ
Adder程序,但是“
DummyCommand00000”仅用于 CICS,并且对我们没有用(在下一部分
创建 JMS Command我们需要手动创建一个 JMS
Command)。您可以删除这三个
WSDL文件(因为它们仅对于创建 CICS 服务代理有用),以及
DummyCommand00000文件,但是首先请浏览它,并注意它的所有方法都仅适用于 J2C 形式的 Service Proxy(在此处,它是一个 CICS 的),并且
execute 方法的内容完全特定于 J2C。
2. 选项 3B:使用 WebSphere Studio 来从
COBOL CopyBooks重新创建 J2C
注意:如果您使用以前的部分 CMA 迁移 CCF
Record(代替使用 WebSphere Studio 工具来重新创建
Record),请跳跃到
步骤 4. Command
您必须已经从 VisualAge for Java 导出了原始的 COBOL(或 C)主机记录
CopyBooks,否则您必须从主机服务器将它们再次复制下来。您于是可以使用 WebSphere Studio 工具来处理它们并创建 J2C(Service)
Record和
FormatHandler助手类。(就像您正在创建一个 CICS 或 IMS Service)。遗憾的是,产生的结果
AdderCommand文件对我们没有用。
重新创建
Record作为 J2C(Service)构件的基本步骤如下:
- 为一个(虚拟)
Command创建一个 CICS(或 IMS)J2C Service Proxy。
- 为它添加一个(或多个)新的
Operation。
- 在创建新的
Operation时,指定
CopyBooks用于输入和/或输出。
- 请仔细选择正确的
平台、
编码等等。
- 删除不需要的(虚拟)
Command和
WSDL文件。
- 保留
Record和
FormatHandler助手类(这就是我们这样做的原因)。
如下说明对于
Adder示例足够了——它们的目的不是在于解释 WebSphere Studio 工具的细节(要了解细节,请参考 WebSphere Studio 文档和样本)。
- 我们将使用与我们在前面的“导入”部分所创建的相同
JMSadderServiceService 项目。
-
注意:如果您在最后部分运行 CMA 程序来迁移 MQ
Adder构件,那么请删除
JMSadderService 项目中的整个“
com.ibm.ivj... ”树。
- 创建一个 Java 包来保存我们的新 J2C 构件,通过单击
File =>New =>Package然后在
Name 键入
com.ibm.studio.sample.jms.adder 并单击
Finish 来创建 Java 包。我们现在已经准备好创建我们的 J2C 构件。
- 通过以下步骤来创建 CICS Service Proxy:单击
File => New => Business Integration => Service built from ... => Next => CICS ECI => Next
> (Connection Properties) Next 然后在
Package 键入
com.ibm.studio.sample.jms.adder 并为
Interface Name 键入
Adder ,然后单击
Finish。
- 当 Service Proxy 创建完毕时,它会在
WSDL Editor中打开。
- 在能够使用它之前,我们需要将一个
Operation(包含一个
CopyBook)添加到它里面。
- 按照如下步骤在
AdderCICSECIBinding.wsdlEditor 中创建一个新的操作:单击
Bindings (tab) =>Available operations =>New,然后在
Operation name 中键入
adderOperation ,再单击
Next (Binding properties) =>Next =>Input message =>Import。
- 导入原始的主机 COBOL CopyBook
JMSadderservice\adder.ccp =>Next并选择
DFHCOMMAREA。然后在
XSD type name 中键入
AdderRecord 并单击
Finish =>Use input message for output =>Next =>Finish。
-
重要:如果您的 MQ message 是一个 TextMessage,那么仅接受缺省的编码,并且在它迁移到/自不同的平台(例如,来自 Windows ASCII 到 zOS EBCDIC 等等)时 MQ 将自动覆盖 Text。
- 记得关闭编辑器窗口(
AdderCICSECIBinding.wsdl)。
- 通过单击
AdderCICSECIService.wsdl =>Enterprise Services =>Generate HelperClasses来生成
Record和
FormatHandler助手类。产生的结果是我们希望得到的
HelperClasses。
不同的
WSDL文件是特定于 CICS 的,并且对我们没有用处。这时通常会删除它们。不过,我们将使用它们,目的只是演示结果(CICS)ServiceProxy
Command的生成。
如果工业 J2C 标准将 JMS 合并为其下的一个传输(正在进行这方面的讨论),并且
如果WebSphere Studio 将 JMS 连接器添加到它的 Service Proxy 工具中,则这可能在未来对我们非常有用。请注意这
不是IBM 的一个承诺或发展方向声明——它仅仅是一个关于 J2C 工业标准的可能发展方向的表示。
- (可选)CICS Service Proxy
Command生成演示。在
JMSadderService项目中,单击
AdderCICSECIService.wsdl =>Enterprise Services =>Generate Service Proxy。在
Class Name 中键入
AdderCommand.java ,然后单击
Command bean =>newOperation =>Finish。
- 得到的结果是一个 CICS
Command,它与前面选项 #1
CMA迁移步骤中的 CMA 程序所生成的内容几乎一样。
- 两个不同的选项到达同样的目标——有用的 J2C
Record和
recordformathandler助手类,不需要的(CICS)
Command。
3. 在 WebSphere Studio 中进行 J2C
Record构件维护
现在,您只需要对 WebSphere Studio 中的 J2C
Record构件进行正常的生命周期维护。
步骤 4. 创建 JMS Command(使用 JMS Command 指导原则)
背景:MQ 构建和运行时 JAR
注意:不论您选择下面哪个
Command方式,您都需要将两个 MQ 构建和运行时 JAR 添加到您的
JMSadderService 项目。同样,由于我们实际上将不会使用一个真正的 J2C 服务,因此不需要一些其他 Services JAR,因此您可以随意地将它们移除。以下捕获屏幕显示了您必须有的 JAR。
右键单击
JMSadderService项目,然后单击
Properties =>Java build path。单击
Libraries选项卡,然后单击
Add External JARs 添加 WebSphere Application
Server MQ-JMS 运行时库 JAR
com.ibm.mq.jar和
com.ibm.mqjms.jar。
背景:简化的应用程序访问
Record(Byte Buffer)
注意:
Command类必须具有发送和接收
消息的能力。然而,我们可以使用 WebSphere Studio
Service 工具来生成
Record和
FormatHandler助手类,它们协调 Java 和 COBOL 表示,并且大大简化了应用程序对 Message 数据的访问。
下面的普通代码展示了如何使用 WebSphere Studio 生成的助手类来访问消息缓冲区:
try {
// Use the format handler to get to the adder record
AdderRecordFormatHandler InFH = new AdderRecordFormatHandler();
AdderRecord rec = (AdderRecord) InFH.getObjectPart();
// Here is the byte buffer (if direct access is required)
byte [] b = InFH.getBytes();
// Set some values in the adder record (or manipulate directly)
rec.setOp1(123);
rec.setOp2(456);
// Serialize the values into the formathandler
rec.fireElementEvents();
// Do whatever is needed. Typical sequence is:
// ... create session+sender+message+send, create receiver+receive
// process reply
b = new byte[512];
int count = replyMessage.readBytes(b);
// Use the formathandler to deserialize the result
AdderRecordFormatHandler OutFH = new AdderRecordFormatHandler();
OutFH.setBytes( replyMessage.getBytes() );
AdderRecord rec1 = (AdderRecord) OutFH.getObjectPart();
System.out.print( "res..."+rec1.getRes());
} catch (Exception ex ){
ex.printStackTrace();
} |
|
背景:设计
Command(直接、JNDI、J2C 调用兼容性)
您现在必须手动创建特定于应用程序的
Command。我们为
Adder样本提供“Cut-And-Paste”代码,您可以在您自己的
Command中方便地使用。
1. 对于您的代码如何定位它的 MQ
Connection和
Queue,您有两种选择:
- 选项 4A:简单地在目标中硬编码。
- 选项 4B:或者使用
JNDI来动态地查找管理位置(需要一个正在运行的带有 JMS 服务的 JNDI 服务器)。
注意:您选择的技术对于
Command实现完全是内部的,并且对于调用应用程序是不可见的。
2. 您必须选择如何组织您的
Command:
- 使它们
与 CCF 兼容,这有可能使应用程序迁移更改减到最少。
- 或者让它们
与 J2C 调用兼容,如果 J2C 工业标准合并 JMS 作为一个传送器,并且 WebSphere Studio 为其生成
Command Service Proxies,则用它来模仿
可能生成什么。(记住,这
不是 IBM 的一个承诺或发展方向声明)。
注意:我们将推迟这一选项(J2C 兼容性)直到我们讨论
应用程序迁移
,这是因为它与应用程序所使用的特定
Command Method调用方式直接相关。
选项 4A:基本(非 JNDI)命令
- 期望的 Command 结构(类似于 CCF Command):
- 公共“访问器”——除了“Execute”外的所有操作:
public class AdderCommand {
private AdderRecord _adderCommandRequestPart;
public
int getRes()
{
return _adderCommandRequestPart.getRes();
}
public void
setOp1(int i)
{
_adderCommandRequestPart.setOp1(i);
System.out.println("Debug: JMSAdderCommand.setOp1="+i);
}
public void
setOp2(int i)
{
_adderCommandRequestPart.setOp2(i);
System.out.println("Debug: JMSAdderCommand.setOp2="+i);
}
public AdderCommand() {
_adderCommandRequestPart = new AdderRecord();
}
|
|
- 主要可调用“Execute”:
public void execute() throws JMSException
{
// ### set RequestMessage
AdderRecordFormatHandler handler = new AdderRecordFormatHandler();
handler.setObjectPart(_adderCommandRequestPart);
_adderCommandRequestPart.fireElementEvents();
try
{
// #### sendMessage and WaitResponse
String reply =
sendMessageWaitResponse(
"ADDER.REQUEST", "ADDER.REPLY",
handler.getBytes());
// #### get ResponseMessage
handler = new AdderRecordFormatHandler();
handler.setBytes(reply.getBytes());
_adderCommandRequestPart = (AdderRecord)handler.getObjectPart();
} catch (Exception e) {
String msg = e.getMessage();
if(e instanceof JMSException) {
msg = ((JMSException)e).getLinkedException().getMessage();
}
System.out.println("JMSAdderCommand.executeMQ Exception="+msg);
}
}
|
|
- 内部“SendMessage 和 WaitResponse”:
private String sendMessageWaitResponse(
String REQname, String REPname,
byte[] messageBytes) throws JMSException
{
QueueConnection conn = null;
QueueSession session = null;
try
{
// ### getConnection
conn =
getConnection()
;
conn.start();
// ### getQueues
Queue queue =
getQueue(REQname)
;
Queue replyQueue =
getQueue(REPname)
;
// ### createQueueSession and createTextMessage
session = conn.createQueueSession(
false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
TextMessage message = session.createTextMessage(
new String(messageBytes));
message.setJMSReplyTo(replyQueue);
// ### send message
sender.send(message);
// ### createReceiver and receive replyMessage
QueueReceiver rcvr = session.createReceiver(replyQueue);
BytesMessage replyMessage = (BytesMessage)rcvr
.receive(25000);
byte[] b = new byte[512];
int count = replyMessage.readBytes(b);
// ### return replyMessage
return (replyMessage != null) ? new String(b) : null;
} catch (JMSException e) {
if (session != null)
session.close();
if (conn != null)
conn.stop();
conn.close();
throw e;
}
}
|
|
- 内部“GetConnection”:
private QueueConnection getConnection() throws JMSException
{
QueueConnectionFactory fact;
QueueConnection connection;
try
{
MQQueueConnectionFactory factory = new MQQueueConnectionFactory();
factory.setCCSID(
819
); // hardcoded
factory.setChannel(
"SYSTEM.AUTO.SVRCONN"
); // hardcoded
factory.setHostName(
"bcsearle.torolab.ibm.com"
); // hardcoded
factory.setPort(
1414
); // hardcoded
factory.setQueueManager(
"QM_bcsearle"
); // hardcoded
factory.setTransportType(
JMSC.MQJMS_TP_CLIENT_MQ_TCPIP
); // hardcoded
QueueConnection conn = factory.createQueueConnection();
System.out.println("Debug: QueueConnection=" + conn);
return conn;
} catch (JMSException e) {
System.out.println("JMSAdderCommand.getConnection Exception=" + e);
throw e;
}
}
|
|
- 内部“GetQueue”:
private Queue getQueue(String queueName) throws JMSException
{
MQQueue queue = null;
try {
queue = new MQQueue();
queue.setBaseQueueName(queueName);
queue.setBaseQueueManagerName(
"
QM_bcsearle"
); // hardcoded
queue.setCCSID(
819
); // hardcoded
queue.setTargetClient(
JMSC.MQJMS_CLIENT_NONJMS_MQ
); // hardcoded
System.out.println("Debug: Queue=" + queue);
return queue;
} catch (JMSException e) {
System.out.println("JMSAdderCommand.getQueue Exception=" + e);
throw e;
}
}
|
|
选项 4B:增强的(JNDI)Command
通过使用 JNDI 来查找
Connection和
Queue值,代码将更易维护。然而它需要运行一个
JNDI服务器(就像 WebSphere Application Server 中所包含的),并将其配置为包含期望的值。同样,JNDI 服务器必须也是一个
JMS 提供者(WebSphere Application Server 就是一个),以在 JNDI 查找期间创建所需的资源。
- JNDI 的 WAS
adminconsole 设置用于 ConnectionFactory:
- JNDI 的 WAS
adminconsole设置用于 RequestQueue(
TargetClient=MQ 错误以后讨论):
- JNDI 的相似 WAS
adminconsole 设置用于 ReplyQueue——本质上相同,只是用
ADDER.REPLY 代替
ADDER.REQUEST
- 取决于正在运行的 WebSphere Application Server
adminconsole的版本和服务包,有一个错误,正在进行的
TargetClient=MQ 没有保存。管理员必须手动编辑
resource.xml 以插入正确的数据(在 WebSphere Studio 中该文件通常是“
MyServersProject\MyBaseV5Server.wsc\cells\localhost\nodes\localhost\resources.xml ”)。
<factories xmi:type="resources.jms.mqseries:MQQueue" xmi:id="MQQueue_1"
name="MQ.ADDER.REQUEST" jndiName="mq/MQ.ADDER.REQUEST"
description="MQ.ADDER.REQUEST" persistence="QUEUE_DEFINED"
priority="QUEUE_DEFINED" expiry="APPLICATION_DEFINED"
baseQueueName="ADDER.REQUEST" baseQueueManagerName="QM_bcsearle"
useNativeEncoding="true" integerEncoding="Normal"
decimalEncoding="Normal" floatingPointEncoding="IEEENormal"
targetClient="MQ"
queueManagerHost="bcsearle.torolab.ibm.com"
queueManagerPort="1414"
serverConnectionChannelName="SYSTEM.AUTO.SVRCONN"/>
<factories xmi:type="resources.jms.mqseries:MQQueue" xmi:id="MQQueue_2"
name="MQ.ADDER.REPLY" jndiName="mq/MQ.ADDER.REPLY"
description="MQ.ADDER.REPLY" persistence="QUEUE_DEFINED"
priority="QUEUE_DEFINED" expiry="APPLICATION_DEFINED"
baseQueueName="ADDER.REPLY" baseQueueManagerName="QM_bcsearle"
useNativeEncoding="true" integerEncoding="Normal"
decimalEncoding="Normal" floatingPointEncoding="IEEENormal"
targetClient="MQ"
queueManagerHost="bcsearle.torolab.ibm.com"
queueManagerPort="1414"
serverConnectionChannelName="SYSTEM.AUTO.SVRCONN"/>
|
|
- 新的带有硬编码选项的 JNDI InitialContext(我们只看到系统缺省选项):
private static InitialContext _initialContext = null;
private InitialContext getInitContext() throws NamingException
{
if(_initialContext == null) {
//##############################################################
// Hashtable env = new Hashtable();
// env.put(Context.INITIAL_CONTEXT_FACTORY,
// com.ibm.websphere.naming.WsnInitialContextFactory");
// env.put(Context.PROVIDER_URL, "corbaloc:iiop:localhost:2809");
// String NAME_SYNTAX = "com.ibm.websphere.naming.name.syntax";
// String NAME_SYNTAX_JNDI = "jndi";
// env.put(NAME_SYNTAX, NAME_SYNTAX_JNDI);
// _initialContext = new InitialContext(env);
//##############################################################
_initialContext =
new InitialContext()
;
}
return _initialContext;
}
|
|
- 增强的 JNDI Execute(在 ConnectionFactory JNDI 名称中传送):
public void execute() throws JMSException
{
// ### set RequestMessage
AdderRecordFormatHandler handler = new AdderRecordFormatHandler();
handler.setObjectPart(_adderCommandRequestPart);
_adderCommandRequestPart.fireElementEvents();
try
{
// #### sendMessage and WaitResponse
String reply = sendMessageWaitResponse(
"mq/MQ.ADDER.CF",
"mq/MQ.ADDER.REQUEST", "mq/MQ.ADDER.REPLY",
handler.getBytes());
// #### get ResponseMessage
handler = new AdderRecordFormatHandler();
handler.setBytes(reply.getBytes());
_adderCommandRequestPart = (AdderRecord)handler.getObjectPart();
} catch (Exception e) {
String msg = e.getMessage();
if(e instanceof JMSException) {
msg = ((JMSException)e).getLinkedException().getMessage();
}
System.out.println("JMSAdderCommand.executeMQ Exception="+msg);
}
}
|
|
- 增强的 JNDI SendMessage 和 WaitReply(将 ConnectionFactory JNDI 名称传送到 GetConnection):
private String sendMessageWaitResponse(
String CFname
String REQname, String REPname,
byte[] messageBytes) throws JMSException
{
QueueConnection conn = null;
QueueSession session = null;
try
{
// ### getConnection
conn = getConnection(
CFname
);
conn.start();
// ### getQueues
Queue queue = getQueue(REQname);
Queue replyQueue = getQueue(REPname);
// ### createQueueSession and createTextMessage
session = conn.createQueueSession(
false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
TextMessage message = session.createTextMessage(
new String(messageBytes));
message.setJMSReplyTo(replyQueue);
// ### send message
sender.send(message);
// ### createReceiver and receive replyMessage
QueueReceiver receiver = session.createReceiver(replyQueue);
BytesMessage replyMessage = (BytesMessage)receiver
.receive(25000);
byte[] b = new byte[512];
int count = replyMessage.readBytes(b);
// ### return replyMessage
return (replyMessage != null) ? new String(b) : null;
} catch (JMSException e) {
if (session != null)
session.close();
if (conn != null)
conn.stop();
conn.close();
throw e;
}
}
|
|
- 增强的 JNDI GetConnection(使用 JNDI ConnectionFactory 查找名称):
private QueueConnection getConnection(
String connName
) throws JMSException
{
QueueConnectionFactory fact;
QueueConnection connection;
try {
fact = (QueueConnectionFactory) getInitContext()
.lookup(connName);
connection = fact.createQueueConnection();
System.out.println("JNDI ConnectionFactory="+fact );
return connection;
} catch (NamingException e) {
System.out.println("getConnection NamingException="+e.getMessage() );
throw new JMSException( e.getMessage() );
}
}
|
|
- 增强的 JNDI GetQueue(使用 JNDI Queue 查找名称):
private Queue getQueue(String queueName) throws JMSException
{
MQQueue queue = null;
try {
queue = (MQQueue) getInitContext()
.lookup(queueName);
System.out.println("JNDI Queue="+queue);
return queue;
} catch (NamingException e) {
System.out.println("getQueue NamingException="+e.getMessage() );
throw new JMSException( e.getMessage() );
}
}
|
|
-
重要:即使正确地构建了所有的东西,您可能还会遇到不清楚的
JNDI 运行时错误。您必须将必要的 JNDI 运行时支持 JAR 添加到您的构建和运行时类路径中:
- 右键单击
JMSadderExecute项目,然后单击
Properties =>Java build path。单击
Libraries选项卡并单击
Add External JARs添加 WebSphere Application Server 运行时库 JAR
namingclient.jar、messagingImpl.jar和
WAS_V5_IMPL_FACTORY_PROP CLASSPATH_VARIABLE。
我们现在有一个有效的
Command、以及前面的
Record和
FormatHandler助手类,但是我们仍然需要
迁移一个实际使用它的应用程序(下面步骤 5)。
步骤 5. 迁移 CCF MQ 应用程序以使用 JMS 构件(遵循迁移编码指导原则)
- 导入 VisualAge for Java 所导出的 MQ 应用程序 JAR。
- 遵循
从 CCF 迁移到 JMS 应用程序指导原则修改 CCF MQ 应用程序以使用迁移的 JMS 构件。
- 最快速的迁移调用
Command中的
CCF 兼容性方法。
-
Enhancement-5A:或者对于
可能的未来J2C JMS 服务兼容性,调用
Command中的
J2C Style Methods
。
1. 将 CCF MQ 应用程序导入到 Java(或 Web)项目
- 创建所需的应用程序 Web 或 Java 项目:
- 单击
File =>New =>Project =>Java =>Java Project =>Next,然后在
Project Name 中键入
JMSadderExecute 并单击
Finish。
- 单击
Next,然后单击
Projects选项卡。选择
JMSadderService并单击
Finish。这样做将添加构建和运行时相关
JMSadderService项目。
- 从 JAR 文件导入 CCF 应用程序:
- 选择新的
JMSadderExecute项目。
- 单击
File =>Import =>Zip file =>Next,然后定位到您的
C:\CCF\MQadderExecute.jar 文件。
- 单击
Open =>Finish导入应用程序(只有一个 MQ
Adder样本的
AdderExecute.java 文件)。
2. 使用
从 CCF MQ 迁移到 JMS 应用程序指导原则来迁移应用程序
- 因为我们选择更改位于重命名的
com.ibm.studio.sample.jms.adder 包中的 JMSadderService
Record和
Command代码,所以我们的应用程序包含错误。它不能解析这些名称(因为
AdderExecute 仍然在
com.ibm.ivj.eab.sample.mq.adder 中)。为了一致性,我们将重命名该包(重新构造它),以与新的名称相匹配:
- 在第一行(
Package 声明),选择
com.ibm.ivj.eab.sample.mq.adder 。
- 右键单击和单击
Refactor =>Rename...。键入新的名称
com.ibm.studio.sample.jms.adder 。
- 单击
Finish。
- 一个典型的错误(如下所示)源于需要构建和运行时访问
javax.jms.JMSException以及其他的
JMS 类:
- 一个典型的节省时间的方法是定义一个工作台环境变量(为达到这一目的,请单击
Window =>Preferences =>Java =>Classpath Variables,然后单击
New 并将它命名为
WAS_50_PLUGINDIR )来允许添加库 JAR 作为
Add Variable =>Extend =>WAS_50_PLUGINDIR\lib扩展。
- 右键单击
JMSadderExecute项目,然后单击
Properties =>Java build path。单击
Libraries选项卡并单击
Add External JARs 添加 WebSphere Application
Server 运行时库 JAR
j2ee.jar。
- 另一组标准错误(如下图所示)是要求我们删除所有旧的
com.ibm.connector.* 导入项。
- 同时还有一组标准错误(如下图所示)是要求我们删除所有旧的
JavaRuntimeContext代码(在我们的样本中需要注释掉 3 个
RuntimeContext 行)。
- 另一组标准错误(如下图所示)是要求我们处理
javax.jms.JMSException。这也要求添加一条
import javax.jms.JMSException 语句。
// execute the command and get the result
System.out.println("Executing the Adder command, op1="
+op1+" op2="+op2+" ...");
try {
adder.execute();
} catch (JMSException e) {
System.out.println("JMSException="+e.getMessage() );
}
System.out.println("Adder result: "
+ adder.getAdderCommandRequestPart().getRes());
|
|
-
最佳实践:最外面的代码捕获
JMSException(从
Command.execute()),但是通常来说它也必须捕捉其他异常(包括
Exception)。一个
JMSException,就其本身来说通常并不能给我们提供多少信息。但最佳实践包含了一个
LinkedException,它能够给我们提供更多的信息(因为它是一个真实的错误),所以我们应该获取并显示它。最佳实践就是始终设法从任何捕捉到的
异常中提取包含更多信息的消息。
// execute the command and get the result
System.out.println("Executing the Adder command, op1="
+op1+" op2="+op2+" ...");
try {
adder.execute();
} catch (Exception e) {
String msg = e.getMessage();
if(e instanceof JMSException) {
JMSException je = (JMSException)e;
Exception le = je.getLinkedException();
msg = le.getMessage();
}
System.out.println("Exception="+msg );
}
System.out.println("Adder result: "
+ adder.getAdderCommandRequestPart().getRes());
|
|
3. 增强-5A:J2C 方式调用
J2C 期望的 Command 结构(包含 J2C 方式方法):
新的 J2C 调用方式方法(代替已弃用的 CCF 方法)
public void
setAdderCommandRequestPart(Object record)
{
_adderCommandRequestPart = (AdderRecord)record;
}
public AdderRecord
getAdderCommandRequestPart()
{
return _adderCommandRequestPart;
}
|
|
使用 J2C 方式调用:
- 一组标准的不赞成警告(如下所示)与新的 J2C 命令调用方式相关。
从 CCF 迁移到 JMS 应用程序指导原则描述了为使用 J2C 调用方式操作
Command
和
Record而需要对标准应用程序进行的更改。
- 您可能选择将
CCF 兼容性方法放置到您的
Command中来使短期应用程序改动的时间减到最少(从而加速应用程序从原始的 CCF 迁移到 J2C 的过程)。使用这些短期的(已弃用的)
CCF 兼容性方法的应用程序必须在应用程序生命周期维护期间被移走,以便使用当前的 J2C 调用方式。
-
重要:J2C 调用方式的整个概念只有在您关心 J2C 调用兼容性时适用,因为您相信在未来您可能更改到 J2C 生成的
Command(例如,如果/当 JMS 成为 J2C 下面的传输器,并且如果/当 J2C 工具为它生成服务代理时)。
- 例如,旧的 CCF
Command.setOperand()和
Command.execute(CommandEvent)模式已被废弃:
- 最佳 J2C 实践是新的 J2C 调用
新的 Record()和
Record.setOperand() 和
Command.setAdderCommandRequestPart(Record)和
Command.execute()
- 另一个示例,旧的 CCF
Command.getRes() 模式已被废弃:
- 最佳 J2C 实践是新的 J2C 调用
Command.getAdderCommandRequestPart()。
-
重要:添加上述 J2C 调用方式还需要将标准的 J2C/WSIF JAR 添加到
JMSadderExecute构建和运行时类路径(除了前面的
JNDI 运行时 Jar)。
- 右键单击
JMSadderExecute项目,然后单击
Properties =>Java build path。单击
Libraries选项卡并单击
Add External JARs 添加 WebSphere Application
Server 运行时库 JAR
wsatlib.jar、wsif-j2c.jar和
wsif.jar。
- 删除所有注释代码之后,基本的代码看起来就像这样:
public static void main(java.lang.String[] args) {
int op1 = 10;
int op2 = 20;
if(args.length>=1) {
String s = args[0];
op1 = Integer.parseInt(s);
s = args[1];
op2 = Integer.parseInt(s);
}
System.out.println("Sample program to demonstrate"
+" commands using the MQ connector.");
System.out.println("Adder client program.");
// create a command that uses the SEND_RECEIVE mode the
// command will put a request message with op1 and op2
// to the ADDER.REQUEST queue, then get the reply
// message (with a result from ExecuteAdderServer)
// from the ADDER.REPLY queue.
AdderCommand adder = new AdderCommand();
AdderRecord record = new AdderRecord();
record.setOp1(op1);
record.setOp2(op2);
adder.setAdderCommandRequestPart(record);
// execute the command and get the result
System.out.println("Executing the Adder command, op1="
+op1+" op2="+op2+" ...");
try {
adder.execute();
} catch (JMSException e) {
Exception le = e.getLinkedException();
System.out.println("JMSException="+le.getMessage() );
}
System.out.println("Adder result: "
+ adder.getAdderCommandRequestPart().getRes());
}
|
|

 |

|
步骤 6. 部署和测试(执行)迁移的应用程序
如果您已经
正确设置了构建和运行时类路径,那么您现在可以只运行迁移了的 JMS 应用程序:
- 打开
ExecuteAdder.java程序并单击
Run。
-
重要:在
AdderExecute应用程序执行期间,如果
Run =>Classpath =>Use default classpath选项
没有被选中,那么您可能得到类似这样的错误:“
codepage-437 not available ”。确保您在缺省的类路径运行该文件(该路径包括完全代码页支持)。您需要确保使用了一个完整的 JDK,而不只是使用一个分离的系统 JVM JRE。
- IBM JDK 包括
jre\lib\codepage.jar 文件,它包含许多
ByteToCharCpXxxx类,其中包括
ByteToCharCp437.class
- Sun JRE 包括
lib\rt.jar 文件,它只包含 6 个
ByteToCharCp125X.class
-
重要:在
AdderExecute应用程序执行期间,如果您在使用 JNDI 并且您没有正确设置
JMSadderService
JNDI 构建和运行时类路径,则您可能会得到让您感到沮丧和难以理解的错误,如下所示:
- 丢失
namingclient.jar 引起“
NamingException=Need to specify class name in environment or system property,
java.naming.factory.initial ”。
注意:即使指定“
-DinitialContextFactory=com.ibm.websphere.naming.WsnInitialContextFactory ”,也不能解决这一容易让人误解的错误。
- 丢失
JNDI server (未运行)引起“
NamingException=Could not obtain an initial context due to a
communication failure ”。
- 丢失
messagingImpl.jar 引起“
NamingException=Failed to initialize the ORB ”。
- 丢失
WAS_V5_IMPL_FACTORY_PROP 引起“
NamingException=Could not obtain an initial context
due to a communication failure. Since no provider URL was specified, ... ”。
- 丢失
messagingImpl.jar(并且同样错误地包含
namingserver.jar)引起“
Exception=javax.naming.Reference ”。
其他 JMS 应用程序变体(Web、应用程序客户端)
我们在此不会详细讲述所有的细节,但是您可以创建一个
Web或一个
ApplicationClientJ2EE 项目(两者都需要在
Enterprise Application(EAR)项目中),并且简单地让它们调用
AdderExecute:
- 为了尝试
应用程序客户端,只需要创建一个
应用程序客户端项目,然后将
JMSadderService和
JMSadderExecute项目的 JAR 导入其中。创建一个
WebSphere v5 Application ClientLaunch Configuration 来运行它,将使用的
Main class 设置为
com.ibm.studio.sample.jms.adder.ExecuteAdder ,然后运行它。
- 为了尝试
Web,只需创建一个
Web Project,然后将
JMSadderService和
JMSadderExecute项目的 JAR 导入其中。还要创建一个 JSP 来调用
JMSadderExecute,然后选择那个 JSP 并单击
Run on Server ...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" %>
<LINK href="theme/Master.css" rel="stylesheet" type="text/css">
<TITLE>JMSadderExecuteWeb.jsp</TITLE>
</HEAD>
<%@ page import="com.ibm.studio.sample.jms.adder.ExecuteAdder" %>
<BODY>
<P>INVOKE ExecuteAdder ....</P>
<%
ExecuteAdder exec = new ExecuteAdder();
String[] args = {"12", "34"};
exec.main(args);
%>
<P>DONE.R ExecuteAdder (output is in CONSOLE VIEW)</P>
</BODY>
</HTML>
|
|
步骤 7. WebSphere Studio 中正在进行迁移的应用程序的生命周期维护
现在,您需要执行的步骤是在 WebSphere Studio 中对您的 JMS 应用程序进行正常的生命周期维护。有一点需要特别注意,如果您使用
CCF 兼容性方法方式调用来加速初始应用程序的迁移,则在方便的时候您应该将它们替换为正常的 J2C 方式的 Command 和 Record 调用。由于同时使用两种调用方式,所以您可以一次替换几个。
CMA 的局限性和指导原则
如果有新的
重要的 JMS CMA 局限性或指导原则,这一部分将会进行更新。
注意:CMA 插件包含在线文档,这是关于已知的 CMA 局限性、问题和指导原则的最详细和最新的定义。
当前已知的最重要的特定于 JMS 的 CMA 局限性和指导原则可以归纳如下:
- 只能迁移
Record,不能迁移 MQ
Command(因为没有 J2C MQ 或 JMS 连接器)。
当前已知的最重要的一般 CMA 局限性和指导原则可以归纳如下:
- 只有 CCF
IMS(或
CICS-ECI或
Beta-JCA)构件(请参阅
CICS-ECI 文章以或关于 CICS-ECI 的具体情况),而没有 CICS-
EPI、HOD-3270 和 MQ Command。
- 只有
COBOL记录(没有
C和
PL/I)。
-
固定长度和
动态记录必须使用正常生成的访问器(任何基本框架访问都需要手动迁移)。
- 所有的
Record都必须有
RecordType(
RecordInfo)(否则它们在迁移时会被跳过而需要手动迁移)。
- 只有
缺省映射是受
RecordTypes支持的(每个
首选类型更改后都需要手动迁移)。
- 没有
层次样式的记录(需要进行手动迁移)。
- CCF 构件中的
自定义方法不会被保持(需要手动复制)。
- 没有 CCF
Navigator迁移(需要手动迁移,最合适的是迁移到
Processes)。
- 没有 CCF
Mapper迁移(需要手动迁移,最合适的是迁移到
Transformers)。
- 没有 EAB
SessionBean和
BusinessObject迁移(需要手动迁移)。
- 如果 EAB
SessionBeans是通过使用
Command包装生成的,则这些
Command可以被迁移,并可在 WebSphere Studio 中部署生成的代码。
- 如果 EAB
SessionBeans是通过使用
CustomUserMethods 生成的,则所有的代码都是内嵌的并使用用户方法来命名,所以是不可能自动迁移的。
- 如果匹配的
SessionBeans 是在 WebSphere Studio 中手动重新生成的,则用户应用程序就可以很容易地进行迁移,通常不需要改动 SessionBean 调用。
- 通过
提升的 Record 特性生成的 CCF Command 可能要求手动更改应用程序。
- 根据
服务器和
事务名称来组织和导出 CCF 构件(CMA 采用通用的
JNDI ConnectionFactory)。
- 根据
名称样式来组织和导出 CCF 构件(CMA 在整个 CCF JAR 范围内采用单一的
名称样式)。
- CMA 以及它的文档
只有英文版的(它并不是正式发布的产品)。
- CMA 在
不受官方支持,它提供仅此状态授权(您不能调用 IBM 支持和向其报告 PMR 问题)。
-
记住: CMA 在线文档是当前的局限性和指导原则的最终来源。如果有疑问,请参阅在线文档而不是本文(因为本文可能已经过时了)。

 |

|
应用程序的局限性和指导原则
如果有新的
重要的 JMS 应用程序局限性或指导原则,这一部分可能会进行更新。
注意:CMA 插件包含在线文档,这是关于已知的应用程序局限性、问题和指导原则的最详细和最新的定义。
当前已知的最重要的特定于 JMS 的应用程序局限性和指导原则可以归纳如下:
- 同时参考
JMS 应用程序资源部分。
- 捕捉
JMSException(而非旧的
CCFException)。同样,提取它嵌入的
LinkedException以获得真实错误。
- 如果您的 MQ 消息是一个
TextMessage,然后当创建 Service Proxy 操作并导入
CopyBook时,只要接受缺省的编码,而 MQ 将自动转换 Text,就像它到/来自不同的平台(例如,从 Windows ASCII 到 zOS EBCDIC 等等)。
- 事务:
- 当 JMS 是一个事务中的唯一参与者(例如,没有数据库更新),那么可以使用
本地 事务。JMS 通过一个
事务的 会话来支持这些本地事务,该会话可以由一个 QueueConnection 来创建。事务的会话管理所有发送和接收的消息,直到执行一次回滚或提交操作为止。由于 JMS 会话特定于连接,所以在点到点的 MQ 消息传递的情况下,一个简单的会话只能处理由单一队列管理器管理的队列。
- 当 JMS 不是一个事务的唯一参与者时(例如,还有数据库更新),那么 Java Transaction Service(JTS)必须用于控制所有已处理的资源。JMS 资源(比如连接工厂)
|