Nablarch v6のウェブプロジェクト用アーキタイプを使って、ウェブアプリケーションを試す

# What's？

前にこんなことをやりました。

https://qiita.com/charon/items/91e04b713570a81ca108

この時はNablarch 5のRESTful ウェブサービスを対象にしていましたが、今回は以下のお題でやってみようかなと思います。

- Nablarch 6u1を使う
- ウェブプロジェクト用アーキタイプからウェブアプリケーションプロジェクトを作成する
- データベースをPostgreSQLに切り替える

# 環境

今回の環境はこちらです。

```shell
$ java --version
openjdk 21.0.4 2024-07-16
OpenJDK Runtime Environment (build 21.0.4+7-Ubuntu-1ubuntu222.04)
OpenJDK 64-Bit Server VM (build 21.0.4+7-Ubuntu-1ubuntu222.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.8 (36645f6c9b5079805ea5009217e36f2cffd34256)
Maven home: /home/charon/.sdkman/candidates/maven/current
Java version: 21.0.4, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-118-generic", arch: "amd64", family: "unix"


$ docker version
Client: Docker Engine - Community
 Version:           20.10.22
 API version:       1.41
 Go version:        go1.18.9
 Git commit:        3a2c30b
 Built:             Thu Dec 15 22:28:08 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.22
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.18.9
  Git commit:       42c8b31
  Built:            Thu Dec 15 22:25:58 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.14
  GitCommit:        9ba4b250366a5ddde94bb7c9d1def331423aa323
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

# プロジェクトを作成する

## アーキタイプからのプロジェクト作成

プロジェクトは、ブランクプロジェクトと呼ばれるものから作成するようです。

https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/index.html

セットアップに関する注意事項はこちら。

https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/beforeFirstStep.html

ウェブプロジェクトのセットアップ手順はこちら。

https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/setup_blankProject/setup_Web.html

プロジェクトを作成するためのWindowsバッチファイルが提供されているのですが、今回の環境はLinuxなのでバッチファイル内に書かれている`maven-archetype-plugin:2.4:generate`を直接実行します。

```shell
$ mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate \
  -DinteractiveMode=false \
  -DarchetypeGroupId=com.nablarch.archetype \
  -DarchetypeArtifactId=nablarch-web-archetype \
  -DarchetypeVersion=6u1 \
  -DgroupId=com.example \
  -DartifactId=hello-nablarch-web \
  -Dversion=0.0.1 \
  -Dpackage=com.example
