CLOVER🍀

That was when it all began.

WildFly Maven Pluginで、WildFly/Infinispan Serverにデプロイする

今更ながら、WildFly Maven Pluginを使うと、WildFlyMavenプロジェクトからデプロイできることを
知りました…。

WildFly Maven Plugin – Introduction

JenkinsからWildFlyへのリモートデプロイ(pom.xmlの更新) - そごうソフトウェア研究所

wildfly-maven-pluginを使ったintegration test

見れば、デプロイ、アンデプロイ以外にも、WildFlyを起動したりとけっこういろいろできるみたいです。

いつも「standalone/deployments」ディレクトリにコピーしてたり、管理CLIからdeployコマンドでデプロイ
してたりしたので、あんまり気にしていませんでした…。

ちょっとしたエントリから、同じプラグインでInfinispan Serverにもデプロイできることを知ったので、
これを機に試してみましょう。

WildFlyに、WildFly Maven Pluginを使ってデプロイする

それでは、WildFlyにデプロイするための簡単なJava EEアプリケーションを作成します。

なお、WildFlyはダウンロード&展開&起動済みとします。管理用のユーザーだけ、先に作っておきましょう。

$ bin/add-user.sh -u wildfly-admin -p wildfly-password

ユーザーは、 wildfly-admin / wildfly-password とします。また、WildFlyは「172.17.0.2」で動作している
ものとします。ここに、別のサーバーからデプロイします。

pom.xmlの設定。プラグインのところは、あとで書きます。project.artifactIdは、「simple-ee-app」とします。

    <packaging>war</packaging>

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

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

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <!-- あとで -->
            </plugin>
        </plugins>
    </build>

簡単なJAX-RSアプリケーションを作成。
src/main/java/org/littlewings/simple/ee/JaxrsActivator.java

package org.littlewings.simple.ee;

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

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

src/main/java/org/littlewings/simple/ee/HelloResource.java

package org.littlewings.simple.ee;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("hello")
public class HelloResource {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello World!!";
    }
}

で、これでパッケージングすればWARファイルができあがりますと。

$ mvn package

...

$ ls -l target/simple-ee-app.war 
-rw-rw-r-- 1 xxxxx xxxxx 3688  411 22:29 target/simple-ee-app.war
デプロイする

このWARファイルをデプロイするには、「mvn wildfly:deploy」を実行します。

プラグインの設定は、このようにしました。

            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>1.2.0.Alpha4</version>
                <configuration>
                    <hostname>172.17.0.2</hostname>
                    <username>wildfly-admin</username>
                    <password>wildfly-password</password>
                </configuration>
            </plugin>

「hostname」のデフォルト値はlocalhostだったりするので、ローカルでWildFlyにデプロイする場合は特に指定する
必要はありません。

各設定項目は、こちらを参照のこと。

WildFly Maven Plugin – wildfly:deploy

では、実行。

$ mvn wildfly:deploy

こんな感じに表示されれば、デプロイは成功しています。

4 11, 2017 10:33:32 午後 org.xnio.Xnio <clinit>
INFO: XNIO version 3.5.0.Beta2
4 11, 2017 10:33:32 午後 org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.5.0.Beta2
4 11, 2017 10:33:33 午後 org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 5.0.0.Beta18
4 11, 2017 10:33:33 午後 org.wildfly.security.Version <clinit>
INFO: ELY00001: WildFly Elytron version 1.1.0.Beta24
[INFO] Authenticating against security realm: ManagementRealm
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:36 min
[INFO] Finished at: 2017-04-11T22:33:42+09:00
[INFO] Final Memory: 20M/240M
[INFO] ------------------------------------------------------------------------

WildFly側にもデプロイのログが出力されています。

2017-04-11 13:33:37,532 INFO  [org.jboss.as.repository] (management-handler-thread - 4) WFLYDR0001: Content added at location /opt/wildfly/standalone/data/content/03/274be09c16dbf174b627a0b5e4b1e5929f0b2e/content
2017-04-11 13:33:37,577 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) WFLYSRV0027: Starting deployment of "simple-ee-app.war" (runtime-name: "simple-ee-app.war")
2017-04-11 13:33:41,590 INFO  [org.jboss.resteasy.resteasy_jaxrs.i18n] (ServerService Thread Pool -- 70) RESTEASY002225: Deploying javax.ws.rs.core.Application: class org.littlewings.simple.ee.JaxrsActivator
2017-04-11 13:33:41,671 INFO  [org.hibernate.validator.internal.util.Version] (ServerService Thread Pool -- 70) HV000001: Hibernate Validator 5.2.4.Final
2017-04-11 13:33:42,465 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 70) WFLYUT0021: Registered web context: /simple-ee-app
2017-04-11 13:33:42,504 INFO  [org.jboss.as.server] (management-handler-thread - 4) WFLYSRV0010: Deployed "simple-ee-app.war" (runtime-name : "simple-ee-app.war")

ちなみに、「mvn wildfly:deploy」は「mvn package」もやってしまうので、実はパッケージングせずに
「mvn wildfly:deploy」だけでもよかったりします。

パッケージングをスキップしてデプロイだけをしたい場合は、「mvn wildfly:deploy-only」を実行すればOKです。
WildFly Maven Plugin – wildfly:deploy-only

