GlassFish/Payara Embeddedとwarをまとめてパッケージングする

# 目的
GlassFish/Payara Embeddedを使えば、GlassFish/Payara EmbeddedのjarとJavaEEアプリのwarの2つ（とJava SE）だけでJavaEEアプリを簡単に走らせることができる。しかし、他人に配布する場合などは、そのjarとwarもまとめてしまって1つのjar（とJava SE）だけでJavaEEアプリを走らせることができれば便利である。単にwarを含めるだけなら手作業で行っても目的は達成できるが、warのビルドからjarにパッケージングするまでをワンアクションで行いたい。そのためのpom.xmlの書き方を検証した。
なお、以下ではPayara Embeddedを用いて検証しているため、Payara Embeddedとのみ記述するが、GlassFish Embeddedでも同様の手順で目的が達成できるはずである。

なお、[次の投稿](http://qiita.com/masaha03/items/49b9a73b96b1e4f2038e)で今回の投稿の発展版を記述しているが、その内容をまとめたサンプルプロジェクトをGitHubで公開している。追加されている内容はあるものの、今回の内容もほぼそのままの形で含まれている。

- https://github.com/masaha03/payara-embedded-sample

# 課題
1. jarの前にwarをビルドする
1. jarにwarを含める
1. jarに含まれたwarをPayara Embeddedにデプロイする

# 方法
## jarの前にwarをビルドする
Mavenのマルチモジュールプロジェクトを、以下の構成で作成する。`payara-emmbeded-sample-app(以降app)`はJavaEEアプリのモジュール、`payara-emmbeded-sample-main(以降main)`はPayara Embeddedを駆動するモジュールである。
`main`の前に`app`をビルドすることができれば、課題1は解決する。

```
payara-embedded-sample
├── payara-emmbeded-sample-app
└── payara-emmbeded-sample-main
```

これは`main`のpom.xmlに以下を加えることで可能である。

```xml:pom.xml
<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">
   ...
    <dependencies>
        ...
        <dependency>
            <groupId>payara-embedded-sample</groupId>
            <artifactId>payara-embedded-sample-app</artifactId>
            <version>0.1-0</version>
            <type>war</type>
            <scope>test</scope>
        </dependency>
        ...
    </dependencies>
    ...
</project>
```

`main`がappに依存していることを明確にしている。scopeはtestにしているが、多分どれにしても問題ない（未検証）。こうしておけば、親モジュールのcompileを行ったときに、mavenは自動的に依存関係を解決し、compileの順番を適切に決定してくれる。子モジュール（`main`）のcompileではないことに注意。


## jarにwarを含める
力技だが、以下で対応可。

```xml:pom.xml
<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">
    ...
    <build>
        <resources>
            <resource>
                <directory>../payara-embedded-sample-app/target</directory>
                <includes>
                    <include>app.war</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.5.5</version>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>jp.mshackers.payara.embedded.sample.PayaraEmbedded</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            ...
        </plugins>
        ...
    </build>
    ...
</project>
```

単純に、`app`のtargetディレクトリ内に生成されるwarをresourceに含めるようにした。前項でビルドの依存関係が規定されているため、`main`のビルド時には必ず`app.war`が存在している。
maven-assembly-pluginは、依存しているjar（つまりPayara embeddedのjar）を同梱するために使用している。

## jarに含まれたwarをPayara Embeddedにデプロイする
なんのひねりもないが、Class Loaderを使ってInputStreamで読み込む。

```java:PayaraEmbedded.java
package jp.mshackers.payara.embedded.sample;

import org.glassfish.embeddable.GlassFish;
import org.glassfish.embeddable.GlassFishException;
import org.glassfish.embeddable.GlassFishProperties;
import org.glassfish.embeddable.GlassFishRuntime;

import java.io.InputStream;

public class PayaraEmbedded {

    public static void main(String[] args) throws GlassFishException {
        GlassFishRuntime runtime = GlassFishRuntime.bootstrap();

        GlassFishProperties glassFishProperties = new GlassFishProperties();
        glassFishProperties.setPort("http-listener", 9080);

        GlassFish glassFish = runtime.newGlassFish(glassFishProperties);
        glassFish.start();

        InputStream inputStream = PayaraEmbedded.class.getClassLoader()
                .getResourceAsStream("app.war");
        glassFish.getDeployer().deploy(inputStream);
    }
}

```

# 実行環境

```bash:
$ date
2015年 10月 4日 日曜日 20時55分48秒 JST
$ mvn --version
Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T20:57:37+09:00)
Maven home: /usr/local/Cellar/maven/3.3.3/libexec
Java version: 1.8.0_40, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.10.5", arch: "x86_64", family: "mac"
$ java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.10.5
BuildVersion:	14F27
```

# 関連する記事

- [GlassFish/Payara Embeddedとwarとdomainと起動スクリプトをまとめてパッケージングし配布用zipを作る](http://qiita.com/masaha03/items/49b9a73b96b1e4f2038e)