GlassFish 5.0にアプリケーションをデプロイしてみる（asadminコマンド、Maven Cargo Plugin）

# What's？

ちょっと、GlassFishを動かしてみたいなと思いまして。

今回はJava EE 8を使いたいので、GlassFish 5を使い、簡単なJAX-RS＋CDIを動かすところまでやってみたいと思います。

# GlassFish 5

GlassFish 5までのWebサイトはこちらですね。

https://javaee.github.io/glassfish/

ドキュメント。

https://javaee.github.io/glassfish/documentation

GlassFish 5.1以降はEE4J傘下にいるので、こちらのWebサイトを見ることになります。

https://projects.eclipse.org/projects/ee4j.glassfish

Jakarta EE 8以降であれば、こちらを使いましょうということですね。

# 環境

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

```shell
$ java -version
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)


$ mvn --version
Apache Maven 3.8.3 (ff8e977a158738155dc465c6a97ffaf31982d739)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 1.8.0_292, vendor: Private Build, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-89-generic", arch: "amd64", family: "unix"
```

# GlassFish 5.0のインストール

まずは、GlassFish 5をインストールしましょう。

https://javaee.github.io/glassfish/download

Installation Guideはこちら。

https://javaee.github.io/glassfish/doc/5.0/installation-guide.pdf

Fulll PlatformとWeb Profileがありますが、今回はWeb Profileにしました。  
Fulll PlatformとWeb Profileに含まれているJava EEの機能の差は、Installation Guideのp.20に書かれています。

zipファイルをダウンロードして

```shell
$ curl -OL http://download.oracle.com/glassfish/5.0.1/release/glassfish-5.0.1-web.zip
```

展開。

```shell
$ unzip glassfish-5.0.1-web.zip
$ cd glassfish5
```

あとはQuick Start Guideを見つつ進めていきます。

https://javaee.github.io/glassfish/doc/5.0/quick-start-guide.pdf

GlassFishを起動。というか、ドメインを起動、ですね。

```shell
$ bin/asadmin start-domain
```

こんな内容がコンソールに出力されます。ドメインやログの位置がわかりますね。

```shell
Waiting for domain1 to start ....
Successfully started the domain : domain1
domain  Location: /path/to/glassfish5/glassfish/domains/domain1
Log File: /path/to/glassfish5/glassfish/domains/domain1/logs/server.log
Admin Port: 4848
Command start-domain executed successfully.
```

また、GlassFishが使用するポートは、Quick Start Guideのp.11に書いてあります。

この状態で`http://localhost:4848/` にアクセスすると、管理UIを見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/32c1c547-b26b-6e47-fd2b-86e0b4f6e151.png)

その他、コマンド。

ドメインの一覧表示。

```shell
$ bin/asadmin list-domains
domain1 running
Command list-domains executed successfully.
```

ドメインの停止。

```shell
$ bin/asadmin stop-domain
Waiting for the domain to stop .
Command stop-domain executed successfully.
```

この後、アプリケーションをデプロイするので、再度ドメインを起動。

```shell
$ bin/asadmin start-domain
```

ちなみに、`domain1`というのはデフォルトのドメインで、`start-domain`や`stop-domain`には明示的にドメインを指定することもできます。

```shell
NAME                                                                                                                                                                                     
       start-domain - starts the DAS of the specified domain                                                                                                                             

SYNOPSIS
           start-domain [--help]
           [--debug={true|false}] [--domaindir domain-dir]
           [--dry-run={true|false}] [--upgrade={true|false}]
           [--verbose={true|false}] [--watchdog={true|false}]
           [domain-name]

------------------------------------------------------------------------------------------

NAME
       stop-domain - stops the Domain Administration Server of the specified
       domain

SYNOPSIS
           stop-domain [--help] [--domaindir domaindir]
           [--force={true|false}] [--kill={false|true}]
           [domain-name]
```

今回は、このままデフォルトの`domain1`を使います。