$ mvn wildfly:deploy-only

1度デプロイしたあとは管理CLIのdeployコマンドの場合はアンデプロイするか「force」オプションを使わないと
デプロイできないのですが、このプラグインの場合は「force」がデフォルトでtrueなので、そのまま再デプロイ
可能だったりします。

redeployとか、redeploy-onlyもありますけどね。
WildFly Maven Plugin – wildfly:redeploy

WildFly Maven Plugin – wildfly:redeploy-only

ところで、終了時に時々ClassNotFoundExceptionが出るんですけど…。

Exception in thread "Remoting "management-client" task-11" java.lang.NoClassDefFoundError: org/xnio/XnioWorker$2
	at org.xnio.XnioWorker.shutDownTaskPool(XnioWorker.java:769)
	at org.xnio.nio.NioXnioWorker.shutdown(NioXnioWorker.java:277)
	at org.jboss.remoting3.EndpointImpl.finishPhase1(EndpointImpl.java:254)
	at org.jboss.remoting3.EndpointImpl.closeTick1(EndpointImpl.java:237)
	at org.jboss.remoting3.EndpointImpl.access$200(EndpointImpl.java:92)
	at org.jboss.remoting3.EndpointImpl$TrackingExecutor.finishWork(EndpointImpl.java:832)
	at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:819)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.xnio.XnioWorker$2
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:271)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:247)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:239)
	... 10 more

それでもふつうに動いてはいそうですが。

アンデプロイする

アンデプロイする場合は、「mvn wildfly:undeploy」を実行します。

$ mvn wildfly:undeploy

こんな感じで。

Infinispan Serverにデプロイする

同じWildFly Maven Pluginで、Infinispan ServerにRemote Taskをデプロイすることもできます。

こちらも、Infinispan Serverはダウンロード&展開&起動済みとします。

管理ユーザーは追加しておきます。

$ bin/add-user.sh -u ispn-admin -p ispn-password

依存関係とWildFly Maven Pluginの設定は、こちら。Infinispan Serverは、WildfFlyと同じく「172.17.0.2」で動作しているものとします。
というか、設定はほぼ同じです。

    <dependencies>
        <dependency>
            <groupId>org.infinispan</groupId>
            <artifactId>infinispan-tasks-api</artifactId>
            <version>9.0.0.Final</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>1.2.0.Alpha4</version>
                <configuration>
                    <hostname>172.17.0.2</hostname>
                    <username>ispn-admin</username>
                    <password>ispn-password</password>
                </configuration>
            </plugin>
        </plugins>
    </build>

なお、Infinispan ServerのRemote TaskのパッケージングはJARになります。アーティファクト名は「remote-task-wildfly-deploy」とし、
これがそのままJARファイルの名前になります。

では、サンプル敵にRemote Taskを作成します。
src/main/java/org/littlewings/infinispan/task/HelloTask.java

package org.littlewings.infinispan.task;

import org.infinispan.tasks.ServerTask;
import org.infinispan.tasks.TaskContext;

public class HelloTask implements ServerTask<String> {
    @Override
    public void setTaskContext(TaskContext taskContext) {
        // no-op
    }

    @Override
    public String getName() {
        return "hello-task";
    }

    @Override
    public String call() throws Exception {
        return "Hello World!!";
    }
}

Service Providerでの設定にも記載。
src/main/resources/META-INF/services/org.infinispan.tasks.ServerTask

org.littlewings.infinispan.task.HelloTask

あとは「mvn wildfly:deploy」でWildFlyと同様にデプロイできます。

$ mvn wildfly:deploy

その他は一緒なので割愛しますが、こちらは確認もしておきましょう。

テストコードで確認することにします。

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.6.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.infinispan</groupId>
            <artifactId>infinispan-client-hotrod</artifactId>
            <version>9.0.0.Final</version>
            <scope>test</scope>
        </dependency>

こんな感じで。
src/test/java/org/littlewings/infinispan/task/HelloTaskTest.java

package org.littlewings.infinispan.task;

import java.util.Collections;

import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class HelloTaskTest {
    @Test
    public void callServerTask() {
        RemoteCacheManager cacheManager =
                new RemoteCacheManager(new ConfigurationBuilder().addServer().host("172.17.0.2").port(11222).build());

        try {
            RemoteCache<String, String> cache = cacheManager.getCache("default");

            String result = cache.execute("hello-task", Collections.emptyMap());
            assertThat(result).isEqualTo("Hello World!!");

            cache.stop();
        } finally {
            cacheManager.stop();
        }
    }
}

できましたと。

まとめ

WildFly Maven Pluginを使って、WildFlyJava EEアプリケーション、Infinispan ServerにRemote Taskをデプロイしてみました。

そもそもプラグインに気づいていなかったのと、Infinispan Serverにもデプロイできるのが割と衝撃的でした。まあ、ベースが
WildFlyだから確かに…という感じではありますが、発想がなかったです…。

気づくきっかけになったのは、こちらのブログエントリでした。いやー、知っておいてよかったです。
Infinispan: In Memory Data Grid Patterns Demos from Devoxx France!

Infinispan ServerへのRemote Taskのデプロイで使ったソースコードについては、こちらに置いています。
https://github.com/kazuhira-r/infinispan-getting-started/tree/master/remote-task-wildfly-deploy