适宜读者:(一年及以上主机经验)
背景知识:(CICS基础知识)
你有曾想过要在CICS应用中重用现有的一些Java EE代码吗?或许,你需要实施一项新的应用特性,从COBOL程序中调用Java EE API。随着CICS TS V5.3功能的持续更新和扩充,现在你可以很方便的完成这些工作。本文中,您将看到如果要实现任一CICS程序能够调用运行在Liberty JVM服务器中的Java EE应用,我们需要做哪些准备工作。
在CICS中运行Java EE应用的要求
在你的项目中,是否可以运用此方法呢?在做决策的时候,需要考虑以下几个方面:首先,你的Java代码必须是POJO (Plain Old Java Object),封装在WAR 或者是EAR文件中。只有调用处理业务逻辑的Java 代码才是有意义的,而非网络层的代码比如servlet或是JAX-RS资源类。你可以调用Java代码作为交易的初始程序,也可以使用EXEC CICS LINK, START 和 START CHANNEL 等API。如果你想调用EJB,目前你必须创建一个POJO将其封装起来才能让CICS调用。如果你正在将应用从OSGi JVM服务器中移植过来,那么就需要略微修改一下应用,比如要更新标签,必须要使用CHANNEL 和 CONTAINER而非 COMMAREA。同样,你需要将其封装在POJO中并放到WAR文件里(这是因为目前Liberty尚未支持直接调用OSGi bundles)。
在交易处理方面,你会很高兴听到Java 代码将会在同一CICS任务中调用,与请求调用的应用处在同一UOW中。这意味着实现CICS资源的可恢复更新,既可以通过调用程序也可以使用Java的 JCICS API来实现。然而,目前在被LINK的Java应用中还不能使用CICS集成JTA。但是,你可以把JTA集成CICS功能关闭,只是这样JTA交易是独立运行的,不在CICS UOW之内。Java应用在使用DPL的CICS API时,不能使用全部API,只能使用部分子集,比如当UOW仍然在JVM服务器中运行时,无法使用Task.commit() 方法对UOW进行commit操作。另外,如果使用DPL方式LINK一个Java应用,无法使用SYNCONRETURN,因为Java应用不能做syncpoint操作。
环境准备阶段
首先,你需要将 APAR PI63005 的PTF部署到CICS TS V5.3系统上,或者尝试一下最新的CICS TS V5.4 Open Beta。此外,你还需要将 CICS Explorer 升级到版本 5.3.0.8,或者使用其最新的试用版。如果你正在使用CICS build toolkit, 版本 5.3.0.8以及试用版也同样提供此工具。
下一步,你需要一个 Liberty JVM 服务器。请查阅 CICS TS Knowledge Center 文章 Configuring a Liberty JVM server 了解具体的配置步骤。此外,你需要将 <feature>cicsts:link‐1.0</feature> 添加到 server.xml 文件中的featureManager 标签中。然后,你就可以 ENABLE 该 JVMSERVER 资源了。
Java代码准备阶段
为了让CICS程序可以调用 Java代码,你需要预处理Java代码。我们已尽力简化预处理阶段。我们建议将你的业务逻辑层封装在一个新的wrapper类中,这样你就可以将CICS相关的代码剥离开。 接下来你需要做的就是将 @CICSProgram 这个注解(annotation)加入CICS 要调用的 Java 方法(method)中。使用注解在 Java EE 开发中非常普遍,所以我们希望对大多数 Java 开发人员来说这不是个问题。使用注解可以帮助CICS在做 build 时,快速定位 Java 代码暴露的方法,同时CICS 会生成一些组件,以帮助 runtime 时成功调用此方法。CICS 甚至会自动创建一个 PROGRAM 资源,PROGRAM 的名称就是注解中的参数。
本文示例代码已打包为 zip 文件,您可下载并导入CICS Explorer。具体方法是:在CICS Explorer中,点击 File > Import>General>Existing projects,勾选 Select archive file。 以后,我们也会把这个例子放在 CICS Explorer 的 CICS Examples中,届时你可以通过新建CICS Example即可完成该示例项目的创建。否则,你需要将代码放到 Dynamic Web Project 中。
下面就是我们的Java 代码:
public class HelloLiberty
{
@CICSProgram("HELLOWLP")
public void printMessage()
{
StringBuilder sb = new StringBuilder();
sb.append("Hello ");
try
{
Channel currentChannel = Task.getTask().getCurrentChannel();
if (currentChannel != null && currentChannel.getContainer("NAME") != null)
{
Container nameContainer = currentChannel.getContainer("NAME");
sb.append(nameContainer.getString());
}
else
{
sb.append(Task.getTask().getUSERID().trim());
}
sb.append(" from Liberty server ");
sb.append(System.getProperty("com.ibm.cics.jvmserver.wlp.server.name"));
System.out.println(sb.toString());
} catch (InvalidRequestException | ContainerErrorException
| ChannelErrorException | CCSIDErrorException
| CodePageErrorException e)
{
e.printStackTrace();
Task.getTask().abend("OHNO");
}
}
}
你会注意到 printMessage()方法中的 @CICSProgram 注解。 @CICSProgram 中写明了 CICS PROGRAM 资源的名字 HELLOWLP,通过 LINK HELLOWLP,就可以调用 printMessage() 方法了。你可以给多个方法加注解,只要给予不同的程序名字就可以。
如果此前,在这一项目中你没有使用过任何注解,你必须开启注解处理。如下图,将光标移动到注解出现的警告上方,点击出现的快速修复链接。
观察 printMessage() 的代码,你会发现我们做的第一件事情就是拿到当前的channel。然后,我们从 channel 中拿到一个 container 用来保存输入数据。使用 channel 和 container 是实现 Java 代码与调用 Java 的 CICS 程序之间数据通信的最主要方式。在本例中,传递的数据是一简单字符串。然而,调用程序要传递包含多个字段的结构数据,那么你必须将其转化为 Java 友好的数据类型和对象。 有两个工具可以用来生成数据转化代码,详细信息请见: JZOS 和 J2C。
一旦我们从调用程序中拿到了数据,接下来就可以执行 Java 代码实现的业务逻辑。其中很可能会涉及到调用其它 Java 对象的方法,以及通过 JCICS API 与 CICS 资源交互。最后,我们反转数据传递流程,仍然将输出参数放入 channel 的container 中传回给调用程序。如果出现 exception,我们有几种处理方式可供选择。我们可以允许 exception 在队列中堆积起来,但是这将有可能造成 task 以 AJ05 abend 终止。另一种方式是: 我们可以捕获 exception 自己处理:一种可能就是返回给调用程序一个错误代码,或者就是放弃该 task,就如我们的示例代码中所做的。
应用部署阶段
现在你已经准备好部署应用了。 你可以用任何一种 Liberty 支持的方式将应用部署到 Liberty JVM 服务器中,比如通过CICS bundle 部署,或者在 server.xml 中编写 application element,或者使用 dropins folder。下面的例子中,我们描述的是用 CICS bundle 进行部署。你需要新建一个 CICS bundle 项目或者是更新某一 CICS bundle 项目。
然后,你需要增加一个 Dynamic Web Project Include,指向我们的Web项目并指出部署到的 JVM 服务器的名称。如果你用的是CICS提供的样本项目,包含该 include 的CICS bundle 已经提供你了,所以你只需要更修改在 com.ibm.cics.server.examples.wlp.link.warbundle 文件中 JVM 服务器的名称 ,将其指定为你所用的服务器。然后,你就可以部署该 bundle 项目了,从菜单栏中选择 Export Bundle Project to z/OS Unix File System。然后,你需要在CICS 系统中创建一个BUNDLE资源,指向你部署的 bundle 项目的 zFS 地址。然后,你要安装该 BUNDLE 资源。
当 CICS BUNDLE 资源的状态是 ENABLED, Web 应用程序就会安装到 Liberty 中去。 这将会触发 CICS 去检查 WAR,发现 annotation 处理器生成的组件(这是 @CICSProgram annotation产生的结果)。 CICS 会为每一个注解过的方法动态地创建一个 PROGRAM 资源。 你可以通过 CICS Explorer 提供的 PROGRAM 页面,以 JVM 服务器名称作为筛选条件,找到这些 PROGRAM 资源。
我们希望这些动态创建的 PROGRAM 资源会给你提供很多的方便。如果需要,你也可以自己定义和安装PROGRAM 资源。如果在Liberty 应用启用的这一刻,相同名称的PROGRAM资源已经安装好,CICS不会再去创建该 PROGRAM 资源。反而CICS会去检测该 PROGRAM 资源的属性是否合适,如果发现有问题会给 MSGUSR 发出警告。
试用样本应用
如果你已经部署了样本应用,现在你可以尝试运行该应用了。你可以使用CECI 调用该PROGRAM:
CECI LINK PROG(HELLOWLP)
然后在JVM服务器的STDOUT中查找下列消息:
Hello WILSON from Liberty server defaultServer
(WILSON是我的CICS 用户名)
如果你在channel中创建了名称为NAME的container,并且如下链接到该channel:
CECI PUT CONTAINER(NAME) CHAR FROM(MATTHEW) CHANNEL(CHAN)
CECI LINK PROG(HELLOWLP) CHANNEL(CHAN)
你可以在输出的消息中看到名称为NAME的 container中的内容:
Hello MATTHEW from Liberty server defaultServer
希望通过以上的介绍,你已经基本了解CICS程序调用 Java代码的流程,可以自己去尝试一下了。如果你需要了解更多的信息,请参阅 Invoking a Java EE application from a CICS program。
原文链接:https://developer.ibm.com/cics/2016/11/14/link-to-liberty-now-available-in-cics-ts-v5-3/
原作者:Matthew Wilson
编译:曹帅、李琴
邮箱:csshATcn.ibm.com, liqincdlATcn.ibm.com (替换AT为@)
内容声明:本文仅代表作者的个人观点,与IBM立场、策略和观点无关。文中专业名词因翻译原因,表述中难免存在差异。如有疑惑,请以英文为准。同时数据来源于实验室环境,仅供参考。如果您对我们的话题感兴趣,请通过电子邮箱联系我们。
Tags: 
api
linktoliberty
java
cics
liberty