# サンプルプログラムを作る

では、GlassFishにデプロイするアプリケーションを作っていきます。

アプリケーションを作る際は、このあたりを参考にするとよいでしょう。

https://javaee.github.io/tutorial/

https://github.com/javaee/tutorial-examples

今回は、JAX-RS（JSON）＋CDIを使った簡単なサンプルにしましょう。

作成したプログラムは、こちら。

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>glassfish5-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>8.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
    </build>
</project>
```

`web.xml`は不要にしています。

```xml
        <failOnMissingWebXml>false</failOnMissingWebXml>
```

JAX-RS有効化。

```java:src/main/java/org/example/JaxrsActivator.java
package org.example;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("")
public class JaxrsActivator extends Application {
}
```

JAX-RSリソースクラス。

```java:src/main/java/org/example/HelloResource.java
package org.example;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("hello")
@ApplicationScoped
public class HelloResource {
    @Inject
    MessageService messageService;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public HelloResponse hello(HelloRequest request) {
        return new HelloResponse(messageService.format(request.getMessage()));
    }

    public static class HelloRequest {
        String message;

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

    public static class HelloResponse {
        String message;

        public HelloResponse(String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }
}
```

CDI管理Bean。

```java:src/main/java/org/example/MessageService.java
package org.example;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class MessageService {
    public String format(String message) {
        return String.format("★★★ %s ★★★", message);
    }
}
```

パッケージング。

```shell
$ mvn package
```

`target/glassfish5-demo.war`というファイルができるので、ここから先はこのファイルをデプロイしていきます。

# アプリケーションをGlassFishにデプロイする

デプロイの方法は、Quick Start Guideのp.13に書かれています。

https://javaee.github.io/glassfish/doc/5.0/quick-start-guide.pdf

以下のコマンドで、デプロイ。

```shell
$ bin/asadmin deploy /path/to/glassfish5-demo/target/glassfish5-demo.war
Application deployed with name glassfish5-demo.
Command deploy executed successfully.
```

確認。

```shell
$ curl -H 'Content-Type: application/json' localhost:8080/glassfish5-demo/hello -d '{"message": "Hello GlassFish!!"}'
{"message":"★★★ Hello GlassFish!! ★★★"}
```

OKですね。

その他、コマンド。

アプリケーションの一覧。

```shell
$ bin/asadmin list-applications
glassfish5-demo  <web>  
Command list-applications executed successfully.
```

再デプロイの場合は、`--name`でアプリケーション名を指定して`redeploy`です。

```shell
$ bin/asadmin redeploy --name glassfish5-demo /path/to/glassfish5-demo/target/glassfish5-demo.war
Application deployed with name glassfish5-demo.
Command redeploy executed successfully.
```

アンデプロイ。

```shell
$ bin/asadmin undeploy glassfish5-demo
Command undeploy executed successfully.
```

これが基本的な操作でしょうか。

# Maven Cargo Pluginを使ってデプロイする

次に、Mavenでもデプロイしてみようと思い、Maven Cargo Pluginを使ってみることにしました。

https://codehaus-cargo.github.io/cargo/Home.html

https://codehaus-cargo.github.io/cargo/Maven+3+Plugin.html

ドキュメントを見ていても使い方がよくわからなかったのですが、掲載されている記事を参考にすると良さそうです。

https://codehaus-cargo.github.io/cargo/Articles.html

今回は、この記事を参考にしました。

https://github.com/hantsy/jakartaee9-starter-boilerplate/blob/master/docs/deploy-cargo.md

今回はこういう設定に。

```xml
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven3-plugin</artifactId>
                <version>1.9.8</version>
                <configuration>
                    <container>
                        <containerId>glassfish5x</containerId>
                        <type>installed</type>
                        <home>/path/to/glassfish5</home>
                    </container>
                    <configuration>
                        <type>existing</type>
                        <home>/path/to/glassfish5/glassfish/domains</home>
                        <properties>
                            <cargo.glassfish.domain.name>domain1</cargo.glassfish.domain.name>
                        </properties>
                    </configuration>
                </configuration>
            </plugin>
        </plugins>
    </build>
```

Codehaus Cargoでは、実行時にアプリケーションサーバーをダウンロードしてきて使う方法と、既存（インストール済み）のアプリケーションサーバーを使う方法がありますが、今回は先ほどインストールしたものを使います。

https://codehaus-cargo.github.io/cargo/Standalone+Local+Configuration.html

https://codehaus-cargo.github.io/cargo/Existing+Local+Configuration.html

よって、`type`が`installed`で`existing`です。

```xml
                <configuration>
                    <container>
                        <containerId>glassfish5x</containerId>
                        <type>installed</type>
                        <home>/path/to/glassfish5</home>
                    </container>
                    <configuration>
                        <type>existing</type>
```

`containerId`は、使うアプリケーションサーバーのバージョンに合ったものを選ぶ必要があります。今回は`glassfish5x`です。

https://codehaus-cargo.github.io/cargo/GlassFish+5.x.html

設定はこれでいいのですが。

ここでだいぶハマったのは、`admin`ユーザーのパスワードを設定していないとこんな感じのエラーになって、延々とハマり続けます。

```shell
[INFO] --- cargo-maven3-plugin:1.9.8:deploy (default-cli) @ glassfish5-demo ---                                                                                                          
[INFO] [edDeployerDeployMojo] Resolved container artifact org.codehaus.cargo:cargo-core-container-glassfish:jar:1.9.8 for container glassfish5x                                          
[INFO] [talledLocalContainer] Parsed GlassFish version = [5.0.1]                                                                                                                         
[INFO] [talledLocalContainer] Command deploy failed.                                                                                                                                     
[INFO] [talledLocalContainer] Authentication failed for user: admin                                                                                                                      
[INFO] [talledLocalContainer] with password from password file: /path/to/glassfish5/glassfish/domains/password.properties                    
[INFO] [talledLocalContainer] (Usually, this means invalid user name and/or password)
```

`glassfish/domains/domain1/password.properties`というパスワードファイルを使っているというログが出ているのですが、このファイル内に設定されているパスワードはデフォルトだと設定されていないみたいなんですよね。  
つまり、`admin`ユーザーにはパスワードが設定されていない状態です。

```shell:glassfish/domains/domain1/password.properties
AS_ADMIN_PASSWORD=adminadmin
```

というわけで、管理コンソールからパスワードを設定。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/4968c407-23d6-f746-dae6-1ec816eb81a2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/abbb6770-0032-2a24-5e43-e32331a3f93b.png)

すると、WARファイルをデプロイできるようになります。

```shell
$ mvn cargo:deploy
```

先に、`mvn package`でWARファイルを作っておくことが必要です。

再デプロイ。

```shell
$ mvn cargo:redeploy
```

アンデプロイ。

```shell
$ mvn cargo:undeploy
```

ちなみに、このようにMaven Cargo Pluginでデプロイできるように構成すると、通常のコマンドで実行する場合にユーザー名とパスワードを指定する必要がでてきます。

```shell
$ bin/asadmin deploy /path/to/glassfish5-demo/target/glassfish5-demo.war
Enter admin user name>  admin
Enter admin password for user "admin"> 


## もしくは
$ bin/asadmin --user admin --passwordfile glassfish/domains/password.properties deploy /path/to/glassfish5-demo/target/glass
fish5-demo.war
Application deployed with name glassfish5-demo.
Command deploy executed successfully.
```

ユーザーのパスワードを設定したので、当然といえば当然なのですが。

Maven Cargo Pluginからアプリケーションサーバーの起動や停止も行うことができます。

```shell
$ mvn cargo:start
$ mvn cargo:stop
```

今回は、こんなところでしょうか。