编写 Java 类来重定向 JVM stdout 和 stderr 输出

在 JVM 概要文件中使用 USEROUTPUTCLASS 选项来命名用于从 JVM 拦截 stdout 流和 stderr 流的 Java™ 类。 您可以更新此类以指定您选择的时间戳记和记录头以及重定向输出。

6.3 beta 对 USEROUTPUTCLASS 函数的支持已弃用。

CICS 提供可用于此目的的样本 Java 类 com.ibm.cics.samples.SJMergedStreamcom.ibm.cics.samples.SJTaskStream。 为 /usr/lpp/cicsts/cicsts64/samples/com.ibm.cics.samples 目录中的这两个类提供了样本源。 /usr/lpp/cicsts/cicsts64 目录是 z/OS UNIX 上 CICS 文件的安装目录。 此目录由 DFHISTAR 安装作业中的 USSDIR 参数指定。 样本类也作为类文件 com.ibm.cics.samples.jar 提供,该文件位于目录 /usr/lpp/cicsts/cicsts64/lib中。 您可以修改这些类,或者根据样本编写您自己的类。

控制 JVM 输出,日志,转储和跟踪的位置 具有有关以下内容的信息:
  • JVM 中由 USEROUTPUTCLASS 选项指定的类拦截的输出类型。 您使用的类必须能够处理它可能拦截的所有类型的输出。
  • 提供的样本类的行为。 com.ibm.cics.samples.SJMergedStream 类为 JVM 输出和错误消息创建两个合并的日志文件,每个记录上都有一个头,其中包含 APPLID ,日期,时间,事务标识,任务号和程序名。 如果有暂态数据队列,则使用暂态数据队列创建日志文件;如果没有暂态数据队列或 Java 应用程序无法使用暂态数据队列,则使用 z/OS UNIX 文件创建日志文件。 com.ibm.cics.samples.SJTaskStream 类将单个任务的输出导向 z/OS UNIX 文件,并添加时间戳和标头,以提供特定于单个任务的输出流。
要使 JVM 服务器使用输出重定向类,必须创建包含输出重定向类的 OSGi 捆绑软件。 您必须确保捆绑软件激活程序在框架中将类的实例注册为服务,并设置属性 com.ibm.cics.server.outputredirectionplugin.name=class_name。 您可以使用常量 com.ibm.cics.server.Constants.CICS_USER_OUTPUT_CLASSNAME_PROPERTY 来获取属性名称。 以下代码摘录显示了如何在捆绑软件激活程序中注册服务:
Properties serviceProperties = new Properties();
    serviceProperties.put(Constants.CICS_USER_OUTPUT_CLASSNAME_PROPERTY, MyOwnStreamPlugin.class.getName());
    context.registerService(OutputRedirectionPlugin.class.getName(), new MyOwnStreamPlugin(), serviceProperties);
您可以将 OSGi 捆绑软件添加到 JVM 概要文件中的 OSGI_BUNDLES 选项,或者确保在运行第一个任务时将捆绑软件安装在框架中。 无论使用哪种方法,仍必须在 USEROUTPUTCLASS 选项中指定类。
如果你决定写自己的课,你需要知道:
  • OutputRedirectionPlugin 接口
  • 输出的可能目标
  • 处理输出重定向错误和内部错误

输出重定向接口

CICS 在 com.ibm.cics.server.jar中提供了一个名为 com.ibm.cics.server.OutputRedirectionPlugin 的接口,可由拦截 JVM 的 stdout 和 stderr 输出的类实现。 提供的样本实现此接口。

提供了以下样本类:
  • 实现此接口的超类 com.ibm.cics.samples.SJStream
  • 子类 com.ibm.cics.samples.SJMergedStreamcom.ibm.cics.samples.SJTaskStream,它们是 JVM 概要文件中指定的类

与样本类一样,请确保您的类直接实现接口 OutputRedirectionPlugin ,或者扩展实现该接口的类。 您可以从超类 com.ibm.cics.samples.SJStream继承,也可以使用同一接口实现类结构。 使用任一方法,您的类都必须扩展 java.io.OutputStream

initRedirect() 方法接收由一个或多个输出重定向类使用的一组参数。 以下代码显示了接口:
package com.ibm.cics.server;

import java.io.*;

public interface OutputRedirectionPlugin {

  public boolean initRedirect( String inDest,
                            PrintStream inPS,
                            String inApplid,
                            String inProgramName,
                            Integer inTaskNumber,
                            String inTransid
                           );
  }               

超类 com.ibm.cics.samples.SJStream 包含 com.ibm.cics.samples.SJMergedStreamcom.ibm.cics.samples.SJTaskStream的公共组件。 它包含返回的 initRedirect() 方法false,这将有效禁用输出重定向,除非此方法被子类中的另一个方法覆盖。 它不会实现 writeRecord() 方法,此类方法必须由任何子类提供以控制输出重定向过程。 您可以在自己的类结构中使用此方法。 还可以使用构造函数而不是 initRedirect() 方法来执行输出重定向的初始化。

inPS 参数包含 JVM 的原始 System.out 打印流或原始 System.err 打印流。 您可以将日志记录写入这些底层日志记录目标中的任何一个。 不能对这些打印流中的任何一个调用 close() 方法,因为它们将永久关闭并且不可供进一步使用。

输出的可能目标

CICS提供的样本类将 JVM 的输出直接指向特定于 CICS 区域的目录; 目录名是使用与 CICS 区域关联的 APPLID 创建的。 在编写自己的类时,如果愿意,可以将多个 CICS 区域的输出发送到同一个 z/OS UNIX 目录或文件。

例如,您可能想要创建单个文件,其中包含与在多个不同 CICS 区域中运行的特定应用程序相关联的输出。

使用 Thread.start() 以编程方式启动的线程无法发出 CICS 请求。 对于这些应用程序, JVM 的输出由您为 USEROUTPUTCLASS 指定的类拦截,但无法使用 CICS 工具 (例如瞬时数据队列) 将其重定向。 您可以像提供的示例类一样,将这些应用程序的输出直接导入 z/OS UNIX 文件。

处理输出重定向错误和内部错误

如果您的类使用 CICS 设施来重定向输出,那么它们应包含相应的异常处理,以处理使用这些设施时发生的错误。

例如,如果要写入瞬时数据队列 CSJO 和 CSJE ,并对这些队列使用 CICS提供的定义,那么 TDQ.writeData:
  • IOErrorException
  • LengthErrorException
  • NoSpaceException
  • NotOpenException

如果您的类直接输出到 z/OS UNIX 文件,则应包含适当的异常处理,以处理写入 z/OS UNIX 时出现的错误。 这些错误的最常见原因是安全性异常。

将在命名 USEROUTPUTCLASS 选项上的类的 JVM 中运行的 Java 程序应包含相应的异常处理,以处理类可能抛出的任何异常。 CICS提供的样本类在内部处理异常,方法是使用 "尝试/捕获" 块来捕获所有可抛出的异常,然后编写一条或多条错误消息以报告问题。 在重定向输出消息时检测到错误时,会将这些错误消息写入 System.err,使其可用于重定向。 但是,如果在重定向错误消息时发现错误,那么会将报告此问题的消息写入正在处理请求的 JVM 所使用的 JVM 概要文件中的 STDERR 选项所指示的文件。 因为样本类以这种方式捕获所有错误,这意味着调用程序不需要处理输出重定向类抛出的任何异常。 您可以使用此方法来避免对调用程序进行更改。 请注意,不要通过尝试将类发出的错误消息重定向到发生故障的目标,将输出重定向类发送到循环中。