AWS 藍光時代結構的現代化應用程序 - AWS 大型主機現代化

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

AWS 藍光時代結構的現代化應用程序

本文件提供現代化應用程式結構的詳細資訊 (使用 AWS 大型主機現代化重構工具),讓開發人員能夠完成各種工作,例如:

  • 流暢地導航到應用程序。

  • 開發可以從現代化的應用程序被調用的自定義程序。

  • 安全地重構現代化應用程式。

我們假設您已經掌握了以下內容的基本知識:

  • 舊式通用編碼概念,例如記錄、資料集及其存取模式,以記錄索引、順序-VSAM、執行單元、jcl 指令碼、CICS概念等。

  • java 編碼使用春天框架

  • 在整個文檔中,我們使short class names用可讀性。如需詳細資訊,請參AWS 藍色時代完整名稱對應閱擷取 AWS Blu Age 執行階段元素的對應完整名稱,第三方完整名稱對應以及擷取協力廠商元素的對應完整名稱。

  • 所有成品和樣本都是從樣本COBOL/CICSCardDemo 應用程序的現代化過程輸出中獲取的。

成品組織

AWS 藍光時代現代化的應用程式會封裝成 Java Web 應用程式 (.war),您可以在伺服器上部署。JEE通常情況下,服務器是一個嵌入 AWS 藍光時代運行時的 Tomcat 實例,該實例目前建立在 Springboot角度(用於 UI 部分)框架上。

戰爭聚合了幾個組件工件(.jar)。每個 jar 都是專用 java 項目的編譯(使用 maven 工具)的結果,該項目的元素是現代化過程的結果。

現代化應用程式成品範例。

基本組織依賴於以下結構:

  • 實體項目:包含業務模型和上下文元素。項目名稱通常以「-實體」結尾。通常,對於給定的舊版COBOL程序,這對應於 I/O 部分(數據集)和數據分割的現代化。您可以有多個實體專案。

  • 服務專案:包含傳統的商務邏輯現代化元素。通常情況下,程序的過程COBOL劃分。您可以擁有多個服務專案。

  • 實用程序項目:包含共享的常用工具和實用程序,由其他項目使用。

  • Web 項目:包含 UI 相關元素的現代化(如果適用)。不適用於僅批次現代化專案。這些 UI 元素可能來自CICSBMS地圖、IMSMFS元件和其他大型主機 UI 來源。您可以有一個以上的 Web 專案。

實體專案內容

注意

以下說明僅適用於COBOL和 PL/I 現代化輸出。RPG現代化輸出以不同的配置為基礎。

在進行任何重構之前,實體專案中的封裝組織會繫結至現代化方案。您可以通過幾種不同的方式完成此操作。首選的方法是使用重構工具箱,該工具箱在觸發代碼生成機制之前運行。這是一個高級操作,這在 BluAge 培訓中進行了說明。如需詳細資訊,請參閱重構研討會。這種方法允許您保留以後重新生成 java 代碼的能力,以便從 future 的進一步改進中受益,例如)。另一種方法是直接在生成的源代碼上進行常規的 java 重構,使用您可能想應用的任何 java 重構方法,風險自擔。

範例程式 CBACT 04C 實體套件。

課程相關課程

每個現代化程序都與兩個軟件包相關,一個業務 .context 和一個商業 .model 軟件包。

  • base package.program.business.context

    該業務 .context 子包包含兩個類,一個配置類和一個上下文類。

    • 程式的一個組態類別,其中包含指定程式的特定組態詳細資訊,例如用來表示以字元為基礎的資料元素的字元集、填補資料結構元素的預設位元組值等等。類名以「配置」結尾。它用@org.springframework.context.annotation.Configuration註釋標記,並包含必須返回正確設置Configuration對象的單個方法。

      Java 中的示例配置。
    • 一個上下文類,它作為程序服務類(見下文)和數據結構()和數據集(Record)從模型子包(File)之間的橋樑(見下文)。類名以「上下文」結尾,是該類的一個子RuntimeContext類。

      示例上下文類(部分視圖)
  • base package.program.business.model

    該模型子包包含所有給定的程序可以使用的數據結構。例如,任何 01 級COBOL數據結構對應於模型子包中的一個類(較低級別的數據結構是其擁有 01 級結構的屬性)。有關我們如何現代化 01 數據結構的更多信息,請參閱AWS 藍光時代的數據簡化器是什麼

    範例記錄實體 (部分檢視)

