Nablarch 6のRESTfulウェブサービスのExampleで開発中に再デプロイしたい

# What's？

タイトルとおりで、Nablarch 6のRESTfulウェブサービスのExampleを開発中に再デプロイできるように設定してみます。

# お題

デプロイ対象のアプリケーションサーバとMavenプラグインを使って、ソースコードを変更した際に再デプロイして開発を効率化したいという話です。

アプリケーションサーバは以下で試しました。

- Jetty
- Open Liberty

試したものの、諦めたのは以下です。

- Payara Micro
- WildFly

そもそも利用できるものがなかったのはApache Tomcatです。

Payara Microは、うまく起動できませんでした…。  
WildFlyは、プロジェクトの構成（URLマッピングやActionの実装）をけっこう変えないといけなさそうだったので諦めました…。

# 環境

今回の環境はこちら。

```shell
$ java --version
openjdk 21.0.3 2024-04-16
OpenJDK Runtime Environment (build 21.0.3+9-Ubuntu-1ubuntu122.04.1)
OpenJDK 64-Bit Server VM (build 21.0.3+9-Ubuntu-1ubuntu122.04.1, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.8 (36645f6c9b5079805ea5009217e36f2cffd34256)
Maven home: /home/charon/.sdkman/candidates/maven/current
Java version: 21.0.3, 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-116-generic", arch: "amd64", family: "unix"
```

# nablarch-example-restリポジトリのclone

nablarch-example-restリポジトリをclone。

```shell
$ git clone https://github.com/nablarch/nablarch-example-rest.git
```

6u1タグをチェックアウトしておきます。

```shell
$ cd nablarch-example-rest
$ git checkout 6u1
```

# Java 21に対応させる

nablarch-example-restリポジトリのNablarch 6向けのExampleはJava 17を前提としているので、Java 21に対応させます。

```xml:pom.xml
    <maven.compiler.source>21</maven.compiler.source>
    <maven.compiler.target>21</maven.compiler.target>
```

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

# 設定されているJetty Maven Pluginを無効に

プロジェクトにあらかじめ設定されている、Jetty Maven Pluginを無効にしておきます。

```xml:pom.xml
      <!--
      <plugin>
        <groupId>org.eclipse.jetty.ee10</groupId>
        <artifactId>jetty-ee10-maven-plugin</artifactId>
        <version>12.0.3</version>
        <configuration>
          <httpConnector>
            <port>9080</port>
          </httpConnector>
        </configuration>
      </plugin>
      -->
```

アプリケーションサーバごとのプラグインは、MavenのProfileで切り替えて指定することにします。

# H2 Databaseをサーバモードで起動する

RESTfulウェブサービスのExampleはH2 Databaseを使います。

```properties:src/main/resources/env.properties
nablarch.db.url=jdbc:h2:./h2/db/rest_example
```

これはプロセス内で動作する組み込みデータベースになるので、Jettyのような外部で再コンパイルするケースだったり再デプロイした時にアプリケーションが再起動する際に失敗します。

```shell
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal jp.co.tis.gsp:gsp-dba-maven-plugin:5.0.0:execute-ddl (default-cli) on project nablarch-example-rest: CREATE USER 実行中にエラー: : データベースが使用中 です: "/path/to/nablarch-example-rest/h2/db/rest_example.mv.db". 可能な解決策: 他の接続を全て閉じる; サ ーバモードを使う
[ERROR] Database may be already in use: "/path/to/nablarch-example-rest/h2/db/rest_example.mv.db". Possible solutions: close all other connection(s); use the server mode [90020-220]: The file is locked: /path/to/nablarch-example-rest/h2/db/rest_example.mv.db [2.2.220/7]
[ERROR] -> [Help 1]
```

なので、今回は`AUTO_SERVER=TRUE`を追加してサーバモードで起動するようにしておきます。

```properties:src/main/resources/env.properties
# JDBC接続URL(DataSourceを直接使用する際の項目)
nablarch.db.url=jdbc:h2:./h2/db/rest_example;AUTO_SERVER=TRUE
```

PostgreSQLなどに切り替える場合はこういう考慮は不要ですね。

# Jetty

Jettyの場合。

