

AWS 大型机现代化服务（托管运行时环境体验）不再向新客户开放。有关类似于 AWS 大型机现代化服务（托管运行时环境体验）的功能，请浏览 AWS 大型机现代化服务（自我管理体验）。现有客户可以继续正常使用该服务。有关更多信息，请参阅[AWS 大型机现代化可用性变更](https://docs.aws.amazon.com/m2/latest/userguide/mainframe-modernization-availability-change.html)。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# AWS 针对现代化应用程序的大型机结构进行转型
<a name="ba-shared-structure"></a>

本文档详细介绍了现代化应用程序的结构（使用 AWS 大型机现代化重构工具），以便开发人员可以完成各种任务，例如：
+ 顺畅地导航到应用程序。
+ 开发可从现代化应用程序中调用的自定义程序。
+ 安全地重构现代化应用程序。

我们假设您已经掌握了以下方面的基础知识：
+ 遗留的常见编码概念，例如记录、数据集及其对记录（索引、顺序）、VSAM、运行单元、jcl 脚本、CICS 概念等的访问模式。
+ 使用 [Spring 框架](https://spring.io/projects/spring-framework)进行 java 编码。
+ 为方便阅读，我们在整篇文档中使用了`short class names`。有关更多信息，请参阅[AWS 为大型机完全限定名称映射进行转换](#ba-shared-structure-fqn-table)检索大型机运行时元素的 Tr AWS ansform 的相应完全限定名称和[第三方完全限定名称映射](#ba-shared-structure-3pfqn-table)检索第三方元素的相应完全限定名称。
+ 所有工件和样本均取自示例 COBOL/CICS [CardDemo 应用程序](https://github.com/aws-samples/aws-mainframe-modernization-carddemo)的现代化过程输出。

**Topics**
+ [构件组织](#ba-shared-structure-org)
+ [运行和调用程序](#ba-shared-structure-run-call)
+ [自行编写程序](#ba-shared-structure-write)
+ [完全限定名称映射](#ba-shared-structure-fqn)

## 构件组织
<a name="ba-shared-structure-org"></a>

AWS 大型机转换现代化应用程序打包为 java Web 应用程序 (.war)，您可以将其部署在 JEE 服务器上。通常，服务器是一个 [Tomcat](https://tomcat.apache.org/) 实例，它嵌入了大型机运行时的 AWS 转换，该变换目前建立在 [Springboot](https://spring.io/projects/spring-boot) 和 [Angular](https://angular.io/)（用于用户界面部分）框架之上。

war 聚合了几个组件构件 (.jar)。每个 jar 都是专用 java 项目的编译（使用 [maven](https://maven.apache.org/) 工具）结果，该项目的元素是在现代化过程产生的。

![\[示例现代化应用程序构件。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/modernized_application_artifacts.png)


基本组织依赖以下结构：
+ 实体项目：包含业务模型和上下文元素。项目名称通常以“-entities”结尾。通常，对于给定的遗留 COBOL 程序，这与 I/O 部分（数据集）和数据部门的现代化相对应。您可以有多个实体项目。
+ 服务项目：包含遗留业务逻辑现代化元素。通常是 COBOL 程序的过程部分。您可以有多个服务项目。
+ 实用程序项目：包含其他项目使用的共享常用工具和实用工具。
+ Web 项目：包含 UI 相关元素的现代化（如果适用）。不用于仅限批处理的现代化项目。这些 UI 元素可能来自 CICS BMS 映射、IMS MFS 组件和其他大型机 UI 源。您可以有多个 Web 项目。

### 实体项目内容
<a name="ba-shared-structure-org-entities"></a>

**注意**  
以下描述仅适用于 COBOL 和 PL/I 现代化输出。RPG 现代化输出基于不同的布局。

在进行任何重构之前，实体项目中的包组织与现代化程序相关联。您可以通过几种不同的方法来实现这一点。首选方法是使用重构工具箱，该工具箱在您触发代码生成机制之前运行。这是一项高级操作，适用于大型机的 AWS 转型培训中对此进行了说明。有关更多信息，请参阅[重构研讨会](https://catalog.workshops.aws/aws-blu-age-l3-certification-workshop/en-US/refactoring)。使用这种方法时，您可以保留后续重新生成 Java 代码的能力，例如可以从将来的进一步改进中受益。另一种方法是使用您希望应用的任何 java 重构方法直接在生成的源代码上进行常规的 java 重构，但需自行承担风险。

![\[示例程序 CBACT04 C 实体包。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/entities_packages.png)


#### 项目相关类
<a name="ba-shared-structure-org-entities-program"></a>

每个现代化程序都与两个包相关：business.context 包和 business.model 包。
+ `base package.program.business.context`

  business.context 子包包含两个类，即一个配置类和一个上下文类。
  + 程序的一个配置类，其中包含给定程序的特定配置详细信息，例如用于表示基于字符的数据元素的字符集、用于填充数据结构元素的默认字节值等。类名称以“Configuration”结尾。该类标有 `@org.springframework.context.annotation.Configuration` 注释，并且包含一个必须返回正确设置的 `Configuration` 对象的方法。  
![\[Java 中的示例配置。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_configuration.png)
  + 一个上下文类，用作程序服务类（见下文）与模型子包（见下文）中的数据结构 (`Record`) 和数据集 (`File`) 之间的桥梁。该类名称以“Context”结尾并且是 `RuntimeContext` 类的子类。  
![\[示例上下文类（局部视图）\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_context.png)
+ `base package.program.business.model`

  模型子包包含给定程序可以使用的所有数据结构。例如，任何 01 级 COBOL 数据结构都对应于模型子包中的一个类（较低级别的数据结构是其所属 01 级结构的属性）。有关如何对 01 数据结构进行现代化的更多信息，请参阅[大型机 AWS 转型中的数据简化器是什么](ba-shared-data.md)。  
![\[示例记录实体（局部视图）\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_record_entity.png)

所有类都扩展了 `RecordEntity` 类，该类表示对业务记录表示的访问权限。有些记录有特殊用途，因为它们绑定到 `File`。a `Record` 和 a 之间的绑定`File`是在创建文件对象时在上下文类中找到的相应的 \$1 FileHandler 方法中进行的。例如，以下清单显示了如何绑定到 TransactFile`Record`（来自模型子包）。 TransactfileFile `File`

![\[记录与文件绑定示例。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_record_file_binding.png)


### 服务项目内容
<a name="ba-shared-structure-org-service"></a>

每个服务项目都附带一个专用的 [Springboot](https://spring.io/projects/spring-boot) 应用程序，该应用程序用作架构的主干。具体是通过名为 `SpringBootLauncher` 的类实现的，该类位于服务 java sources 的基础包中：

![\[服务项目 SpringBoot 申请。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/springbootlauncher.png)


该类主要用于：
+ 为程序类和托管资源（数据源/事务管理器/数据集映射/等...）之间建立联系。
+ 为程序提供 `ConfigurableApplicationContext`。
+ 发现所有标记为 spring 组件 (`@Component`) 的类。
+ 确保程序在 `ProgramRegistry` 中正确注册。请参阅用于进行此注册的 initialize 方法。

![\[程序注册。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/programs_registration.png)


#### 程序相关构件
<a name="ba-shared-structure-org-service-program"></a>

在未进行事先重构的情况下，业务逻辑现代化输出将按每个遗留程序两个或三个包进行组织：

![\[示例程序包。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_program_packages.png)


最详尽的情况下将提供三个包：
+ `base package.program.service`：包含一个名为 *Program*Process 的接口，该接口具有处理业务逻辑的业务方法，保留了遗留的执行控制流。
+ `base package.program.service.impl`: 包含一个名为 Prog *ra* ProcessImpl m 的类，它是前面描述的 Process 接口的实现。在这里，依赖大型机 AWS 转换框架，将遗留语句 “翻译” 为 java 语句：  
![\[现代化 CICS 语句（SEND MAP、SEND MAP）示例\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_cics_statements.png)
+ `base package.program.statemachine`：该包有时可能不存在。当传统控制流的现代化必须使用状态机方法（即使用 [Spring StateMachine 框架](https://spring.io/projects/spring-statemachine)）来正确覆盖遗留的执行流程时，这是必需的。

  在这种情况下，状态机子包包含两个类：
  + `ProgramProcedureDivisionStateMachineController`：该类扩展实现 `StateMachineController`（定义控制状态机执行所需的操作）和 `StateMachineRunner`（定义运行状态机所需的操作）接口的类，用于驱动 Spring 状态机机制；例如，示例用例中的 `SimpleStateMachineController`。  
![\[示例状态机控制器。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_statemachine_controller.png)

    状态机控制器定义了可能的不同状态以及状态之间的转换，可重现给定程序的遗留执行控制流。

    在构建状态机时，控制器会引用状态机包的关联服务类中定义的方法，如下所述：

    ```
    subConfigurer.state(States._0000_MAIN, buildAction(() -> {stateProcess._0000Main(lctx, ctrl);}), null);
    subConfigurer.state(States.ABEND_ROUTINE, buildAction(() -> {stateProcess.abendRoutine(lctx, ctrl);}), null);
    ```
  + `ProgramProcedureDivisionStateMachineService`：该服务类代表一些业务逻辑，这些逻辑需要与状态机控制器创建的状态机绑定，如前所述。

    该类方法中的代码使用状态机控制器中定义的事件：  
![\[使用状态机控制器事件的状态机服务。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/service_using_event_1.png)  
![\[使用状态机控制器事件的状态机服务。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/service_using_event_2.png)

    状态机服务还会调用前面所述的过程服务实现：  
![\[.statemachine 服务调用过程实现\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/service_using_processimpl.png)

除此之外，名为 `base package.program` 的包也发挥重要作用，因为该包为每个程序收集一个类，该类将作为程序的入口点（稍后会详细介绍）。每个类都实现 `Program` 接口，即程序入口点的标记。

![\[项目入口点\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/programs.png)


#### 其他构件
<a name="ba-shared-structure-org-service-other"></a>
+ BMS MAPs 同伴

  除了与程序相关的构件外，服务项目还可以包含用于各种用途的其他构件。对于 CICS 在线应用程序的现代化，现代化过程会生成一个 json 文件并放入/文件夹的地图src/main/resources文件夹中：  
![\[资源文件夹中的 BMS MAPs json 文件。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/maps_json_files.png)

  AWS Transform for mainframe运行时使用这些 json 文件来将 SEND MAP 语句使用的记录与屏幕字段绑定。
+ Groovy 脚本

  如果旧版应用程序有 JCL 脚本，则这些脚本已现代化为 [groovy](https://groovy-lang.org/) 脚本，存储在/src/main/resources/scripts文件夹中（稍后会详细介绍该特定位置）：  
![\[groovy 脚本（JCL 现代化）\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/groovy_scripts.png)

  这些脚本用于启动批处理作业（专用、非交互式、CPU 密集型数据处理工作负载）。
+ SQL 文件

  如果遗留应用程序使用 SQL 查询，则相应的现代化 SQL 查询已收集在专用属性文件中，使用命名模式 *program*.sql，其中 *program* 是使用这些查询的程序的名称。  
![\[资源文件夹中的 SQL 文件\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sql_files.png)

  这些 sql 文件的内容是 (key=query) 条目的集合，其中每个查询都与一个唯一的键相关联，现代化程序使用该键来运行给定查询：  
![\[现代化程序使用的示例 sql 文件。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_sql_file.png)

  例如， COSGN00C 程序正在使用键 “COSGN00C\$11”（sql 文件中的第一个条目）执行查询：  
![\[按程序列出的示例查询使用情况\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_sql_query_usage.png)

### 实体项目内容
<a name="ba-shared-structure-org-utilities"></a>

名字以“-tools”结尾的实用程序项目包含一组技术实用工具，这些工具可用于所有其他项目。

![\[实体项目内容\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/tools_project.png)


### Web 项目内容
<a name="ba-shared-structure-org-web"></a>

Web 项目仅在对遗留 UI 元素进行现代化时才存在。用于构建现代化应用程序前端的现代 UI 元素基于 [Angular](https://angular.io/) 用于显示现代化构件的示例 COBOL/CICS 应用程序是在大型机上运行的应用程序。CICS 系统 MAPs 用来表示用户界面屏幕。每个映射相应的现代元素为一个 html 文件和多个 [Typescript](https://www.typescriptlang.org/) 文件：

![\[现代化为 Angular 的 CICS 映射示例\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_cics_maps_angular.png)


Web 项目仅处理应用程序的前端方面。依赖于实用程序和实体项目的服务项目提供后端服务。前端和后端之间的链接是通过名为 Gapwalk-Application 的 Web 应用程序建立的，该应用程序是大型机运行时分发标准 AWS 转换的一部分。

## 运行和调用程序
<a name="ba-shared-structure-run-call"></a>

在遗留系统上，程序被编译为独立的可执行文件，可以通过 CALL 机制（例如 COBOL CALL 语句）进行自我调用，并根据需要传递参数。现代化应用程序提供了相同的功能，但使用了不同的方法，因为所涉及的构件的性质与遗留构件的性质不同。

在现代化系统上，程序入口点是实现 `Program` 接口的特定类，是 Spring 组件 (@Component)，位于服务项目中名为 `base package.program` 的包中。

### 程序注册
<a name="ba-shared-structure-run-call-register-programs"></a>

每次启动托管现代化应用程序的 [Tomcat](https://tomcat.apache.org/) 服务器时，也会启动服务 Springboot 应用程序，从而触发程序注册。名为 `ProgramRegistry` 的专用注册表中填充了程序条目，每个程序都使用其标识符进行注册，每个已知的程序标识符对应一个条目，这意味着如果一个程序具有多个不同的已知标识符，则注册表包含的条目与标识符的数量相等。

给定程序的注册依赖于 getProgramIdentifiers () 方法返回的标识符集合：

![\[示例程序（局部视图）\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/sample_program.png)


在此示例中，该程序注册了一次，名为 “CBACT04C”（查看 ProgramidEntifiers 集合的内容）。Tomcat 日志显示每个程序的注册情况。程序注册仅取决于声明的程序标识符，而不取决于程序类名词本身（尽管通常程序标识符和程序类名称是一致的）。

同样的注册机制适用于各种用于大型机 Web 应用程序的实用程序 Tr AWS ansform 带来的实用程序，它们是 Tr AWS ansform for 大型机运行时发行版的一部分。例如， Gapwalk-Utility-PgmWeb应用程序提供了 z/OS 系统实用程序（IDCAMS、ICEGENER、SORT等）的等效功能，并且可以通过现代化的程序或脚本进行调用。在 Tomcat 启动时注册的所有可用实用程序都记录在 Tomcat 日志中。

### 脚本和进程守护程序注册
<a name="ba-shared-structure-run-call-register-scripts"></a>

在 Tomcat 启动时，位于/ src/main/resources/scripts 文件夹层次结构中的 groovy 脚本也会发生类似的注册过程。遍历脚本文件夹层次结构后，所有发现的 groovy 脚本（特殊的 functions.groovy 保留脚本除外）都将注册到 `ScriptRegistry` 中，并使用其短名称（脚本文件名中位于第一个点字符之前的部分）作为密钥进行检索。

**注意**  
如果多个脚本的文件名会导致生成相同的注册密钥，则仅注册最新的脚本，并覆盖该给定密钥之前的任何注册。
考虑到上述注意事项，使用子文件夹时需引起注意，因为注册机制会使层次结构扁平化并可能导致意外覆盖。层次结构不计入注册过程：通常为/ scripts/A/myscript.groovy and /scripts/B/myscript.groovy will lead to /scripts/B/myscript.groovy overwriting /scripts/A/myscript .groovy。

/src/main/resources/daemons文件夹中的 groovy 脚本的处理方式略有不同。它们仍被注册为常规脚本，但此外，它们仅在 Tomcat 启动时以异步方式启动一次。

在 `ScriptRegistry` 中注册脚本后，即可使用 Gapwalk-Application 公开的专用端点进行 REST 调用来启动这些脚本。有关更多信息，请参阅相应文档。

### 程序调用程序
<a name="ba-shared-structure-run-call-programs"></a>

每个程序都可以将另一个程序作为子程序进行调用，并向其传递参数。程序使用 `ExecutionController` 接口实现来进行调用（大多数情况下，这是一个 `ExecutionControllerImpl` 实例），并使用名为 `CallBuilder` 的 fluent API 机制来构建程序调用参数。

所有程序的方法都将 `RuntimeContext` 和 `ExecutionController` 作为方法参数，因此 `ExecutionController` 始终可用于调用其他程序。

例如，参见下图，它显示了 CBST03 A 程序如何将 CBST03 B 程序作为子程序调用，并向其传递参数：

![\[.sub-program 调用示例\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/subprogram_call_sample.png)

+ `ExecutionController.callSubProgram` 的第一个参数是要调用的程序的标识符（即用于程序注册的标识符之一，请参阅以上段落）。
+ 第二个参数是在 `CallBuilder` 上构建的结果，是一个 `Record` 数组，对应于从调用方传递给被调用方的数据。
+ 第三个也是最后一个参数是调用者 `RuntimeContext` 实例。

所有三个参数都是必需的，不能为空，但第二个参数可以是空数组。

被调用方仅在最初设计为能够处理传递的参数时才能处理这些参数。对于遗留的 COBOL 程序，这意味着要有一个 LINKAGE 部分和一个 USING 子句，以便过程部分使用 LINKAGE 元素。

例如，参见相应的 [CBSTM03B.CBL COBOL](https://github.com/aws-samples/aws-mainframe-modernization-carddemo/blob/main/app/cbl/CBSTM03B.CBL) 源文件：

![\[COBOL 源文件中的示例链接\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/linkage_sample.png)


因此， CBSTM03B 程序将单个`Record`作为参数（大小为 1 的数组）。这是 `CallBuilder` 使用 byReference() 和 getArguments() 方法链接构建的内容。

`CallBuilder` fluent API 类有几种方法可用于填充要传递给被调用方的参数数组：
+ asPointer (RecordAdaptable)：通过引用添加指针类型的参数。指针表示目标数据结构的地址。
+ byReference (RecordAdaptable)：通过引用添加参数。调用方将看到被调用方执行的修改。
+ byReference (RecordAdaptable)：先前方法的可变参数变体。
+ byValue(Object)：添加一个按值转换为 `Record` 的参数。调用方将看到被调用方执行的修改。
+ byValue (RecordAdaptable)：与前面的方法相同，但该参数可以直接作为`RecordAdaptable`.
+ byValueWith边界（Object、int、int）：添加一个参数，将其转换为 a`Record`，按值提取由给定边界定义的字节数组部分。

最后，getArguments 方法将收集所有添加的参数，并将其作为 `Record` 数组返回。

**注意**  
调用方需确保参数数组具有所需的大小，在内存布局与 linkage 元素的预期布局方面，项目顺序正确且兼容。

### 调用程序的脚本
<a name="ba-shared-structure-run-call-scripts"></a>

从 groovy 脚本中调用注册程序需要使用用于实现 `MainProgramRunner` 接口的类实例。通常，获得这样的实例是通过 Spring 的 ApplicationContext 使用来实现的：

![\[。 MainProgramRunner : 获取实例\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/mpr.png)


`MainProgramRunner` 接口可用后，使用 runProgram 方法调用程序并将目标程序的标识符作为参数传递：

![\[MainProgramRunner : 运行一个程序\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/mpr_runprogram.png)


在上述示例中，作业步骤调用 IDCAMS（文件处理实用程序），提供实际数据集定义与其逻辑标识符之间的映射。

在处理数据集时，遗留程序大多使用逻辑名称来标识数据集。当从脚本调用程序时，脚本必须将逻辑名称与实际的物理数据集进行映射。这些数据集可能位于文件系统中、Blusam 存储中，甚至可以由内联流、多个数据集的串联或生成 GDG 来定义。

使用该 withFileConfiguration 方法构建数据集的逻辑到物理映射，并将其提供给被调用的程序。

## 自行编写程序
<a name="ba-shared-structure-write"></a>

自行编写程序供脚本或其他现代化程序调用是一项常见任务。通常，在现代化项目中，当可执行的遗留程序是使用现代化过程不支持的语言编写的，或者源代码丢失（是的，可能会发生这种情况），或者该程序是一个源代码不可用的实用程序时，您需要自行编写程序。

在这种情况下，您可能必须自己使用 java 编写缺失的程序（前提是您对程序的预期行为、程序参数的内存布局（如果有）等有足够的了解。） 您的 java 程序必须符合本文档中描述的程序机制，以便其他程序和脚本可以运行它。

要确保该程序可用，您必须完成两个必需的步骤：
+ 编写一个能正确实现 `Program` 接口的类，以便可以注册和调用该接口。
+ 确保您的程序已正确注册，以便其他程序/脚本可以看到该程序。

### 编写程序实现
<a name="ba-shared-structure-write-implementation"></a>

使用 IDE 创建用于实现 `Program` 接口的新 java 类：

![\[创建新的 java 程序类\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/new_program.png)


下图显示了 Eclipse IDE，用于创建所有要实现的必需的方法：

![\[创建新的 java 程序类 – 编辑源\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/new_program_ide.png)


### Spring 集成
<a name="ba-shared-structure-write-spring"></a>

首先，必须将该类声明为 Spring 组件。为该类添加 `@Component` 注释：

![\[使用 spring @Component 注解\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/program_component.png)


接下来，正确实现所需的方法。在本示例中，我们将 `MyUtilityProgram` 添加到已包含所有现代化程序的包中，该位置允许程序使用现有的 Springboot 应用程序来提供 getSpringApplication 方法实现`ConfigurableApplicationContext`所需的内容：

![\[实现 getSpringApplication 方法。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/getSpringApplication.png)


您可以为自己的程序选择不同的位置。例如，您可以将给定的程序放在另一个专门的服务项目中。确保给定的服务项目有自己的 Springboot 应用程序，这样就可以检索 ApplicationContext （应该是 a`ConfigurableApplicationContext`）。

### 为程序添加标识
<a name="ba-shared-structure-write-identity"></a>

要使程序能被其他程序和脚本调用，必须为其提供至少一个标识符，该标识符不得与系统中任何现有的其他已注册程序发生冲突。选择标识符可以根据要涵盖现有遗留程序替换的需求来确定；在这种情况下，您必须使用所需的标识符，例如在整个遗留程序中 CALL 次数中所出现的标识符。在遗留系统中，大多数程序标识符的长度为 8 个字符。

在程序中创建一组不可修改的标识符是实现此目的的一种方法。以下示例显示了如何选择“MYUTILPG”作为单一标识符：

![\[程序标识符示例\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/program_identifier.png)


### 将程序与上下文关联
<a name="ba-shared-structure-write-context"></a>

程序需要一个配套 `RuntimeContext` 实例。对于现代化程序，Tr AWS ansform for mainframe 会使用旧版程序中的数据结构自动生成配套上下文。

如果您正在编写自己的程序，则还必须编写配套上下文。

请参阅[项目相关类](#ba-shared-structure-org-entities-program)，即可以看到一个程序至少需要两个配套类：
+ 配置类。
+ 使用配置的上下文类。

如果实用程序使用任何额外的数据结构，则还应编写相应的数据结构并使其被上下文使用。

这些类应位于包层次结构中的包中，应用程序启动时会扫描该包层次结构，从而确保上下文组件和配置由 Spring 框架处理。

我们在实体项目中新创建的 `base package.myutilityprogram.business.context` 包中编写一个最小配置和上下文：

![\[新实用程序的新专用配置和上下文\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/new_program_context_package.png)


以下是配置内容，其使用的配置构建与附近其他（现代化）程序类似。您可能需要根据自己的特定需求对其进行自定义。

![\[新程序配置\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/new_program_configuration.png)


注意：
+ 一般命名约定是*ProgramName*配置。
+ 必须使用 @org.springframework.context.annotation.Configuration 和 @Lazy 注释。
+ bean 名称通常遵循*ProgramName*ContextConfiguration 惯例，但这不是强制性的。确保在整个项目中避免 Bean 名称冲突。
+ 要实现的单个方法必须返回一个 `Configuration` 对象。使用 `ConfigurationBuilder` fluent API 来帮助您构建此方法。

相关的上下文：

![\[Java 文件中的新程序上下文。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/new_program_context.png)


注意
+ 上下文类应扩展现有的 `Context` 接口实现（`RuntimeContext` 或者 `JicsRuntimeContext`（即具有 JICS 特定项的增强 `RuntimeContext`））。
+ 一般命名约定是*ProgramName*上下文。
+ 必须将其声明为 Prototype 组件，并使用 @Lazy 注解。
+ 构造函数引用关联的配置，使用 @Qualifier 注释来定位正确的配置类。
+ 如果实用程序使用一些额外的数据结构，这些数据结构应：
  + 已编写并添加到 `base package.business.model` 包中。
  + 在上下文中引用。查看其他现有的上下文类，了解如何引用数据结构类并根据需要调整上下文方法（构造函数/清理/重置）。

专用上下文可用后，新程序即可使用该上下文：

![\[新程序使用新创建的上下文。\]](http://docs.aws.amazon.com/zh_cn/m2/latest/userguide/images/new_program_uses_context.png)


备注：
+ getContext 方法必须严格如图所示，使用对`ProgramContextStore`类的 getOrCreate 方法和自动连线 Spring `BeanFactory` 的委托。单个程序标识符用于在 `ProgramContextStore` 中存储程序上下文；该标识符被称为“程序主标识符”。
+ 必须使用 `@Import` spring 注释来引用配套配置和上下文类。

### 实现业务逻辑
<a name="ba-shared-structure-write-business-logic"></a>

完成程序框架后，实现新实用程序的业务逻辑。

在程序的 `run` 方法中执行此操作。该方法会在程序被其他程序或脚本调用时执行。

祝您编码顺利！

### 处理程序注册
<a name="ba-shared-structure-write-registration"></a>

最后，请确保将新程序在 `ProgramRegistry` 中正确注册。如果您将新程序添加到已包含其他程序的包中，则无需执行任何其他操作。在应用程序启动时，新程序会被选中并与其所有邻居程序一并注册。

如果您为程序选择了其他位置，则必须确保该程序在 Tomcat 启动时能够正确注册。有关如何执行此操作的一些灵感，请查看服务项目中生成 SpringbootLauncher 类的初始化方法（请参阅[服务项目内容](#ba-shared-structure-org-service)）。

查看 Tomcat 启动日志。每个程序注册都会被记录在日志中。如果您的程序成功注册，可找到匹配的日志条目。

确定程序已正确注册后，即可开始迭代业务逻辑编码。

## 完全限定名称映射
<a name="ba-shared-structure-fqn"></a>

本节包含适用于大型机的 Tr AWS ansform 列表和用于现代化应用程序的第三方完全限定名称映射列表。

### AWS 为大型机完全限定名称映射进行转换
<a name="ba-shared-structure-fqn-table"></a>


| 短名称 | 完全限定名称 | 
| --- | --- | 
|  `CallBuilder`  |  `com.netfective.bluage.gapwalk.runtime.statements.CallBuilder`  | 
|  `Configuration`  |  `com.netfective.bluage.gapwalk.datasimplifier.configuration.Configuration`  | 
|  `ConfigurationBuilder`  |  `com.netfective.bluage.gapwalk.datasimplifier.configuration.ConfigurationBuilder`  | 
|  `ExecutionController`  |  `com.netfective.bluage.gapwalk.rt.call.ExecutionController`  | 
|  `ExecutionControllerImpl`  |  `com.netfective.bluage.gapwalk.rt.call.internal.ExecutionControllerImpl`  | 
|  `File`  |  `com.netfective.bluage.gapwalk.rt.io.File`  | 
|  `MainProgramRunner`  |  `com.netfective.bluage.gapwalk.rt.call.MainProgramRunner`  | 
|  `Program`  |  `com.netfective.bluage.gapwalk.rt.provider.Program`  | 
|  `ProgramContextStore`  |  `com.netfective.bluage.gapwalk.rt.context.ProgramContextStore`  | 
|  `ProgramRegistry`  |  `com.netfective.bluage.gapwalk.rt.provider.ProgramRegistry`  | 
|  `Record`  |  `com.netfective.bluage.gapwalk.datasimplifier.data.Record`  | 
|  `RecordEntity`  |  `com.netfective.bluage.gapwalk.datasimplifier.entity.RecordEntity`  | 
|  `RuntimeContext`  |  `com.netfective.bluage.gapwalk.rt.context.RuntimeContext`  | 
|  `SimpleStateMachineController`  |  `com.netfective.bluage.gapwalk.rt.statemachine.SimpleStateMachineController`  | 
|  `StateMachineController`  |  `com.netfective.bluage.gapwalk.rt.statemachine.StateMachineController`  | 
|  `StateMachineRunner`  |  `com.netfective.bluage.gapwalk.rt.statemachine.StateMachineRunner`  | 

### 第三方完全限定名称映射
<a name="ba-shared-structure-3pfqn-table"></a>


| 短名称 | 完全限定名称 | 
| --- | --- | 
|  `@Autowired`  |  `org.springframework.beans.factory.annotation.Autowired`  | 
|  `@Bean`  |  `org.springframework.context.annotation.Bean`  | 
|  `BeanFactory`  |  `org.springframework.beans.factory.BeanFactory`  | 
|  `@Component`  |  `org.springframework.stereotype.Component`  | 
|  `ConfigurableApplicationContext`  |  `org.springframework.context.ConfigurableApplicationContext`  | 
|  `@Import`  |  `org.springframework.context.annotation.Import`  | 
|  `@Lazy`  |  `org.springframework.context.annotation.Lazy`  | 