所有類擴展RecordEntity類,它代表對業務記錄表示的訪問。一些記錄有一個特殊的目的,因為它們綁定到File. a Record 和 a 之間的綁定File是在創建文件對象時在上下文類中找到的相應 * FileHandler 方法中進行的。例如,下列清單顯示 TransactfileFile File如何繫結至 transactFile Record (從模型子套件)。

範例記錄到檔案繫結。

服務項目內容

每個服務項目都配備了一個專用的 Springboot 應用程序,該應用程序被用作架構的骨幹。這是通過位於服務 java 源代碼的基本包中名為SpringBootLauncher的類來實現:

服務項目 SpringBoot 應用程序。

這個課程特別負責:

  • 在程序類和託管資源(數據源/事務管理器/數據集映射/等)之間製作膠水。

  • 提供一ConfigurableApplicationContext個程序。

  • 發現標記為彈簧組件(@Component)的所有類。

  • 確保程序正確註冊在 ProgramRegistry--請參閱負責此註冊的初始化方法。

程序註冊。

程式相關加工品

在沒有事先重構的情況下,業務邏輯現代化輸出會根據每個舊版程式的兩個或三個套件進行組織:

範例程式套件。

最詳盡的案例將有三個包:

  • base package.program.service:包含一個名為 Program Pro cess 的介面,該介面具有用於處理業務邏輯的業務方法,並保留傳統執行控制流程。

  • base package.program.service.impl: 包含一個名為 Program 的類ProcessImpl,這是前面描述的 Process 接口的實現。這是遺留語句被「翻譯」為 java 語句的地方,依賴於 AWS Blu Age 框架:

    現代化CICS陳述式範例 (SENDMAP、RECEIVEMAP)
  • base package.program.statemachine:這個軟件包可能並不總是存在。當傳統控制流程的現代化必須使用狀態機器方法(即使用 S pring StateMachine 框架)來正確覆蓋傳統執行流程時,這是必需的。

    在這種情況下,靜態子包包含兩個類:

    • ProgramProcedureDivisionStateMachineController: 擴充用於驅動 Spring 狀態機力學的類別 StateMachineController (定義控制狀態機執行所需的作業) 和 StateMachineRunner (定義執行狀態機所需的作業) 介面的類別;例如,SimpleStateMachineController如範例中所示。

      樣品狀態機控制器。

      狀態機控制器定義了可能的不同狀態和它們之間的轉換,從而重現給定程序的傳統執行控制流程。

      在構建狀態機時,控制器指的是在位於狀態機包中的相關服務類中定義的方法,如下所述:

      subConfigurer.state(States._0000_MAIN, buildAction(() -> {stateProcess._0000Main(lctx, ctrl);}), null); subConfigurer.state(States.ABEND_ROUTINE, buildAction(() -> {stateProcess.abendRoutine(lctx, ctrl);}), null);
    • ProgramProcedureDivisionStateMachineService: 此服務類別代表一些需要與狀態機控制器建立之狀態機器繫結的業務邏輯,如前所述。

      在這個類的方法的代碼使用狀態機控制器中定義的事件:

      使用靜態控制器事件來定位服務。
      使用靜態控制器事件來定位服務。

      靜態服務也會呼叫先前描述的程序服務實作:

      .statemachine 服務調用過程實施