```xml:pom.xml
    <profile>
      <id>jetty</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.eclipse.jetty.ee10</groupId>
            <artifactId>jetty-ee10-maven-plugin</artifactId>
            <version>12.0.3</version>
            <configuration>
              <!-- hot deploy -->
              <scan>5</scan>
              <httpConnector>
                <port>9080</port>
              </httpConnector>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
```

`scan`を設定すると、アプリケーションが変更された際に再デプロイしてくれます。

https://qiita.com/charon/items/29824ac20fe43e0014fd

起動。

```shell
$ mvn -P jetty jetty:run
```

ただ、ソースコードを変更しても自動検知してくれるわけではなく、外部からコンパイルなどが行われるとそれを検出して再デプロイが行われます。

```shell
mvn compile
```

変更を検知する間隔（秒数）を`scan`で指定します。

# Open Liberty

Open Libertyの場合。

```xml:pom.xml
    <profile>
      <id>open-liberty</id>
      <build>
        <plugins>
          <plugin>
            <groupId>io.openliberty.tools</groupId>
            <artifactId>liberty-maven-plugin</artifactId>
            <version>3.10.3</version>
            <configuration>
              <runtimeArtifact>
                <groupId>io.openliberty</groupId>
                <artifactId>openliberty-kernel</artifactId>
                <version>24.0.0.7</version>
                <type>zip</type>
              </runtimeArtifact>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
```

Open Libertyの場合、カレントディレクトリが`mvn`コマンドを実行した場所ではなくなるので、H2 Databaseのデータファイルへのパスを絶対パスで指定する必要があります。

```properties
# JDBC接続URL(DataSourceを直接使用する際の項目)
#nablarch.db.url=jdbc:h2:./h2/db/rest_example;AUTO_SERVER=TRUE
nablarch.db.url=jdbc:h2:/path/to/nablarch-example-rest/h2/db/rest_example;AUTO_SERVER=TRUE
```

これもPostgreSQL等を使う場合は関係ありませんね。

また6u1の場合、Maven War Pluginに`classifier`の指定が入っているのですが、これはあるとちょっと都合が悪いので削除しておきます。

```xml
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.3.2</version>
        <configuration>
          <webXml>${webxml.path}</webXml>
          <!-- <classifier>${env.classifier}</classifier> -->
```

Open Libertyの設定。

```xml:src/main/liberty/config/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <feature>servlet-6.0</feature>
        <feature>pages-3.1</feature>
    </featureManager>

    <!-- This template enables security. To get the full use of all the capabilities, a keystore and user registry are required. -->

    <!-- For the keystore, default keys are generated and stored in a keystore. To provide the keystore password, generate an
        encoded password using bin/securityUtility encode and add it below in the password attribute of the keyStore element.
        Then uncomment the keyStore element. -->
    <!--
    <keyStore password=""/>
    -->

    <!--For a user registry configuration, configure your user registry. For example, configure a basic user registry using the
        basicRegistry element. Specify your own user name below in the name attribute of the user element. For the password,
        generate an encoded password using bin/securityUtility encode and add it in the password attribute of the user element.
        Then uncomment the user element. -->
    <basicRegistry id="basic" realm="BasicRealm">
        <!--
        <user name="yourUserName" password="" />
        -->
    </basicRegistry>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint id="defaultHttpEndpoint"
                  httpPort="9080"
                  httpsPort="9443" />

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

    <!-- Configures the application on a specified context root -->
    <webApplication contextRoot="/" location="nablarch-example-rest-6u1.war" />

    <!-- Default SSL configuration enables trust for default certificates from the Java runtime -->
    <ssl id="defaultSSLConfig" trustDefaultCerts="true" />
</server>
```

featureにはServletとJSPを指定しておきます。今回は最低限これだけあれば大丈夫です。

```xml
    <!-- Enable features -->
    <featureManager>
        <feature>servlet-6.0</feature>
        <feature>pages-3.1</feature>
    </featureManager>
```

JSPは必要なのか？という気もしますが、EL式を必要とするらしくこのfeatureが含まれていないと実行時にエラーになります。

起動。

```shell
$ mvn -P open-liberty compile liberty:dev
```

Open Libertyの場合はソースコードを変更すると自動的に検出 → 再ビルドを行い、再デプロイまで行われます。

便利なのですが、最初の起動がOpen Libertyサーバ自体を構築したりするので遅く、その点ではJettyに譲ります。  
一方で起動さえしてしまえば変更の検出や反映はとても速いので便利です。