```

作成できました。

```shell
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: nablarch-web-archetype:6u1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: hello-nablarch-web
[INFO] Parameter: version, Value: 0.0.1
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: packageInPathFormat, Value: com/example
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: hello-nablarch-web
[INFO] Parameter: version, Value: 0.0.1
[INFO] project created from Archetype in dir: /path/to/hello-nablarch-web
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.740 s
[INFO] Finished at: 2024-08-16T12:42:48+09:00
[INFO] ------------------------------------------------------------------------
```

プロジェクト内に移動。

```shell
$ cd hello-nablarch-web
```

ざっとファイルを見てみます。

```shell
$ find -type f
./README.md
./db/data/data.sql
./db/ddl/h2/drop.sql
./db/ddl/h2/create.sql
./db/ddl/postgresql/drop.sql
./db/ddl/postgresql/create.sql
./db/ddl/sqlserver/drop.sql
./db/ddl/sqlserver/create.sql
./db/ddl/db2/drop.sql
./db/ddl/db2/create.sql
./db/ddl/oracle/drop.sql
./db/ddl/oracle/create.sql
./tools/nablarch-tools.xml
./tools/static-analysis/jspanalysis/transform-to-html.xsl
./tools/static-analysis/jspanalysis/config.txt
./tools/static-analysis/spotbugs/spotbugs_exclude_for_production.xml
./tools/static-analysis/spotbugs/published-config/test/JakartaEEOpenApi.config
./tools/static-analysis/spotbugs/published-config/test/NablarchApiForProgrammer.config
./tools/static-analysis/spotbugs/published-config/test/NablarchTestingApiForArchitect.config
./tools/static-analysis/spotbugs/published-config/test/NablarchApiForArchitect.config
./tools/static-analysis/spotbugs/published-config/test/NablarchTestingApiForProgrammer.config
./tools/static-analysis/spotbugs/published-config/test/JavaOpenApi.config
./tools/static-analysis/spotbugs/published-config/production/JakartaEEOpenApi.config
./tools/static-analysis/spotbugs/published-config/production/NablarchApiForProgrammer.config
./tools/static-analysis/spotbugs/published-config/production/NablarchApiForArchitect.config
./tools/static-analysis/spotbugs/published-config/production/JavaOpenApi.config
./.gitignore
./pom.xml
./h2/db/SAMPLE.mv.db.org
./h2/db/SAMPLE.mv.db
./h2/bin/h2.bat
./h2/bin/h2w.bat
./h2/bin/h2.sh
./h2/bin/h2-2.2.220.jar
./src/env/dev/resources/web-boot.xml
./src/env/dev/resources/log.properties
./src/env/dev/resources/env.properties
./src/env/dev/resources/handler_dev.xml
./src/env/dev/resources/override_dev.xml
./src/env/dev/resources/db-for-webui_dev.xml
./src/env/prod/resources/env.properties
./src/main/java/com/example/package-info.java
./src/main/java/com/example/domain/package-info.java
./src/main/java/com/example/domain/SampleDomainManager.java
./src/main/java/com/example/domain/SampleDomainBean.java
./src/main/java/com/example/SampleAction.java
./src/main/webapp/images/nablarch-logo.jpg
./src/main/webapp/WEB-INF/web.xml
./src/main/webapp/WEB-INF/errorPages/USER_ERROR.jsp
./src/main/webapp/WEB-INF/errorPages/SERVICE-UNAVAILABLE-ERROR.jsp
./src/main/webapp/WEB-INF/errorPages/TAMPERING-DETECTED.jsp
./src/main/webapp/WEB-INF/errorPages/ERROR.jsp
./src/main/webapp/WEB-INF/errorPages/REQUEST_ENTITY_TOO_LARGE.jsp
./src/main/webapp/WEB-INF/errorPages/PAGE_NOT_FOUND_ERROR.jsp
./src/main/webapp/WEB-INF/errorPages/PERMISSION-ERROR.jsp
./src/main/webapp/WEB-INF/test/test.jsp
./src/main/resources/common.properties
./src/main/resources/web-boot.xml
./src/main/resources/log.properties
./src/main/resources/entity/data-model_sqlserver.edm
./src/main/resources/entity/data-model.edm
./src/main/resources/entity/data-model_oracle.edm
./src/main/resources/entity/data-model_postgresql.edm
./src/main/resources/entity/data-model_db2.edm
./src/main/resources/routes.xml
./src/main/resources/messages.properties
./src/main/resources/web-component-configuration.xml
./src/main/resources/app-log.properties
./src/main/resources/net/unit8/http/router/routes.properties
./src/test/java/com/example/SampleActionRequestTest.xls
./src/test/java/com/example/test/XxxxHttpRequestExtension.java
./src/test/java/com/example/test/XxxxHttpRequestTestSupport.java
./src/test/java/com/example/test/XxxxHttpRequestTest.java
./src/test/java/com/example/SampleActionRequestTest.java
./src/test/resources/data/CODE_NAME.csv
./src/test/resources/data/CODE_PATTERN.csv
./src/test/resources/log.properties
./src/test/resources/nablarch/test/http-request-test/html-check-config.csv
./src/test/resources/override_test.xml
./src/test/resources/unit-test.xml
```

構成についてはこちらに説明があります。

https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/MavenModuleStructures/index.html

[pj-webプロジェクト](https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/MavenModuleStructures/index.html#pj-web)

プロファイルを確認しておきます。

```shell
$ mvn help:all-profiles
```

一覧。

```shell
[INFO] Listing Profiles for Project: com.example:hello-nablarch-web:war:0.0.1
  Profile Id: development (Active: true, Source: pom)
  Profile Id: BACKUP (Active: false, Source: pom)
  Profile Id: prod (Active: false, Source: pom)
  Profile Id: gsp (Active: false, Source: pom)
  Profile Id: ossrh (Active: false, Source: pom)
```

サンプルのActionクラス。

```java:src/main/java/com/example/SampleAction.java
package com.example;

import nablarch.common.web.session.SessionUtil;
import nablarch.fw.ExecutionContext;
import nablarch.fw.web.HttpRequest;
import nablarch.fw.web.HttpResponse;

/**
 * 疎通確認用のアクションクラス。
 *
 * 以下の機能について、疎通確認を行う。
 * <ul>
 *     <li>ディスパッチ機能</li>
 *     <li>データベースアクセス</li>
 *     <li>メッセージ機能</li>
 *     <li>コード機能</li>
 *     <li>スレッドコンテキスト</li>
 *     <li>リソースマッピング</li>
 * </ul>
 * <p>
 * 疎通確認に失敗した場合は、その時点で例外が発生する。
 * </p>
 * <p>
 * 全ての疎通確認に成功した場合、画面に疎通確認結果が表示される。
 * </p>
 *
 * @deprecated TODO 疎通確認用のクラスです。確認完了後、削除してください。
 */
public class SampleAction {