除此之外,一個名為的軟件包base package.program起著重要作用,因為它每個程序收集一個類,這將作為程序進入點(稍後有關此更多詳細信息)。每個類實現接Program口,標記為程序入口點。

計劃進入點

其他文物

  • BMSMAPs同伴

    除了方案相關的人工因素之外,服務專案還可以包含用於各種目的的的其他成品。在CICS線上應用程式的現代化情況下,現代化程序會產生一個 json 檔案,並放入 /src/main/resources 資料夾的地圖資料夾中:

    BMSMAPs資源文件夾中的 json 文件。

    Blu Age 運行時消耗這些 json 文件,以將SENDMAP語句使用的記錄與屏幕字段綁定。

  • 常規的腳本

    如果傳統應用程序有JCL腳本,那麼這些腳本已經被現代化為 groovy 腳本,存儲在 /src/main/資源/腳本文件夾中(稍後有關該特定位置的更多信息):

    常規腳本(JCL現代化)

    這些指令碼可用來啟動批次工作 (專用、非互動式、CPU 密集型資料處理工作負載)。

  • SQL文件

    如果舊版應用程式使用SQL查詢,則相應的現代化SQL查詢已收集到專用屬性檔案中,並使用命名模式式 .sql,其中的式是使用這些查詢的程式名稱。

    SQL資源資料夾中的檔案

    這些 sql 文件的內容是(key=query)條目的集合,其中每個查詢都與一個唯一密鑰相關聯,現代化程序用於運行給定的查詢:

    現代化程式使用的範例 sql 檔案。

    例如,COSGN00C 程序正在使用密鑰「COSGN00C_1」(sql 文件中的第一個條目)執行查詢:

    依程式查詢使用範例

公用程式專案內

公用事業項目,其名稱以「-tools」結尾,包含一組技術實用程序,可能被所有其他項目使用。

公用程式專案內

Web 專案內容

Web 項目只有在現代化傳統 UI 元素時才存在。用於構建現代化的應用程序前端的現代 UI 元素基於 Angular。用來顯示現代化成品的範例應用程式是在大型主機上執行的COBOL/CICS應用程式。系CICS統使用MAPs來表示 UI 螢幕。相應的現代元素將是,對於每個地圖,一個 html 文件伴隨著打字稿文件:

範例CICS地圖現代化為角度

Web 專案只負責應用程式的前端方面依賴公用程式和實體專案的服務專案提供後端服務。前端和後端之間的鏈接是通過名為 Gapwalk-應用程序,這是標準的 AWS 藍光時代運行時分佈的一部分的 Web 應用程序進行。

運行和調用程序

在傳統系統上,程式會編譯為獨立的可執行檔,可透過CALL機制 (例如COBOLCALL陳述式) 自行呼叫,並在需要時傳遞引數。現代化的應用程式提供相同的功能,但使用不同的方法,因為所涉及的成品的性質與舊版的性質不同。

在現代化方面,程序入口點是實現Program接口的特定類,是 Spring 組件(@Component),並且位於服務項目中,名為base package.program

程序註冊

每次託管現代化應用程序的 Tomcat 服務器啟動時,服務 Springboot 應用程序也被啟動,這會觸發程序註冊。一個名ProgramRegistry為專用的註冊表填充了程序條目,每個程序正在使用它的標識符,每個已知的程序標識符一個條目,這意味著,如果一個程序是由幾個不同的標識符已知,註冊表包含盡可能多的條目,因為有標識符。

給定程序的註冊依賴於由 getProgramIdentifiers()方法返回的標識符的集合:

範例程式 (部分檢視)

