IntelliJ IDEAからCloudBees上のWildflyにJavaEE7アプリをデプロイする


##概要
IntelliJ IDEA 13からMavenでCloudBees上のWildflyにJava EE 7アプリケーションをデプロイする方法を説明します。
Java EE 7アプリケーションの例として簡単なWebSocketを用いたサンプルを実装します。
CloudBeesとのMaven連携は[CloudBees Maven Guide](http://wiki.cloudbees.com/bin/view/RUN/MavenGuide)に従い、CloudBees提供のbees-maven-pluginを用います。

##環境
* IntelliJ IDEA 13
* [CloudBees Wildfly ClickStack](http://www.cloudbees.com/press-room/cloudbees-adds-wildfly-support-java-ee-7-rolled-out-wildfly-8.cb)

##webappプロジェクトの作成
Mavenプロジェクトを作成します。
archetypeにmaven-archetype-webappを指定します。
![Screen Shot 2014-01-19 at 10.45.26 AM.png](https://qiita-image-store.s3.amazonaws.com/0/29426/f79e74e8-a818-94b1-9e97-9700ba93379b.png "Screen Shot 2014-01-19 at 10.45.26 AM.png")

##bees-maven-pluginをpom.xmlに追加
CloudBeesとのMaven連携には、CloudBees提供のbees-maven-pluginを利用するため、pom.xmlにpluginを記載します。
また、今回はJava EE 7アプリケーションを作成するので、Java EE 7 APIのdependencyを追加しています。

```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/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>net.otyk</groupId>
      <artifactId>michelle</artifactId>
      <packaging>war</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>michelle Maven Webapp</name>
      <url>http://maven.apache.org</url>
      <!-- CloudBees start -->
      <pluginRepositories>
        <pluginRepository>
          <id>cloudbees-public-release</id>
          <url>http://repository-cloudbees.forge.cloudbees.com/public-release</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
      <!-- CloudBees end -->
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
        <!-- Java EE 7 start -->
        <dependency>
          <groupId>javax</groupId>
          <artifactId>javaee-api</artifactId>
          <version>7.0</version>
          <scope>provided</scope>
        </dependency>
        <!-- Java EE 7 end -->
      </dependencies>
      <build>
        <finalName>michelle</finalName>
        <plugins>
          <!-- CloudBees start -->
          <plugin>
            <groupId>com.cloudbees</groupId>
            <artifactId>bees-maven-plugin</artifactId>
            <version>1.3.2</version>
          </plugin>
          <!-- CloudBees end -->
        </plugins>
      </build>
    </project>
```

##webappを実装
Java EE 7アプリケーションとしては、WebSocketのサンプルを実装してみます。
#### web.xml

```xml
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    </web-app>
```

#### HelloWS.java
WebSocketサーバーエンドポイントです。
Sessionをメモリ上に保持し、受信したメッセージをそのまま各Sessionに送信する処理を実装しています。

```java

    import javax.websocket.OnClose;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;
    
    @ServerEndpoint("/hellows")
    public class HelloWS {

        static Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());

        @OnOpen
        public void onOpen(Session session) {
            sessions.add(session);
        }

        @OnMessage
        public void onMessage(String message) {
            for (Session session : sessions) {
                session.getAsyncRemote().sendText(message);
            }
        }

        @OnClose
        public void onClose(Session session) {
            sessions.remove(session);
        }
    }
```

#### ws.html
簡単なWebSocketのクライアントコードです。
フォームに入力されたテキストを送信する処理と、受信したイベントやメッセージを随時表示する処理を実装しています。

```html
    <!DOCTYPE html>
    <html>
    <head>
        <title>HelloWS</title>
        <script type="text/javascript" src="jquery-1.10.2.js"></script>
        <script type="text/javascript">
            $(function() {
                var ws = new WebSocket("ws://APPURL/hellows")
                ws.onopen = function() {
                    $("#log").prepend("ws:onopen<br>");
                };
                ws.onmessage = function(message) {
                    $("#log").prepend(message.data + "<br>");
                };
                ws.onerror = function() {
                    $("#log").prepend("ws:onerror<br>");
                };
                ws.onclose = function() {
                    $("#log").prepend("ws:onclose<br>");
                };
                $("#send").click(function() {
                    ws.send($("#msg").val());
                    $("#msg").val("");
                });
                $(window).unload(function() {
                    ws.onclose = function() {};
                    ws.close();
                });
            });
        </script>
        </head>
        <body>
            <input id="msg" type="text">
            <button id="send">send</button>
            <div id="log"></div>
        </body>
    </html>
```

プロジェクト内の構成は以下のようになりました。

![Screen Shot 2014-01-19 at 8.19.14 PM.png](https://qiita-image-store.s3.amazonaws.com/0/29426/d39daa44-d3f3-8c07-8b79-a28b5feea0f5.png "Screen Shot 2014-01-19 at 8.19.14 PM.png")


##bees:deployゴールの作成
IntelliJ IDEAのメニューのRun->Edit Configurationから、CloudBeesへのwebappのデプロイを行うMavenゴールを作成します。
オプションの詳細は、[CloudBees Maven Guide](http://wiki.cloudbees.com/bin/view/RUN/MavenGuide)に記載されています。

![Screen Shot 2014-01-19 at 5.57.40 PM.png](https://qiita-image-store.s3.amazonaws.com/0/29426/1497e3af-9e51-dabb-97cc-8548df7b4e47.png "Screen Shot 2014-01-19 at 5.57.40 PM.png")

##bees:deployゴールの実行
bees:deployゴールを実行すると、webappがビルドされ、warがCloudBees上にデプロイされます。
bees:deployゴールにあらかじめ指定したオプションが足りない場合、このゴールの実行中に必要な情報を入力するように要求されます。（APIキー、Secretキーなど）

![Screen Shot 2014-01-19 at 6.14.41 PM.png](https://qiita-image-store.s3.amazonaws.com/0/29426/4265120a-2b91-6115-eed2-158108d07dc1.png "Screen Shot 2014-01-19 at 6.14.41 PM.png")


##動作確認
2つのブラウザウィンドウを立ち上げ、それぞれhttp://APPURL/ws.htmlにアクセスし、テキストを送信すると、、、

![Screen Shot 2014-01-19 at 8.28.10 PM.png](https://qiita-image-store.s3.amazonaws.com/0/29426/8e814571-12b3-06be-c660-c9cd82f71afa.png "Screen Shot 2014-01-19 at 8.28.10 PM.png")

成功です！
ちなみに、CloudBeesでWebSocketを利用する際には[こちら](http://qiita.com/yuukiohtaka/items/2c87677fcc0df35f47bf)に注意です。

##その他
IntelliJ IDEAにはCloudBees Integrationというプラグインがあります。
こちらを有効化した場合にはIntelliJの組み込み機能としてCloudBeesと連携するためのRun Configurationが作成できるようになりますが、ClickStackからWildflyが選択できませんでした。
そのため、今回はIntelliJのCloud Integration機能による連携は試していません。

![Screen Shot 2014-01-19 at 8.32.10 PM.png](https://qiita-image-store.s3.amazonaws.com/0/29426/6eee318b-bec3-216d-eca8-5983e8c95d66.png "Screen Shot 2014-01-19 at 8.32.10 PM.png")