    /**
     * @param request リクエストコンテキスト
     * @param context HTTPリクエストの処理に関連するサーバ側の情報
     * @return HTTPレスポンス
     */
    public HttpResponse index(HttpRequest request, ExecutionContext context) {
        //セッションストアの動作確認用
        //(DBストア使用時(デフォルトはDBストア)、USER_SESSIONテーブルにセッションのデータが格納されます。疎通確認後、USER_SESSIONテーブルのデータを削除してください)
        Integer number = SessionUtil.or(context, "number", Integer.valueOf(0));
        context.setRequestScopedVar("number", number);
        SessionUtil.put(context, "number", number + 1);

        return new HttpResponse("/WEB-INF/test/test.jsp");
    }


}
```

フォワード先のJSP。

```jsp::src/main/webapp/WEB-INF/test/test.jsp
<%--
TODO 疎通確認用のクラスです。確認完了後、ディレクトリごと削除してください。
--%>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<%@ taglib prefix="n" uri="http://tis.co.jp/nablarch" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Webアプリケーション疎通確認</title>
</head>
<body>
<h1>Congratulations!</h1>

アプリケーションのデプロイに成功しました。
以下の疎通確認結果を確認してください。

<h2>各機能の疎通確認結果</h2>

<h3>ディスパッチ機能</h3>

<%-- このJSPに遷移しているということはディスパッチは機能している --%>
ディスパッチ機能は正常に動作しています。

<h3>セッションストア</h3>

リロードする度に、以下のカウンタがカウントアップされていれば成功です。
<p>
カウンタ：<n:write name="number"/>
</p>

<h3>コード管理機能</h3>
セレクトメニューが表示されていれば成功です。

<n:form name="dummyForm">
  <n:codeSelect name="sample.codeSelectValues" codeId="C0000001" multiple="true"/>
</n:form>

<h3>データベースアクセス機能</h3>

<%-- コード機能で例外は発生しないということは、DBアクセスは機能している --%>
データベースアクセス機能は正常に動作しています。

<h3>メッセージ管理機能</h3>
<p>
「」内にメッセージが表示されていれば成功です。
</p>
メッセージID=errors.doubleSubmission のメッセージは
<p>
「<n:message messageId="errors.doubleSubmission" />」
</p>
です。

<h3>リソースマッピング</h3>
<p>
画像が表示されていれば成功です。
</p>

<n:img src="/images/nablarch-logo.jpg" alt="logo"/>

<hr/>
確認完了後は、疎通確認用のリソースを削除してください。

</body>
</html>
```

## Java 21に対応する

今回はJava 21で使いたいので、以下の手順に従って`pom.xml`に書かれているJavaのバージョンを変更します。

```xml:pom.xml
  <properties>
    <!-- ソース及びclassファイルが準拠するJavaのバージョン-->
    <java.version>21</java.version>
```

[Java21で使用する場合のセットアップ方法 / Javaバージョンの変更](https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/setup_blankProject/setup_Java21.html#java)

## 疎通確認

では、疎通確認に従って動かしてみましょう。

[疎通確認](https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/setup_blankProject/setup_Web.html#firststepwebstartuptest)

テストを実行します。

```shell
$ mvn test
```

テストが通りました。

```shell
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.717 s - in com.example.SampleActionRequestTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
```

1度`mvn clean`。

```shell
$ mvn clean
```

次に起動確認をしてみましょう。

[起動確認](https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/setup_blankProject/setup_Web.html#id6)

コンパイルしてJettyを起動します。

```shell
$ mvn compile jetty:run
```

起動しました。

```shell
[INFO] Started ServerConnector@7204d98f{HTTP/1.1, (http/1.1)}{0.0.0.0:9080}
[INFO] Started oejs.Server@120d6cbf{STARTING}[12.0.3,sto=0] @10969ms
[INFO] Automatic redeployment disabled, see 'mvn jetty:help' for more redeployment options
```

`http://localhost:9080/`にアクセスして確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/8d501b3e-ff95-eb44-e06a-b58b2c8387e9.png)

OKですね。

リロードするとカウントアップされています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/840ae85e-0605-688d-f08b-abed71e1644e.png)

Jettyを再起動すると、カウンタはリセットされます。

# データベースをPostgreSQLに変更する

次に、使用するデータベースをH2 DatabaseからPostgreSQLに変更してみます。  
※今回はgsp-dba-maven-pluginについては考えないことにします

https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/blank_project/CustomizeDB.html

PostgreSQLは、16.4を使うことにします（16.2までは稼働環境で確認済みだそうで）。

https://nablarch.github.io/docs/6u1/doc/application_framework/application_framework/nablarch/platform.html

必要なSQLファイルはデータベースの種類ごとに`db`ディレクトリに入っているようなので、これを使います。

