CICS-Javaアプリケーションを動かす - (3)Gradleによるビルド管理

# はじめに
CICS TS V5.6では、CICS-Javaアプリケーションのビルド管理ツールとして、Mavenと合わせてGradleもサポートされています。ここではGradleを使ったCICS-Javaアプリのビルド管理を試してみます。

## 関連記事
[CICS-Javaアプリケーションを動かす - (1)単純なサンプルアプリの稼働](https://qiita.com/tomotagwork/items/aac10ad84fe83d88bb5f)
[CICS-Javaアプリケーションを動かす - (2)Mavenによるビルド管理](https://qiita.com/tomotagwork/items/a487484835d4e8dd2d6f)
[CICS-Javaアプリケーションを動かす - (3)Gradleによるビルド管理](https://qiita.com/tomotagwork/items/6fae5bd3440635ad26af)
[CICS-Javaアプリケーションを動かす - (4)Spring Bootアプリ](https://qiita.com/tomotagwork/items/9bdef46069e1591103ba)
[CICS-Javaアプリケーションを動かす - (5)JCICSXの利用](https://qiita.com/tomotagwork/items/cac290f6435453c19b7b)

# 環境情報
**開発環境**
Windows10
CICS Explorer V5.5.0.9

**実行環境**
z/OS V2.4
CICS Transaction Server for z/OS V5.6

# 事前準備
これはMavenのケースとほぼ同様です。(Mavenの代わりにGradleを使います)

### 適当なJavaEE開発環境

EclipseやVS CodeなどJavaEEアプリケーション開発ができるものを適宜使用してください。
今回はサンプルをそのまま使うので特にソースの編集はしないので使わなくてもよいですが、通常はなんらかの開発環境使うことになるでしょう。Gradle, gitなどと連携できるとよいかも。
CICS Explorerを一緒に使うのであればEclipse使っておけばOK。

### CICS Explorer

こちらも必須ではありませんが、CICSの資源定義とか確認するのに使えます。
以下の辺りを参考にCICS ExplorerというEclipseベースのツールをダウンロードしてセットアップしておきます。
参考: [Downloading and starting CICS Explorer](https://www.ibm.com/support/knowledgecenter/SSSQ3W_5.5.0/com.ibm.cics.core.help/topics/concepts/install_planning_client.html)
※このツールはCICS利用者は無償で使えるツールです。

### Gradle
以下の手順に従ってインストールします。
[Installing Gradle](https://docs.gradle.org/6.5/userguide/installation.html)
基本的には、ダウンロードしたものを解凍してパスを通すだけ。

前提としてJava8以降が必要になります。

```
c:\>java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
```

以下から現時点での最新版Gradle V6.5をダウンロードします(gradle-6.5.zip)。
[Releases](https://gradle.org/releases/)

適当なディレクトリに展開します。(ここでは(c:\x\Gradle\gradle-6.5\)
展開先のbin(C:\x\Gradle\gradle-6.5\bin)をPATHに追加します。

確認

```
c:\>gradle -v

------------------------------------------------------------
Gradle 6.5
------------------------------------------------------------

Build time:   2020-06-02 20:46:21 UTC
Revision:     a27f41e4ae5e8a41ab9b19f8dd6d86d7b384dad4

Kotlin:       1.3.72
Groovy:       2.5.11
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          1.8.0_144 (Oracle Corporation 25.144-b01)
OS:           Windows 10 10.0 amd64
```

これでOKです。


### git

gitHubに提供されるサンプルを入手して使用するので、gitもインストールしておきます。
セットアップ方法などはその辺に転がってるので割愛。

```
c:\>git --version
git version 2.21.0.windows.1
```

## 実行環境(z/OS, CICS)
※ホスト側はMavenのケースとまったく同じです。Mavenのシナリオ実施済みであればそのまま同じものを使えばよいです。

サンプルを稼働させるCICSリージョンを用意します。
ここでは、CICSplex管理下の**CT56B4A1**という名前のリージョンを使うことにします。
そこに、Javaアプリケーションを稼働させるためのJVMServerという資源を追加します。
今回は、CICS-Liberty用のサンプル(JavaEEアプリケーション)を使用するので、Liberty用のJVMServerを作成しておきます。

### JVMプロファイル

USS上にJVMプロファイルを準備します。(JVMServerに関するプロパティーは実質このUSS上のファイルに指定します。JVMSERVER資源定義ではこのJVMプロファイルのファイル名をポイントすることになります。)
サンプルが提供されているのでそれをコピーして使用します。

/var/cicsts/cicsts56/CT56B4A1/JVMProfiles というディレクトリを作成し、そこに/usr/lpp/cicsts/cicsts56/JVMProfiles/DFHWLP.jvmprofile(CICS導入ディレクトリ下に配置されているLiberty用のサンプル定義)をコピーします。
環境に合わせて適宜カスタマイズします。

```xxx:DFHWLP.jvmprofile抜粋
JAVA_HOME=/usr/lpp/java/J8.0_64/
WORK_DIR=/var/cicsts/cicsts56/CT56B4A1/work
WLP_INSTALL_DIR=/usr/lpp/cicsts/cicsts56/wlp
-Dcom.ibm.cics.jvmserver.wlp.autoconfigure=true
-Dcom.ibm.cics.jvmserver.wlp.server.host=*
-Dcom.ibm.cics.jvmserver.wlp.server.http.port=56441
-Dcom.ibm.cics.jvmserver.wlp.server.https.port=56451
-Xms128M
-Xmx256M
-Xmso1M
-Xgcpolicy:gencon
-Xscmx256M
-Xshareclasses:name=cicsts%g,groupAccess,nonfatal
-Xtune:virtualized
-Dcom.ibm.tools.attach.enable=no
-Dfile.encoding=ISO-8859-1
_BPXK_DISABLE_SHLIB=YES
```

### SIT

上のプロパティーファイルを配置したディレクトリを、SITパラメーター"JVMPROFILEDIR"に指定します。

```
JVMPROFILEDIR=/var/cicsts/cicsts56/CT56B4A1/JVMProfiles 
```

変更反映のためにリージョンを再起動します。

### JVMServer定義

JVMSERVER資源定義を準備します。
製品提供のDFH$WLPというグループにあるJVMSERVER定義"DFHWLP"を適当なグループにコピーしてインストールします。

```
OBJECT CHARACTERISTICS                                    CICS RELEASE = 0730
 CEDA  View JVmserver( DFHWLP   )                                            
  JVmserver      : DFHWLP                                                    
  Group          : TAGGRP                                                    
  DEScription    : CICS JVM server to run WLP samples                        
  Status         : Enabled            Enabled | Disabled                     
  Jvmprofile     : DFHWLP                                         (Mixed Case
  Lerunopts      : DFHAXRO                                                   
  Threadlimit    : 015                1-256                                  
 DEFINITION SIGNATURE                                                        
  DEFinetime     : 06/04/20 16:20:21                                         
  CHANGETime     : 06/04/20 16:20:21                                         
  CHANGEUsrid    : CICSUSER                                                  
  CHANGEAGEnt    : CSDApi             CSDApi | CSDBatch                      
  CHANGEAGRel    : 0730                                                                     
```

※Jvmprofile: DFHWLPとなっていますが、これはSITのJVMPROFILEDIRに指定されたディレクトリ下のDFHWLP.jvmprofileというファイルがJVMプロパティーファイルとして使用されることを意味します。


CEMT I JVMSERVERで見てEnableになっていればOK。

```
I JVMS                                             
STATUS:  RESULTS - OVERTYPE TO MODIFY              
 Jvm(DFHWLP  ) Ena     Prf(DFHWLP  ) Ler(DFHAXRO ) 
    Threadc(005) Threadl( 015 ) Cur(48314096)           
```
 
### CICS Bundle Deployment API
CICS TS V5.6から提供されるようになったCICS Bundle Deployment APIのセットアップをしておく必要があります。
この機能は、CMCIと呼ばれるRESTベースの管理APIの一つとしてアプリケーションのデプロイ用に追加されました。
ターゲットのCICSリージョンを管理するWUIサーバー上にCMCIをセットアップし、CMCI JVMサーバーのプロパティーで、CICS Bundle Deployment API用のパラメーターを指定します。
参考: [How it works: CICS bundle deployment API](https://www.ibm.com/support/knowledgecenter/SSGMCP_5.6.0/fundamentals/cpsm/cics-bundle-api.html)

最低限必要な設定は以下の通りです。
USS上にBundleファイル配置用のディレクトリを作成します。ここでは`/var/cicsts/cicsts56/bundles`とします。
WUIのCMCI JVM Server用のJVMプロファイル(EYUCMCIJ.jvmprofile)に、以下のパラメーターを設定します。
`-Dcom.ibm.cics.jvmserver.cmci.bundles.dir=/var/cicsts/cicsts56/bundles`

# サンプル稼働確認

## ローカルにクローン作製

ローカルのPCの適当なディレクトリに、`https://github.com/IBM/cics-bundle-gradle.git`のクローンを作成します。

```
C:\y\workspace\cicsts56>git clone https://github.com/IBM/cics-bundle-gradle.git
Cloning into 'cics-bundle-gradle'...
remote: Enumerating objects: 125, done.
remote: Counting objects: 100% (125/125), done.
remote: Compressing objects: 100% (87/87), done.
remote: Total 1855 (delta 43), reused 86 (delta 13), pack-reused 1730Receiving objects:  99% (1837/1855), 2.08 MiB | 2.01 MiB/s
Receiving objects: 100% (1855/1855), 4.19 MiB | 2.83 MiB/s, done.
Resolving deltas: 100% (610/610), done.
```

## ファイル構造の理解
samples以下のgradle-multipart-sampleというサンプルを使うので、ディレクトリを移動して、ファイルの構造を見てみます。

```
C:\y\workspace\cicsts56\cics-bundle-gradle\samples\gradle-multipart-sample>tree /f /a
フォルダー パスの一覧:  ボリューム Windows
ボリューム シリアル番号は 1866-E2FC です
C:.
|   build.gradle
|   gradlew
|   gradlew.bat
|   README.md
|   settings.gradle
|
+---gradle
|   \---wrapper
|           gradle-wrapper.jar
|           gradle-wrapper.properties
|
+---gradle-bundle-demo
|       build.gradle
|
\---gradle-war-demo
    |   build.gradle
    |
    \---src
        \---main
            +---java
            |   \---demo
            |           SimpleServlet.java
            |
            \---web-app
                |   index.html
                |   index.js
                |   style.css
                |
                +---images
                |       cics.png
                |
                \---WEB-INF
                        web.xml


```

build.gradleが複数あって階層構造になっていますが、これはGradleの"マルチプロジェクト"という構成になっています。
参考: [Gradle によるマルチプロジェクトの基本](https://maku77.github.io/gradle/multi-project.html)

通常CICS-Javaアプリを作成する場合、アプリ本体であるOSGiプロジェクト(jar)やWebプロジェクト(WAR)を作成し、アプリケーションを取りまとめるためのCICSバンドルプロジェクトを作成し、これらをひとまとまりのパッケージにしてデプロイする、ということを行います。
今回のサンプルは、gradle-war-demo部分がアプリ本体(WAR)のプロジェクト、gradle-bundle-demo部分がCICSバンドルプロジェクトに相当し、それらをひとまとめにパッケージングするために、マルチ・プロジェクトとして親のgradle-multipart-sampleプロジェクトでまとめています。build.gradleの関係を整理すると以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/26626de6-3964-296d-d8da-2a9a1f314d04.png)

以下のコマンドでプロジェクトの関係を表示させることもできるようです。

```
c:\y\workspace\cicsts56\cics-bundle-gradle\samples\gradle-multipart-sample>gradle -q projects

------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'gradle-multipart-sample'
+--- Project ':gradle-bundle-demo'
\--- Project ':gradle-war-demo'

To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :gradle-bundle-demo-test04:tasks
```


## 中身の確認/編集

### gradle-war-demo(javaEEアプリ)

こちらはCICS-Libertyでの稼働を想定したWebアプリです。単純なhtml, Servletで実装されています。(Mavenのサンプルと同じっぽいです)

```java:SimpleServlet.java
package demo;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ibm.cics.server.InvalidRequestException;
import com.ibm.cics.server.Task;

/**
 * Servlet implementation class SimpleServlet
 */
@WebServlet("/SimpleServlet")
public class SimpleServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");

        response.getWriter().print("Hello world!");
        Task task = Task.getTask();

        try {
            String userid = task.getUSERID();
            response.setContentType("text/html");
            response.getWriter().print("\nI am " + userid);
        } catch (InvalidRequestException e) {
            throw new RuntimeException(e);
        }
    }

}
```

JCICSのTask Classで稼働している自タスクのオブジェクト取得して、そこから自分自身を実行しているユーザー情報を取得して表示させるという処理をしています。

アプリ本体は特に変更の必要は無いので中身の確認だけしておきます。

### gradle-bundle-demo(CICSバンドル)
通常CICS ExplorerでCICS-Javaアプリを作成する場合(Gradleを使わない場合)、CICSバンドルプロジェクトを作成し、そこに組み込むアプリ(WARやOSGiなど)を設定していくことになります。結果的にcics.xmlやxxx.warbundleというファイル等が作成されることになります。

ここはCICSバンドルプロジェクトに相当する部分ですがbuild.gradleしか存在していません。Gradleの仕組みを使って依存関係を指定することで、CICS提供のGradleプラグイン(cics-bundle-gradle)がCICSバンドルプロジェクトに必要なファイル群を自動で作成してくれるようです。従って、ユーザーとしてはbuild.gradleに必要な設定をするだけで、CICSバンドルプロジェクトを直接的には意識しなくてよくなります。

build.gradleを環境に合わせて編集します。
変更箇所はコメント(1)～(7)に記載

```gradle:gradle-bundle-demo-test04\build.gradle
plugins {
    id 'com.ibm.cics.bundle' version '1.0.0'
}

group 'com.ibm.cics'
version '1.0.0'

repositories {
    mavenCentral()
}

cicsBundle {
    build {
        defaultJVMServer = 'DFHWLP' // (1)JVMSERVER名
    }
    deploy {
        cicsplex = 'C73PLX'         // (2) ターゲットのCICSリージョンが属しているCICSplex名
        region   = 'CT56B4A1'       // (3) ターゲットのCICSリージョン名
        bunddef  = 'GRDBUNDL'       // (4) ターゲットのCICSリージョン上に定義したバンドル定義資源名
        csdgroup = 'TAGGRP'         // (5) (4)のバンドル定義が属しているCSDグループ名
        url = 'http://etp1:56002'   // (6) WUIのCMCIのURL
        username = 'TAG'            // (7) CMCIによるDeployment API発行時に使用するユーザーと
        password = '********'       // 　　パスワード
        //caution: uncomment the line below to disable TLS/SSL checking for certificates
        //insecure = true
    }
}

dependencies {
    cicsBundlePart group: 'org.codehaus.cargo', name: 'simple-war', version: '1.7.7', ext: 'war'
    cicsBundlePart project(path:':gradle-war-demo', configuration: 'archives')
}
```

ここで、CICSバンドル用プロジェクトのディレクトリ名をgradle-bundle-demo から gradle-bundle-demo-test04 に変更しました。このディレクトリ名がUSS上に生成物を転送する際のディレクトリ名に使われます。`<CICSバンドル用プロジェクト名>_<version>`というディレクトリが、WUIのJVMServerで指定したバンドル・ディレクトリ配置用のディレクトリ(ここでは`/var/cicsts/cicsts56/bundles`)に作成され、各種ファイルが展開されます。
例: `/var/cicsts/cicsts56/gradle-bundle-demo-test04_1.0.0/`

その他変更パラメータは以下の通りです。

**(1)defaultjvmserver**: アプリを稼働させる対象のJVMSERVER名を指定します。事前にターゲットのCICSリージョンにインストールしておく必要があります。
**(2)cicsplex**: ターゲットのCICSリージョンが属しているCICSplex名
**(3)region**: ターゲットのCICSリージョン名
**(4)bunddef**: ターゲットのCICSリージョン上に定義したバンドル定義資源名
**(5)csdgroup**: (4)のバンドル定義が属しているCSDグループ名
**(6)url**: WUIのCMCIのURLを指定します。このWUIについてはCICS Bundle Deployment APIを有効化しておく必要があります。(雛形だと`http://`の記載が無いですがこれを指定しないとエラーになるので注意！)
**(7)username/password**: CMCIによるDeployment API発行時に使用するユーザー、パスワード

※ここでは、まだビルド/デプロイ操作はしません。

プロジェクトのディレクトリ名を変更したので、親のsetting.gradleもそれに合わせて修正します。

```gradle:setting.gradle
rootProject.name = 'gradle-multipart-sample'
include 'gradle-war-demo'
include 'gradle-bundle-demo-test04'
```

## BUNDLE定義作成
上のbuild.gradleで指定した内容に従って、バンドル定義を作成します。

```
OBJECT CHARACTERISTICS                                    CICS RELEASE = 0730
 CEDA  View Bundle( GRDBUNDL )                                               
  Bundle         : GRDBUNDL                                                  
  Group          : TAGGRP                                                    
  DEScription    : CICS-BUNDLE-DEMO                                          
  Status         : Enabled            Enabled | Disabled                     
  BUndledir      : /var/cicsts/cicsts56/bundles/gradle-bundle-demo-test04_1.0
  (Mixed Case)   : .0                                                        
                 :                                                           
                 :                                                           
                 :                                                           
  BAsescope      :                                                           
  (Mixed Case)   :                                                           
                 :                                                           
                 :                                                           
                 :                                                           
 DEFINITION SIGNATURE                                                        
  DEFinetime     : 06/17/20 14:19:33                                         
```

CSDグループは(5)、BUNDLE定義名は(4)、BUNDLEDIRはプロジェクトのディレクトリ名およびバージョン情報の値を元に指定します。
※ここでは、まだインストール操作はしません

## サンプル修正
※追記: github上のサンプルが修正されたのでここで記載している対応は不要になりました。
参考: ["web-app" should be "webapp" in gradle-war-demo sample #74](https://github.com/IBM/cics-bundle-gradle/issues/74)

そのうち修正されるような気がしますが、提供されているサンプルのディレクトリ構成に不備があり、このまま後続の処理を実施するとサンプル稼働でうまく動きません。
`...\gradle-multipart-sample\gradle-war-demo\src\main\web-app\`というディレクトリがあるのですが、この`web-app`を`webapp`に変更しておきましょう(ハイフンを削除)。
GradleのWarプラグインの動作としては、デフォルトだとwebapp以下のファイルはWAR作成時にコピーされるのですが、サンプルだとweb-appになっているのでこのディレクトリ配下のweb.xmlやindex.html等がコピーされず、サンプルアプリが呼び出せない状態になってしまいます。

参考: [Gradle - The War Plugin](https://docs.gradle.org/current/userguide/war_plugin.html#sec:war_default_settings)

>The default behavior of the War task is to copy the content of src/main/webapp to the root of the archive. Your webapp directory may of course contain a WEB-INF sub-directory, which may contain a web.xml file. Your compiled classes are compiled to WEB-INF/classes. All the dependencies of the runtime [1] configuration are copied to WEB-INF/lib.


## ビルド/デプロイ実行
※以下の手順では、ビルド「gradelw build」とデプロイ「gradlew deployCICSBundle」を2段階で実行していますが、後者のコマンドだけでもビルド～デプロイ実行が行われます。

ビルドを行うために、gradle-multipart-sampleディレクトリ下で、以下のコマンドを実行します。
最初は必要なパッケージのダウンロードなどが走るので時間がかかります。

```
c:\y\workspace\cicsts56\cics-bundle-gradle\samples\gradle-multipart-sample>gradlew build
Downloading https://services.gradle.org/distributions/gradle-5.0-all.zip
...........................................................................................................................

Welcome to Gradle 5.0!

Here are the highlights of this release:
 - Kotlin DSL 1.0
 - Task timeouts
 - Dependency alignment aka BOM support
 - Interactive `gradle init`

For more details see https://docs.gradle.org/5.0/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)

> Task :gradle-bundle-demo-test04:buildCICSBundle
Adding Java-based bundle parts from 'cicsBundlePart' dependency configuration
Adding Java-based bundle part: 'C:\Users\TomohiroTaguchi\.gradle\caches\modules-2\files-2.1\org.codehaus.cargo\simple-war\1.7.7\5f462015066db63c2e240b4fc3674c6f4910bb73\simple-war-1.7.7.war'
Adding Java-based bundle part: 'C:\y\workspace\cicsts56\cics-bundle-gradle\samples\gradle-multipart-sample\gradle-war-demo\build\libs\gradle-war-demo-1.0.0.war'
Adding non-Java-based bundle parts from 'src/main/resources'

BUILD SUCCESSFUL in 1m 12s
4 actionable tasks: 4 executed
```

これでプロジェクトのビルドが行われました。
gradle-bundle-demoディレクトリ以下にはCICSバンドルプロジェクトの各ファイルと、それらをまとめたzipファイル(デプロイ時に使用される)等が生成されます。

```
c:\y\workspace\cicsts56\cics-bundle-gradle\samples\gradle-multipart-sample>tree gradle-bundle-demo-test04 /f /a
フォルダー パスの一覧:  ボリューム Windows
ボリューム シリアル番号は 1866-E2FC です
C:\Y\WORKSPACE\CICSTS56\CICS-BUNDLE-GRADLE\SAMPLES\GRADLE-MULTIPART-SAMPLE\GRADLE-BUNDLE-DEMO-TEST04
|   build.gradle
|
\---build
    +---distributions
    |       gradle-bundle-demo-test04-1.0.0.zip
    |
    \---gradle-bundle-demo-test04-1.0.0
        |   gradle-war-demo-1.0.0.war
        |   gradle-war-demo-1.0.0.warbundle
        |   simple-war-1.7.7.war
        |   simple-war-1.7.7.warbundle
        |
        \---META-INF
                cics.xml
```

次にデプロイ作業を実施します。
gradle-multipart-sampleディレクトリ下で、以下のコマンドを実行します。

```
c:\y\workspace\cicsts56\cics-bundle-gradle\samples\gradle-multipart-sample>gradlew deployCICSBundle

> Task :gradle-bundle-demo-test04:deployCICSBundle
Task deployCICSBundle

BUILD SUCCESSFUL in 12s
5 actionable tasks: 1 executed, 4 up-to-date
```

CICS Explorerで、バンドル、バンドルパーツの状況を見てみると、正常にインストールされてEnableになっていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/7f7ad2a2-9a8a-88c6-2c90-1bef7ebd7a93.png)

つまり上のGradleのコマンドで以下のような処理が行われたことになります。

ビルド: JavaEEアプリ(gradle-war-demo)のコンパイル/WARの作成、CICSバンドル(gradle-bundle-demo)の生成
パッケージ: 関連モジュールのパッケージング
デプロイ: CICSバンドルファイルのUSSへの転送/展開、BUNDLE定義のインストール


## アプリ稼働確認
ターゲットのCICS上で稼働するLibertyにデプロイされたアプリをブラウザからアクセスしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/a7f71361-169b-06f9-f1f4-3faae8aeff7a.png)

デフォルトのユーザー"CICSUSER"で稼働しているのでそのユーザー名が表示されています。

これできちんとアプリケーションが稼働するところまで確認できました！