在這個例子中,該程序被註冊一次,名為 'CBACT04C'(看看 programIdentifiers 集合的內容)。tomcat 日誌顯示每個程序註冊。程序註冊僅取決於聲明的程序標識符,而不是程序類名本身(儘管通常程序標識符和程序類名稱是對齊的。

相同的註冊機制適用於各種實用程序 AWS Blu Age Web 應用程序帶來的實用程序,這些應用程序是 AWS Blu Age 運行時分佈的一部分。例如,Gapwalk-Utiliy-Pgm web 應用程式提供 z/OS 系統公用程式 (IDCAMS、、等等) 的功能對等項目,ICEGENER而且可以透過現代化的程式或指令碼來呼叫。SORT在 Tomcat 啟動時註冊的所有可用公用程式都會記錄在 Tomcat 記錄檔中。

腳本和守護進程註冊

類似的註冊過程,在 Tomcat 啟動時,發生在/src /主/資源/腳本文件夾層次結構的groovy 腳本。腳本文件夾層次結構被遍歷,並且發現的所有 groovy 腳本(除了特殊的 functions.groovy 保留腳本)都在中註冊ScriptRegistry,並使用它們的短名稱(腳本文件名的一部分位於第一個點字符之前)作為檢索的關鍵字。

注意
  • 如果有多個腳本具有將導致產生相同註冊密鑰的文件名,則只會註冊最新的腳本,覆蓋任何先前遇到的該給定密鑰的註冊。

  • 考慮到上述注意事項,使用子文件夾時請注意,因為註冊機制會扁平化層次結構並可能導致意外的覆蓋。層次結構在註冊過程中不計算:典型地/腳本/A /MyScript.Groovy 和/腳本 /B/MyScript.Groovy 將導致/腳本//MySCRIPT。

/src/主/資源/守程文件夾中的groovy 腳本的處理方式有點不同。它們仍然註冊為常規腳本,但此外,它們會直接在 Tomcat 啟動時間以異步方式啟動一次。

在中註冊指令碼之後ScriptRegistry,REST呼叫可以使用 Gapwalk 應用程式公開的專用端點來啟動它們。如需詳細資訊,請參閱對應的文件。

程序調用程序

每個程序可以調用另一個程序作為一個子程序,傳遞參數給它。程序使用接ExecutionController口的實現來這樣做(大多數情況下,這將是一個實ExecutionControllerImpl例),以及一個名為 the 的流暢API機制CallBuilder來構建程序調用參數。

所有程序方法都採用 a RuntimeContext 和 a ExecutionController as 方法參數,因此始終可用於調用其他程序。ExecutionController

例如,請參閱下面的圖表,其中顯示 03 CBST A 程序如何調用 CBST 03B 程序作為子程序,並將參數傳遞給它:

. 子程序調用示例
  • 的第一個引數ExecutionController.callSubProgram是要調用的程序的標識符(即用於程序註冊的標識符之一--見上面的段落)。

  • 第二個引數,這是構建的結果CallBuilder,是一個數組Record,對應於從調用者傳遞給被調用者的數據。

  • 第三個也是最後一個引數是呼叫者RuntimeContext實例。

所有這三個參數都是強制性的,不能為 null,但第二個參數可以是一個空數組。

被調用者將能夠處理傳遞的參數,只有當它最初被設計為這樣做。對於傳統程COBOL序,這意味著具有一個LINKAGE部分和一個USING子句,用於程序劃分以利用這些LINKAGE元素。

例如,請參閱相應的 CBSTM03B。 CBLCOBOL來源檔案:

COBOL來源檔案中的範例連結

所以 CBSTM 03B 程序將一個單個Record作為參數(大小為 1 的數組)。這是使用byReference()和getArguments()方法鏈接的構建。CallBuilder

CallBuilder流利的API類有幾種方法可用於填充參數數組以傳遞給被調用者:

  • asPointer(RecordAdaptable):通過引用添加指針類型的參數。指針表示目標數據結構的地址。

  • byReference(RecordAdaptable):通過引用添加參數。呼叫者將看到被呼叫者執行的修改。

  • byReference(RecordAdaptable):以前方法的可變參數變體。

  • byValue(對象):添加一個參數Record,按值轉換為 a。呼叫者不會看到被呼叫者執行的修改。

  • byValue(RecordAdaptable):與前面的方法相同,但參數直接作為RecordAdaptable.

  • byValueWith邊界(Object,int,int):添加一個參數,轉換為 aRecord,按值提取由給定邊界定義的字節數組部分。

最後,該 getArguments 方法將收集所有添加的參數並將其作為數組返回Record

注意

確保 arguments 數組具有所需的大小,就內存佈局與鏈接元素的預期佈局而言,這些項目是正確排序和兼容的調用者的響應性。

腳本調用程序

從 groovy 腳本調用註冊的程序需要使用實現MainProgramRunner接口的類實例。通常,獲得這樣的實例是通過 Spring 的 ApplicationContext 使用來實現的:

。 MainProgramRunner :取得執行個體

MainProgramRunner接口可用後,使用該 runProgram 方法調用程序並將目標程序的標識符作為參數傳遞:

MainProgramRunner :執行程式

在前面的範例中,作業步驟呼叫 IDCAMS (檔案處理公用程式),提供實際資料集定義及其邏輯識別碼之間的對應。

在處理數據集時,舊版程序大多使用邏輯名稱來識別數據集。從指令碼呼叫程式時,指令碼必須將邏輯名稱與實際的實體資料集對應。這些數據集可以位於文件系統中,在 Blusam 存儲中,甚至由內聯流,多個數據集的串聯或. GDG

使用此方 withFileConfiguration 法建立資料集的邏輯對實體對應,並將其提供給被呼叫的程式。

編寫您自己的程序

為腳本或其他現代化程序編寫自己的程序來調用是一項常見任務。一般而言,在現代化專案中,當可執行的舊版程式是以現代化程序不支援的語言撰寫,或是來源已遺失 (是的,可能發生這種情況),或程式是無法取得來源的公用程式時,撰寫自己的程式。

在這種情況下,您可能必須自己用 java 編寫丟失的程序(假設您對程序預期行為應該是什麼有足夠的了解,程序參數的內存佈局(如果有的話)。您的 java 程式必須符合本文件中描述的程式機制,以便其他程式和指令碼可以執行它。

若要確保程式可用,您必須完成兩個強制步驟:

  • 編寫一個正確實現接Program口的類,以便它可以被註冊和調用。

  • 確保您的程序已正確註冊,以便從其他程序/腳本中可見。

編寫程序實施

使用您IDE的創建一個實現Program接口的新 Java 類:

創建一個新的 Java 程序類

下圖顯示了 EclipseIDE,它需要創建要實現的所有強制性方法的護理:

建立新的 Java 程式類別-編輯原始碼

彈簧整合

首先,類必須聲明為 Spring 組件。用@Component註釋註釋類:

使用彈簧 @Component 註解

接下來,正確實施所需的方法。在此範例的內容中,我們將新增MyUtilityProgram至已包含所有現代化程式的套件中。該放置允許程序使用現有的 Springboot 應用程序來提供所需ConfigurableApplicationContext的 getSpringApplication 方法實現:

實現該 getSpringApplication 方法。

您可以為自己的程序選擇不同的位置。例如,您可以在另一個專用服務項目中找到給定的程序。確保給定的服務項目有自己的 Springboot 應用程序,這使得它可以檢索 ApplicationContext (應該是一個ConfigurableApplicationContext)。

給一個身份的程序

要被其他程序和腳本調用,該程序必須給予至少一個標識符,這不能與系統中的任何其他現有的註冊程序發生衝突。識別碼的選擇可能是由於需要涵蓋現有舊版程式替換的需求所驅動;在這種情況下,您必須使用預期的識別碼,如同在整個舊版程式中發現的CALL事件中所遇到的那樣。在傳統系統中,大多數程序標識符都是 8 個字符。

在程序中創建一組不可修改的標識符是執行此操作的一種方法。下列範例顯示選擇 "MYUTILPG" 作為單一識別碼:

程式識別碼範例

將方案與前後關聯產生關聯

該程序需要一個伴隨RuntimeContext實例。對於現代化程序, AWS Blu Age 使用屬於舊計劃一部分的數據結構自動生成伴隨上下文。

如果您正在編寫自己的程序,則還必須編寫伴隨上下文。

參考一下課程相關課程,您可以看到一個程序至少需要兩個同伴課程:

  • 一個配置類。

  • 使用配置的上下文類。

如果實用程序使用任何額外的數據結構,它應該被寫入,以及由上下文使用。

這些類應該在一個包中,該軟件包層次結構的一部分將在應用程序啟動時進行掃描,以確保上下文組件和配置將由 Spring 框架處理。

讓我們在實體項目中新創建的base package.myutilityprogram.business.context包中編寫一個最小的配置和上下文:

新公用程式的新專用組態和內容

以下是配置內容。它使用的配置構建類似於附近的其他現代化程序。您可能必須根據您的特定需求進行自定義。

新的程序配置

備註:

  • 一般命名慣例為「ProgramName組態」。

  • 它必須使用 @org. 彈簧框架. 上下文. 註釋. @Lazy

  • bean 名稱通常遵循ProgramNameContextConfiguration 慣例,但這不是強制性的。確保避免整個項目中的 bean 名稱衝突。

  • 要實現的單個方法必須返回一個Configuration對象。使用ConfigurationBuilder流利API來幫助您構建一個。

和相關的上下文:

Java 文件中的新程序上下文。

備註

  • 上下文類應該擴展現有的Context接口實現(RuntimeContext或者JicsRuntimeContext,這是一個JICS具RuntimeContext有特定項目的增強)。

  • 一般命名慣例是ProgramName上下文。

  • 您必須將其宣告為原型元件,並使用 @Lazy 註解。

  • 構造函數引用相關的配置,使用 @Qualifier 註釋來定位適當的配置類。

  • 如果實用程序使用一些額外的數據結構,它們應該是:

    • 寫入並添加到base package.business.model包中。

    • 在上下文中引用。看看其他現有的上下文類,看看如何引用數據串類,並根據需要調整上下文方法(構造函數/清理/重置)。

現在有專用上下文可用,讓新程序使用它:

新程式會使用新建立的前後關聯。

備註:

  • 該 getContext 方法必須嚴格執行,如圖所示,使用對ProgramContextStore類的 getOrCreate 方法和 auto 有線 Spring 的委託BeanFactory。單個程序標識符用於存儲在程序上下文ProgramContextStore; 這個標識符被引用為「程序主標識符」。

  • 伴隨配置和上下文類必須使用 @Import spring 註釋引用。

實作業務邏輯

當程式架構完成時,請實行新公用程式的企業邏輯。

在程序的run方法中執行此操作。此方法將在任何時候程序被調用,無論是由另一個程序或由腳本執行。

快樂的編碼!

處理程序註冊

最後,請確定新程式已在中正確註冊ProgramRegistry。如果您將新程序添加到已包含其他程序的軟件包中,則無需執行任何操作。在應用程序啟動時,將新程序拾取並註冊其所有鄰居程序。

如果您為程序選擇了其他位置,則必須確保該程序在 Tomcat 啟動時正確註冊。有關如何執行此操作的一些靈感,請查看服務項目中生成的 SpringbootLauncher 類的初始化方法(請參閱服務項目內容)。

檢查 Tomcat 的啟動日誌。每個程序註冊都會記錄下來。如果您的程序已成功註冊,您將找到匹配的日誌條目。

當您確定您的程序已正確註冊時,可以開始迭代業務邏輯編碼。

完整名稱對映

本節包含 AWS Blu Age 和第三方完整名稱對應的清單,可用於現代化的應用程式。

AWS 藍色時代完整名稱對應

短名稱 完整名稱

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

第三方完整名稱對應

短名稱 完整名稱

@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