normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

Azure Websites 上の Java アプリをリモートデバッグする

最近の投稿は Java 成分が多めになっているが、昨今の職種と役割のせいだと信じたいところ。さて、今回は Azure Websites 上の Java アプリにリモートデバッグを行う。当然ながらローカル環境と Azure Websites 上では少なからず差異があるため、今回紹介するリモートデバッグの機能は有用な人が多いはずだ。

こちらは既に Microsoft からソースコードを含めた利用方法が GitHub/Azure/azure-websites-java-remote-debugging に公開されている。今回はこちらを利用して実際に Azure Websites 上の Java アプリをリモートデバッグする。上記のソースコードを一読すると理解できると思うが、リモートデバッグ自体は既存の JDWP‐Java Debug Wire Protocol を利用しているので、こちらを理解している人であればとっかかりはあまり難しくないだろう。

リモートデバッグを試す

以下がリモートデバッグを試すまでの全体の流れになる。初回の疎通を通すまでは以下を参考にした方が楽にできるだろう。

  1. Websites を作成して「構成」タブから WebSocket を有効化する(おすすめはギャラリーからの Tomcat 7.x 作成
  2. Web.config に追記を行う
  3. 自作アプリの配置
  4. https://github.com/Azure/azure-websites-java-remote-debugging をダウンロードして DebugSession.bat の実行
  5. ブラウザから Azure Websites の自作アプリにアクセス

まず、新規に Websites を作成するが、こちらは 無料 モードでも 標準 モードでも問題ない。次に編集する Web.config があらかじめ配置されるギャラリーから「Apache Tomcat 7」がお勧めだ。
f:id:waritohutsu:20150125075205p:plain:w400
Websites 作成後、以下を参考に構成タブから WebSocket を有効化する。
f:id:waritohutsu:20150125075249p:plain

次に、kudu( https://<サイト名>.scm.azurewebsites.net/)にアクセスして D:\home\site\wwwroot\web.config を以下の様に編集する。デバッグオプションが追加していることが確認できるだろう。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="httpPlatformHandler" path="*" verb="*" 
                 modules="httpPlatformHandler" resourceType="Unspecified" />
        </handlers>
        <httpPlatform processPath="d:\home\site\wwwroot\bin\apache-tomcat-7.0.52\bin\startup.bat">
            <environmentVariables>
                <environmentVariable name="CATALINA_OPTS" value="-Dport.http=%HTTP_PLATFORM_PORT%" />
                <environmentVariable name="CATALINA_HOME" value="d:\home\site\wwwroot\bin\apache-tomcat-7.0.52" />                
                <environmentVariable name="JAVA_OPTS" value="-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=127.0.0.1:%HTTP_PLATFORM_DEBUG_PORT%" />
            </environmentVariables>
        </httpPlatform>
    </system.webServer>
</configuration>

更に、自作アプリを Websites 上に配置する。Eclipse から新規プロジェクト作成を選択し、Dynamic Web Project を選択して以下の様に index.jsp を配置する。
f:id:waritohutsu:20150125075109p:plain

上記でも紹介した Kudu の Debug console を利用して D:\home\site\wwwroot\bin\apache-tomcat-7.0.52\webapps\ROOT 以下のバックアップを取得したうえで作成した Java アプリを配置する。

次にリモートデバッグ用のツールを実行する。azure-websites-java-remote-debugging から取得したファイルの bin\DebugSession.bat を以下の実行例に沿って実行する。

>DebugSession.bat -p 8000 -s <sitename>.scm.azurewebsites.net -u <username> -w <password> -t
1 25, 2015 7:57:37 午前 org.azure.waws.DebugSession startSession
情報: Waiting for debugger to connect on 8000 ...

ここでの注意として、username には sitename\username を指定してはいけない点だ(例:normalian)。

Eclipse から [Debug As]-[Debug Configurations..] を選択し、以下の実行例に沿ってアプリケーションをデバッグ実行する。
f:id:waritohutsu:20150125075929p:plain

最後にブラウザからサイトにアクセスすると、以下の様に Eclipse 上からリモートデバッグが可能となる。
f:id:waritohutsu:20150125080600p:plain

最後に注意点として、Azure Websites を無料モードで利用している場合にCPU使用制限に引っかかってインスタンスが再起動される場合があるので、長時間放置する場合には WebSocket のコネクションが切れている場合があるので注意が必要だ。

Azure Websites で Tomcat や Jetty を運用する場合の注意点

Websites は Java にも対応しており、工夫次第では Java EE アプリも稼働させることのできることができることは本ブログで紹介済みだ。今回は Websites で Java アプリケーションを運用する際の注意を記載する(というよりは httpPlatformHandler を使ってるアプリは全部な気もするが)。

まず、Websites には 無料, 共有, 基本, 標準 と呼ばれる動作モードがあるが、この際に無料を使う場合にいくつか制限が存在している。Windows Azure Web サイトのスケール アップとスケール アウト に記載があるが、特に注意すべきは以下の記載だ。

無料モードは、他の無料モードや共有モードのサイトと同じコンピューティング リソース
で実行されます。また、一定のクォータ期間のサイト (およびサブスクリプション内の他
の無料サイト) の CPU 使用時間が制限されています。使用時間が制限に達した場合、その
サイトおよびサブスクリプション内にある他の無料モードのサイトで、次のクォータ期間
までコンテンツおよびデータのサービスが停止されます。また、無料モードではサイトが
クライアントへサービスを提供する際のデータ量 (データ送信) の制限があります

上記の記載は「無料で使ってしばらく運用してる場合、ほっとくと Tomcat や Jetty のプロセス落とすから気を付けて」といっている。
実際、数時間放置して TomcatEE 等をデプロイした無料の Azure Websites にアクセスすると、以下の様にレスポンスが帰ってこずにエラーとなる(2回目、3回目のアクセスは再度プロセスが起動しなおされているので瞬時にレスポンスが来る)。
f:id:waritohutsu:20150122212936p:plain:w500

こちらを回避する方法はいたってシンプルで、Websites の「常時接続」機能を利用すればよい。Azure Websites でバックグラウンド タスクを実行して Web ジョブを使用する方法 に以下の記載がある。

[WACOM.NOTE] 連続的に実行するタスクについては、Web サイトの [構成] ページで 
[常時接続] を有効にすることをお勧めします。[常時接続] は [基本] と [標準] の
モードで使用できる機能であり、この機能を有効にすると、アイドル状態がしばらく
続いても Web サイトがアンロードされなくなります。Web サイトが常に読み込まれ
ていれば、連続的に実行するタスクをより高い信頼性で実行できます。

残念ながら「無料」モードでは利用できないが、「スケール」タブから[基本]か[標準]を選択して保存した後、「構成」タブから以下を参考に 常時接続 を選択する。
f:id:waritohutsu:20150122213049p:plain

実際に「無料」モードと「標準&常時接続」モードの運用結果を比べてみた。
f:id:waritohutsu:20150122213147p:plain

上記で分かる通り、無料側では catalina.xxxxxxxx.log が大量に作成されている(もちろん標準&常時接続側にも日次リクエストは投げている)。中身は Tomcat の起動ログであり、CPU 使用時間の制限でサービスが停止された後、リクエストが来た際に Tomcat が再起動したものが出力されている。

Web サイト上の JavaEE アプリからVPN経由で Oracle DB を参照する!

最近記載した以下の記事により、Web サイト上で Java EE のアプリケーションが稼働することは理解できたと思う。

しかし、これだけでは肝心のデータベースに接続する方法を記載していない。そのため、今回は仮想マシン上に Oracle DB を作成して Web サイトからデータを参照する方法を紹介する。

大枠の流れは以下になる。

  1. 仮想ネットワークとゲートウェイを作成する
  2. Azure 上に仮想マシンOracle DB を作成してセットアップする
  3. クライアント端末の NetBeansJavaEE のアプリケーションを作成する
  4. Web サイトと仮想ネットワークを VPN で接続する
  5. Web サイトを作成し、Tomcat EE をデプロイする

上記で作成されるアプリケーションの構成は以下になる。
f:id:waritohutsu:20150111034103p:plain

今回は上記の構成を目指した JavaEE アプリケーションを作成する。

仮想ネットワークとゲートウェイを作成する

まずは管理ポータルから仮想ネットワークを新規し、チュートリアル: サイト間クロスプレミス接続用の仮想ネットワークの作成を参考に「ゲートウェイの起動」までを参考にゲートウェイを作成する。以下のような画面になればOKだ。
f:id:waritohutsu:20150111034401p:plain

Azure 上に仮想マシンOracle DB を作成してセットアップする

仮想ネットワークとゲートウェイを作成した後、仮想ネットワーク上に配置する形で Oracle DB の仮想マシンインスタンスを作成する。このあたりについては私がちまちま情報を書くよりは Creating an Oracle Database 12c virtual machine in Azure を参照していただいた方がいいだろう。
こちらで注意が必要な点は三つだ。その一は Oracle Listener を立ち上げること(デフォルトだと立ち上がっていなかった)だ。こちらは以下を参考に管理ツールを弄れば簡単だろう。
f:id:waritohutsu:20150111034155p:plain:w400

その二は、Windows ファイヤウォールのポートを Oracle DB 向けにあけること(今回はオフにしたが、本番環境では 1521 ポートのみ有効にする)。
f:id:waritohutsu:20150111034222p:plain:w400

その三は、NetBeans 上でアプリケーションを開発するために Oracle DB のエンドポイントで 1521 をオープンにする。
f:id:waritohutsu:20150111034308p:plain:w400

クライアント端末の NetBeansJavaEE のアプリケーションを作成する

次に JavaEEのアプリケーションを作成する。まずは NetBeans 8.0.1 で JavaEE7 な CDI を利用する際の注意点 を参考にして JavaEE のアプリケーションを作成し、更に JavaEE の実行環境を Microsoft Azure の Web サイト上で稼働させる を参考に NetBeans に TomcatEE を導入する。

以上の下準備が済んだ後、NetBeasn 以下の画面より作成した JavaeEE アプリケーションから [新規接続] を選択する。
f:id:waritohutsu:20150111034957p:plain

ここからは以下の新規接続ウィザードが起動するので、Oracle Thin を選んで[次 >]を押下するが、ojdbc6.jar or ojdbc7.jar が存在しない場合は別途取得して[追加]ボタンからドライバファイルを追加する。
f:id:waritohutsu:20150111035302p:plain:w300f:id:waritohutsu:20150111035306p:plain:w300

また、Microsoft Azure 上に配置された Oracle DB への接続文字列を以下を参考に記載する。この際、Oracle の SID は「Azure 上に仮想マシンOracle DB を作成してセットアップする」にて自身で作成したものになるはずなのでご留意頂きたい。
f:id:waritohutsu:20150111035349p:plain:w400

最後にスキーマを選択するが、今回は伝統のある SCOTT スキーマのデータを参照したいので以下を参考に接続文字列の終了を確認する。
f:id:waritohutsu:20150111035400p:plain:w400

また、以下の様に ojdbc7.jar を WEB-INF/lib 以下の配置して、アプリケーションが Oracle DB に接続する準備をすること。
f:id:waritohutsu:20150111035542p:plain

次に、以下の画面から [新規]-[その他]メニューを選択し、[持続性]-[データベースからのエンティティ・クラス]を選択する。
f:id:waritohutsu:20150111035456p:plain:w300f:id:waritohutsu:20150111035500p:plain:w300

ここから以下のウィザードが表示され、SCOTT スキーマのテーブルを選択できるので、DEPT と EMP を療法選択する。
f:id:waritohutsu:20150111035632p:plain:w400

ウィザードから XHTMLJava クラスが全て自動生成されるので、この時点で一度ローカルで TomcatEE を起動して疎通を確認するといいだろう。

Web サイトと仮想ネットワークを VPN で接続する

こちらは新管理ポータルである https://portal.azure.com/ にアクセスし、以下の画面を参考に仮想ネットワークと接続する(この際、Web サイトが無料の構成では設定できない点に注意すること)。
f:id:waritohutsu:20150111035921p:plain

この際、仮想ネットワークのゲートウェイ作成が完了していないと以下のようなエラーメッセージがでるので注意してほしい。
f:id:waritohutsu:20150111040216p:plain

Web サイトを作成し、Tomcat EE をデプロイする

こちらについては JavaEE の実行環境を Microsoft Azure の Web サイト上で稼働させる を参照して TomcatEE をデプロイする。デプロイ前に、META-INF/persistence.xml を編集し、接続先を以下の様に仮想マシン上のローカルIPとする。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="com.mycompany_MavenWebApp_war_1.0-SNAPSHOTPU" transaction-type="JTA">
        <jta-data-source>exampledb</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="javax.persistence.jdbc.driver"   value="oracle.jdbc.OracleDriver"/>
            <property name="javax.persistence.jdbc.url"      value="jdbc\:oracle\:thin\:@10.0.1.4\:1521\:example" />
            <!-- 
            <property name="javax.persistence.jdbc.url"      value="jdbc\:oracle\:thin\:@winoracledb12c.cloudapp.net\:1521\:example" />
            -->
            <property name="javax.persistence.jdbc.user"     value="SCOTT" />
            <property name="javax.persistence.jdbc.password" value="<password>" />
        </properties>
    </persistence-unit>
</persistence>

以下を実施した後、NetBeans で作成した war ファイルを Web サイト上の TomcatEE 上にデプロイしよう。正しくアプリケーションが動作していれば以下のようになる。
f:id:waritohutsu:20150111040600p:plain

Microsoft Azure の Web サイトで CDI と JSF を動かしてみる

JavaEE の実行環境を Microsoft Azure の Web サイト上で稼働させる で TomcatEE が Web サイト上で動作することを紹介できたが、今回は実際に JSFCDI を利用したアプリケーションが動くかを検証する。前回の記事でも記載しているが、TomcatEE における JavaEE の実装は以下になる。

上記の内容は アノテーションで大混乱した JavaEE6 頃の実装だが、めげずにアプリを作成したいと思う。また、今回利用したアプリは https://github.com/normalian/MavenWebApp に配置しているので、別途参照してほしい。

アプリケーションの概要

今回作成したアプリケーションは、以下の様に JSF でのデータバインディングを行い、セッションにデータを格納して次の画面で値を表示する簡単な内容だ。
f:id:waritohutsu:20150104152517p:plain

コードの詳細は GitHub を参照いただくとして、トップ画面の XHTML, Java コードを紹介する。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            Hello from Facelets &amp; Please input message
            <h:inputText value="#{viewDto.message}" /> <br />
            <h:commandButton value="submit" action="#{indexAction.doAction}" />
        </h:form>
    </h:body>
</html>
package com.mycompany.mavenwebapp.common;

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@SessionScoped
@Named
public class ViewDto implements Serializable {

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
package com.mycompany.mavenwebapp.action;

import com.mycompany.mavenwebapp.common.ViewDto;
import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@RequestScoped
public class IndexAction implements Serializable {

    @Inject
    ViewDto viewDto;

    public String doAction() {
        System.out.println("@@@@@@@@ message = " + viewDto.getMessage());
        return "show.xhtml";
    }
}

ご覧のとおり、JSFCDI を利用した簡単なアプリケーションだ。ローカルの TomcatEE でも動作を確認後、Kudu を利用して D:\home\site\wwwroot\bin\apache-tomee-plus-1.7.1\webapps 以下に war ファイルを配置する。war 配置後は冒頭で記載した様に JSFCDI が正しく動作していることが確認できる。

異常で、Jetty や Tomcat しか動かないと思われた Web サイトでも JavaEE の機能が利用できることが紹介できた。是非皆様もいろんなハックを Web サイト上でやってみよう!

JavaEE の実行環境を Microsoft Azure の Web サイト上で稼働させる

新年初ポストは Web サイトと JavaEE について言及させていただきたい。良い子の諸君は JavaEE といえば GlassFish, WebSphere, JBoss AS, WebLogic (それぞれ正式名称が違うのはご容赦頂きたい)を想像すると思うが、Java EE6 から導入されたWeb Profile の実装である TomcatEE を Web サイト上で稼働させることで JavaEE の機能を利用することが可能となることはご存知だと思う。
今回は Tomcat EE を Web サイト上で稼働させてみるが、2015年1月時点での最新版である TomcatEE 1.7.1 の実装は以下となっているので、おおよそ JavaEE6 の機能が稼働すると考えてよいだろう。

Web サイト上での Tomcat EE の稼働

Tomcat 自体は Web サイトにバンドルされているが、まずは Web サイトのギャラリーから Tomcat を選択して Web サイトを作成する(こちらで web.config が作成されるため、TomcatEE の設定を実施しやすくなる)。
f:id:waritohutsu:20150104010257p:plain
次に、Kudu に接続して以下のコマンドを実行して Web サイト上に Tomcat EE を展開する( TomcatEE の URL はバージョン次第で変えること )。

D:\home\site\wwwroot>dir
 Volume in drive D is Windows
 Volume Serial Number is 746D-E3BB

 Directory of D:\home\site\wwwroot

01/02/2015  04:10 PM    <DIR>          .
01/02/2015  04:10 PM    <DIR>          ..
01/02/2015  04:12 PM    <DIR>          bin
01/02/2015  04:13 PM             4,828 web.config
               1 File(s)          4,828 bytes
               3 Dir(s)     767,229,952 bytes free

D:\home\site\wwwroot>cd bin

D:\home\site\wwwroot\bin>curl -O http://ftp.riken.jp/net/apache/tomee/tomee-1.7.1/apache-tomee-1.7.1-plus.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 41.4M  100 41.4M    0     0  11.0M      0  0:00:03  0:00:03 --:--:-- 11.1M

D:\home\site\wwwroot\bin>unzip apache-tomee-1.7.1-plus.zip 

次に、D:\home\site\wwwroot\web.config を以下のように編集する。CATALINA_HOME を編集している点に注目してほしい。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="httpPlatformHandler" path="*" verb="*" 
                 modules="httpPlatformHandler" resourceType="Unspecified" />
        </handlers>
        <httpPlatform processPath="dd:\home\site\wwwroot\bin\apache-tomee-plus-1.7.1\bin\startup.bat">
            <environmentVariables>
                <environmentVariable name="CATALINA_OPTS" value="-Dport.http=%HTTP_PLATFORM_PORT%" />
                <environmentVariable name="CATALINA_HOME" value="d:\home\site\wwwroot\bin\apache-tomee-plus-1.7.1" />                
                <environmentVariable name="JAVA_OPTS" 	  value="-Djava.net.preferIPv4Stack=true" />
            </environmentVariables>
        </httpPlatform>
    </system.webServer>
</configuration>

更に、D:\home\site\wwwroot\bin\apache-tomee-plus-1.7.1\conf\server.xml を以下のように編集する(抜粋しているので注意してほしい)。Connector タグの port 属性を 8080 から #{port.http} に編集している点に注意してほしい。

        <Connector port="${port.http}" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
        <!-- A "Connector" using the shared thread pool-->

ここで Azure の管理ポータルより当該 Web サイトを再起動する。再起動後、Web サイトにアクセスすることで TomcatEE となっていることが確認できる。
f:id:waritohutsu:20150104010332p:plain

NetBeans 8.0.1 で JavaEE7 な CDI を利用する際の注意点

NetBeansJavaEE 開発にとってなくてはならない優秀な IDE だが、CDI を利用する場合に注意点が存在する。JavaEE6 以降ではすっかり主軸となった CDI についての注意点を紹介する。

新規プロジェクト作成時の注意点

新規プロジェクトから以下の「Webアプリケーション」を選んだ場合、CDI のライブラリに参照が張られない点だ。
f:id:waritohutsu:20141222115117p:plain

cdi-api.jar への参照が存在しないため、CDI を管理コンテナとして明示する以下のアノテーションが利用できない。

  • @javax.enterprise.context.RequestScoped
  • @javax.enterprise.context.SessionScoped
  • @javax.enterprise.context.ApplicationScoped

一方で、以下の JSF 2.0 の管理コンテナを利用するアノテーションは指定できてしまうので注意が必要だ(以下のアノテーションを利用しても、CDI の @Inject ではインスタンスを利用できない)。

  • @javax.faces.bean.RequestScoped
  • @javax.faces.bean.SessionScoped
  • @javax.faces.bean.ApplicationScoped

この辺りの情報は 大混乱に陥っているJavaEE 6のアノテーションに関する使い分けについて が詳しい。

どう解決したらいいの?

以下の様に新規プロジェクトから Maven の Web アプリケーションを選択し、pom.xml を記載して参照を解決すればよい。
f:id:waritohutsu:20141222115127p:plain

pom.xml は以下の様に記載する。CDI のバージョンが 1.2 よりも新しくなったら別途追記してほしい。

<?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>com.mycompany</groupId>
    <artifactId>MavenWebApp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>MavenWebApp</name>

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

/// 中略

Java API for JSON Processing(JSR 353) を利用してASP.NET と疎通してみる

今回は ASP.NET Calendar 2014 の14日目である。今回は ASP.NETJava EE 系の連携方法についての紹介を記載する。昨今の REST API ブームに乗っ取り、JSON 形式でデータのやり取りをすることが非常に多い。.NET Framework 側では Json.NET が有名だが、Java 側も JSON を処理する API が提供されたので、今回は .NET Framework と Java EE の連携を実装する。

クライアント .NET Framework, サーバ側 Java EE

(記載中)

クライアント Java EE, サーバ側 .NET Framework

(記載中)

まとめ

(記載中)