```shell
$ tree db
db
├── data
│   └── data.sql
└── ddl
    ├── db2
    │   ├── create.sql
    │   └── drop.sql
    ├── h2
    │   ├── create.sql
    │   └── drop.sql
    ├── oracle
    │   ├── create.sql
    │   └── drop.sql
    ├── postgresql
    │   ├── create.sql
    │   └── drop.sql
    └── sqlserver
        ├── create.sql
        └── drop.sql

7 directories, 11 files
```

SQLファイルはShift_JISで書かれているようなので、UTF-8に変換します。

```shell
$ iconv -f sjis -t utf-8 db/ddl/postgresql/create.sql -o db/ddl/postgresql/create.sql.utf8
$ iconv -f sjis -t utf-8 db/data/data.sql -o db/data/data.sql.utf8
```

PostgreSQLを起動。

```shell
$ docker container run -it --rm --name postgres \
  -v $(pwd)/db:/data/db \
  -e POSTGRES_USER=postgres_user \
  -e POSTGRES_PASSWORD=postgres_password \
  -e POSTGRES_DB=mydatabase \
  postgres:16.4-bookworm
```

コンテナに入って、DDL実行とデータの登録。

```shell
$ docker container exec -it postgres bash
# psql -U postgres_user -f /data/db/ddl/postgresql/create.sql.utf8 mydatabase
# psql -U postgres_user -f /data/db/data/data.sql.utf8 mydatabase
```

今回はホスト側のポートにバインドせず、別ホストのように扱ってみることにしましょう。コンテナのIPアドレスを確認します。

```shell
$ docker container inspect postgres | grep IPA
            "SecondaryIPAddresses": null,
            "IPAddress": "172.22.0.2",
                    "IPAMConfig": null,
                    "IPAddress": "172.22.0.2",
```

`pom.xml`に定義されているJDBCドライバーを、H2からPostgreSQLのものに差し替えます。

```xml:pom.xml
        <!-- TODO: プロジェクトで使用するDB製品にあわせたJDBCドライバに修正してください。 -->
        <!--
        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <version>2.2.220</version>
          <scope>runtime</scope>
        </dependency>
        -->
        <dependency>
          <groupId>org.postgresql</groupId>
          <artifactId>postgresql</artifactId>
          <version>42.7.3</version>
        </dependency>
```

開発環境向けの`env.properties`を修正。  
※本番環境向けの`env.properties`はJNDI経由でコネクションプールを取得するようになっているので置いておきます

```properties:src/env/dev/resources/env.properties
##
## 開発環境用設定ファイル
##
# JDBC接続ドライバクラス(DataSourceを直接使用する際の項目)
# (TODO: 開発環境で使用するDBに合わせて変更する。)
#nablarch.db.jdbcDriver=org.h2.Driver
nablarch.db.jdbcDriver=org.postgresql.Driver

# JDBC接続URL(DataSourceを直接使用する際の項目)
# (TODO: 開発環境用の接続先に変更する。H2の接続URLは、データファイルの所在とユーザ名で決定される。変更する際は、理解したうえで変更すること)
#nablarch.db.url=jdbc:h2:./h2/db/SAMPLE
nablarch.db.url=jdbc:postgresql://172.22.0.2:5432/mydatabase

# DB接続ユーザ名(DataSourceを直接使用する際の項目)
# (TODO: 開発環境用のユーザ名に変更する)
#nablarch.db.user=SAMPLE
nablarch.db.user=postgres_user

# DB接続パスワード(DataSourceを直接使用する際の項目)
# (TODO: 開発環境用のパスワードに変更する)
#nablarch.db.password=SAMPLE
nablarch.db.password=postgres_password

# DBスキーマ名(DataSourceを直接使用する際の項目)
# (TODO: 自動テスト用のスキーマ名に変更する。H2使用時は「PUBLIC」を設定すること)
#nablarch.db.schema=PUBLIC
nablarch.db.schema=public
```

DialectをH2 DatabaseからPostgreSQLのものに変更。

```xml:src/main/resources/web-component-configuration.xml
  <!-- ダイアレクト設定 -->
  <!-- TODO:使用するDBに合わせてダイアレクトを設定すること -->
  <!-- <component name="dialect" class="nablarch.core.db.dialect.H2Dialect" /> -->
  <component name="dialect" class="nablarch.core.db.dialect.PostgreSQLDialect" />
```

ひとまず、テストしてみます。

```shell
$ mvn test
```

OKでした。

```shell
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.435 s - in com.example.SampleActionRequestTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
```

起動してみます。

```shell
$ mvn compile jetty:run
```

こちらもOKでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/6bcecf74-ed69-61f4-56bf-f7b6d5c941da.png)

というわけで、PostgreSQLで動作するように変更できました、と。