2013年11月24日日曜日

Undertow Handler Authors Guide 和訳

このエントリは WildFly(旧名 JBoss AS)の Web サブシステムとしても利用される Undertow の以下設計ドキュメントの和訳です。実際に存在するクラス名も出てきますので、ソースコードもお手元にあるとよいかと思います。

Undertow Handler Authors Guide

原本は https://github.com/undertow-io/undertow-io-site の eda33a 時点のものを利用しています。更新が確認され次第、随時反映します。

なお、自分が理解が足りていないところが多いため、変な日本語になっています。。ちょくちょく直していく予定です。

イントロダクション


このガイドでは、Undertow のネイティブハンドラの作成方法の概要を説明します。HttpServerExchange オブジェクトの全ての API に言及している訳ではありません。API の多くは自明であったり、javadoc で理解可能なものです。そのかわり、このガイドでは Undertow のハンドラを記述する際に必要な概念の説明を中心に行います。

シンプルな例から始めましょう。
public class HelloWorldServer {

    public static void main(final String[] args) {
        Undertow server = Undertow.builder()                                                                                //Undertow ビルダ
                .addListener(8080, "localhost")                                                                                //リスナバインディング
                .setHandler(new HttpHandler() {                                                                                //デフォルトハンドラ
                    @Override
                    public void handleRequest(final HttpServerExchange exchange) throws Exception {
                        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");  //レスポンスヘッダ
                        exchange.getResponseSender().send("Hello World");                                        //レスポンスセンダ
                    }
                }).build();
        server.start();
    }

}
大部分は自明です。

Undertow ビルダ


この API により、Undertow の設定と起動をすぐに行うことができます。この API は組込みや試験環境での用途を想定しています。現時点で、この API は変更される可能性があります。

リスナバインディング


次の行では Undertow が localhost の 8080 ポートにバインドするようにしています。

デフォルトハンドラ


このハンドラは Undertow に登録されたパスにどれもマッチしない URL に対して割り当てられます。このケースでは他にハンドラを登録していないので、常にこのハンドラが実行されます。

レスポンスヘッダ


自明ですが、これは Content-Type ヘッダに値を設定しています。1つ注意すべきなのは、Undertow ではヘッダのマップのキー値として String 型ではなく、ケースインセンティブな文字列である io.undertow.util.HttpString を利用します。io.undertow.utils.Headers クラスは一般的なヘッダーをあらかじめ定数で定義しています。

レスポンスセンダ


Undertow のセンダ API の役割はレスポンスを送ることのみです。センダの詳細は後ほど述べますが、このケースでは完了に対応するコールバックが指定されていないので、センダは、与えられた文字列が完全なレスポンスであると認識します。そして Content-Length ヘッダの設定を行い、レスポンス処理を完了します。

今後のコード例ではハンドラ自体に焦点を当て、サーバのセットアップ部分は割愛します。

リクエストのライフサイクル


(このことはリクエストライフサイクルのドキュメントでも 取り上げています。)

クライアントがサーバへ接続する際、Undertow は io.undertow.server.HttpServerConncection を生成します。クライアントがリクエストを送ると、リクエストは Undertow のパーサによってパースされ、その結果の io.undertow.server.HttpServerExchange がルートハンドラへ渡されます。ルートハンドラの処理が完了すると、以下の4つのいずれかの状態となります。

Exchange がすでに完了している


リクエスト及びレスポンスチャンネルの完全に読込み/書込み終わっている場合、Exchange は完了したとみなされます。(GET や HEAD などで) No Content が返されるようなリクエストに対しては、リクエスト側は自動的に完全に読込み終わったと見なします。ハンドラが完全なレスポンスを書込み、クローズし、レスポンスチャネルをフラッシュすると読込み側は完了したとみなされます。Exchange がすでに完全な状態となっているならば、Exchange は完了したとして何もしません。

ルートハンドラが Exchange の完了なしに正常に返る


このケースでは Exchange は HttpServerExchange.endExchange() が呼ばれることで完了します。endExchange() のセマンティクスについては後述します。

ルートハンドラが例外を伴って返る


このケースではレスポンスコードとして 500 が設定され、Exchange はHttpServerExchange.endExchange() を使って終了します。

ルートハンドラが HttpServerExchange.dispatch() が呼ばれた後、または非同期 IO が開始された後に返る


このケースではディスパッチされるタスクがディスパッチエグゼキュータへと渡されるか、非同期 IO がリクエストまたはレスポンスチャネル上で開始していれば、それから処理が始まります。このケースでは Exchange は完了せず、いつ処理が終わって Exchange が完了するかは、非同期タスク次第です。

もっとも一般的な HttpServerExchange.dispatch() の利用用途は、ブロッキング処理の行えない IO スレッドから、ブロッキング処理の行えるワーカースレッドへ処理を委譲することです。この例は典型的には以下のようになります。

ワーカースレッドへの処理の委譲
public void handleRequest(final HttpServerExchange exchange) throws Exception {
    if (exchange.isInIoThread()) {
      exchange.dispatch(this);
      return;
    }
    // ハンドラのコード
}
Exchange は実際にはコールスタックが返るまでディスパッチされないため、ある Exchange 中において同時に 2 つ委譲のスレッドが動作することはないと考えてよいでしょう。この Exchange はスレッドセーフでないですが、複数のスレッドが同時に Exchange を変更しようとしない限り、複数スレッド間で共有される可能性があります。また、1つ目と2つ目のスレッドアクセスの間に、スレッドプールディスパッチのようなことが起こりえます。

Exchange の完了


上で説明した通り、Exchange はリクエストおよびレスポンスチャネルのクローズとフラッシュすると完了したとみなされます。

Exchange の完了には2種類あり、リクエストチャネルの読込みが完了し、レスポンスチャネルで shutdownWrites() が呼ばれ、レスポンス内容がフラッシュされたときか、HttpServerExchange.endExchange() が呼ばれた時です。endExchange() が呼ばれた時、Undertow はコンテンツが生成されたかどうかチェックします。生成されていればリクエストチャネルを開放し、レスポンスチャネルのクローズとフラッシュを行います。コンテンツが生成されていない場合、Exchange にデフォルトのレスポンスリスナが登録されていれば、Undertow はレスポンスリスナにデフォルトのレスポンスを設定します。こうしてデフォルトのエラーページを返す機構を提供します。

Undertow のバッファプール


Undertow は NIO をベースとしているので、バッファリングが必要な場合は java.nio.ByteBuffer が使われます。これらのバッファは要求ごとに割り当てると性能に重大な影響を与えるため、プールされます。このバッファプールは HttpServerConnection.getBufferPool() を実行することで取得できます。

プールされたバッファは利用後はガベージコレクトの対象にならないため、開放されなくてはなりません。プール中のバッファのサイズはサーバが作成された際に設定されます。経験則として、最大限のパフォーマンスを出すサイズは 16kb です(これは Linux のデフォルトのソケットバッファサイズと一致します)。

ノンブロッキング IO


デフォルトでは Undertow はノンブロッキングの XNIO チャネルを利用し、リクエストは最初 XNIO の IO スレッド上で実行されます。これらのチャネルは受信データを送るために直接利用されます。これらのチャネルはかなり低レベルですが、Undertow はよい扱いやすくするために抽象化したものを提供します。

ノンブロッキング IO を利用したレスポンスを送信するもっとも簡単な方法は、上述したセンダ API を利用することです。センダ API は byte や String 両方に対応した send() メソッドを様々な用途にあった形で提供しています。メソッドの中には、送信が完了したらコールバック処理を実行するものや、コールバックをしない代わりに送信が完了した際に Exchange を終了させるものもあります。

センダ API はキューイングをサポートしないことに注意してください。send() をコールバックが通知されるまで呼ぶことはおそらくできません。

コールバックを取らない send() メソッドは、Content-Length ヘッダが自動的に設定されます。そうでなければ chunked エンコーディングを避けるために、自分で Content-Length ヘッダを設定する必要があります。

センダ API はまた、ブロッキング IO をサポートします。Exchange が HttpServerExchange.startBlocking() の実行によりブロッキングモードになった場合、センダは Exchange のアウトプットストリームを利用してデータを送信します。

ブロッキング IO


Undertow はブロッキング IO もサポートしています。XNIO のワーカスレッド中ではブロキング IO を使えないため、リード/ライトする前にリクエストをワーカスレッドプールへディスパッチする必要があります。

ワーカスレッドをディスパッチするコードは、前述のとおりです。

ブロッキング IO を利用するために HttpServerExchange.startBlocking() を実行します。このメソッドは 2 つあり、1 つは引数を取らず Undertow のデフォルトのストリーム実装を利用します。もう 1 つの HttpServerExchange.startBlocking(BlockingHttpServerExchange blockingExchange) では、利用中のストリームをカスタマイズして使うことができます。例えば サーブレット実装では Undertow のデフォルトストリームの代わりに Servlet(Input/Output)Stream を使うためにこの 2つ目のメソッドを利用しています。

ブロッキングモード Exchange が完了すると HttpServerExchnage.getInputStream() と HttpServerExchange.getOutputStream() を実行することができ、通常通りデータを書き込むことができます。上で述べた sender API も利用できますが、この場合 sender の実装はブロッキング IO が利用されます。

デフォルトで Undertow はバッファリングストリームを利用し、バッファはバッファプールから取り出されます。レスポンスがバッファに適合するほど十分小さければ、Content-Length ヘッダが自動的に設定されます。

ヘッダ


リクエストとレスポンスヘッダは HttpServerExchange.getRequestHeaders() と HttpServerExchange.getResponseHeaders() を介してアクセスできます。これらのメソッドは最適化sれたマップ実装である HeaderMap を返します。

ヘッダは最初のデータがチャネルへ書き込まれたときに HTTP レスポンスヘッダに書きだされます(バッファリングされていた場合、最初にデータが書き込まれた時刻とは一致しない可能性があります)。

ヘッダへの書き込みを矯正したい場合は、レスポンスチャネルまたはストリームで flush() メソッドを利用できます。

HTTP Upgrade


HTTP upgrade を実行するために HttpServerExchange.upgradeChannel(ExchangeComplietionListener upgradeComplitionListern) が利用できます。レスポンスコードは 101 に設定され、Exchange が完了するとリスナに通知されます。ハンドラは upgrade クライアントが期待するような適切なヘッダを設定することが可能です。


2013年11月10日日曜日

JJUG CCC 2013 Fall メモ

JJUG CCC 2013 Fall に参加しました。どのセッションも非常におもしろく、あっという間に1日が過ぎてしまいました。

WebSocket のハンズオンは社内システムに応用できそうなアーキテクチャ(WebSocket + JMS)なので、ぜひ WildFLy 上で動作するようにしてみたいと思います。

JVM コードリーディング入門は、大規模ソースコードのリーディングに普遍的に通用するテクニックを教えていただきました。めげずにいろいろと読んで行こうと思います。

Virt.x も気になるプロダクトです。まずは Acroquest さんのブログで入門したいと思います。

以下、メモをはりつけ(手抜きですみません)。発表スライドは公表されたら順次リンクしていきます。

参加セッションリスト



K-2 2013 エンタープライズ Java 最前線

GlassFish のロードマップ


  • 商用ライセンスサポートはバージョン 3.1.2.2 までで終了
  • バージョン 4 以降は OSS 版のみ提供
  • 今後 Oracle が提供する Java アプリケーションサーバは WLS のみ
  • 今後も Java EE の RI であるという GlassFIsh の位置づけは変わらない

Java EE 7 2013.6 リリース


  • EE 7 は EE 6 を拡張したもの。Web のトレンド(HTML5, WebSocket など)に対応したもの。
    • EE 6 は EoD の集大成と言えるリリースであった。
  • WebSocket の注目が高い(寺田さん調べ)
  • CDI + JTA で EJB をかなり置き換えられるようになった。
  • Bean Validation がいろいろなところで使えるようになった。
  • Concurancy Utility で、ユーザアプリケーション側でスレッドを起こすことが可能になった。
  • JAX-RS が Full Profile から Web Profile へ移った。

Project Avatar


  • JDK8_b103 以降で利用できる。 
  • 今年の Java One で OSS 化された旨が発表された。
  • Avatar を試してみたい場合、自力でセットアップするよりも、Avatar 公式サイトからダウンロードできる Avatar が同梱された GlassFish を使うのがおすすめ(どこにあるかわからない...)。 
  • Avatar は JS のエンジン(Nashorn)上で動作する。
    • Nashorn は JVM 上で動作する JS エンジンで、JDK8 の 1 プロジェクト。旧来の JS エンジンである Rhino より性能がよいらしい。 
      • 性能が良いのは、JDK8 における Invoke Dynamic 命令の恩恵らしい。 
  • Avatar で TSA を実現する場合。// TODO 寺田さんの絵がほしい。 
  • Avatar はデータバインディングに EL 式を使える。 
    • Avatar コンパイラでコンパイルする。 
  • Avatar でビルドしたアプリケーションは、GlassFish にそのままデプロイできる。 
  • 同じ AP サーバ上にほかの Java EE アプリケーションもデプロイされるので、Java <-> JS の相互呼び出しが可能。 
  • Avatar のサンプルアプリケーションは寺田さんのブログを参照。

Java EE 8 とその将来


  • まだまだ決まっていないことがたくさんあって、これからの状態
    • JSON バインディング、JCache は確実に入ってきそう。

R5-1 Java EE 7 WebSocket ハンズオン

// TODO WIldFLy で動かせるようにしたい!

  • 作成するアプリケーションは WebSocket による大規模リアルタイム情報配信
    • チャットとかだとバックエンドのサーバがあまり企業システムらしくないので、それらしいものを作る。
    • 利用テクノロジは WebSocket + JSF + JMS WebSocket
    • サーバはクラスタ構成にする。
    • JMS アプリケーションと WS アプリケーションは別のアプリケーションとして提供する。
  • 寺田さんは public フィールドはお好みでないようだ。
  • JSF のエッセンスは ManagedBean と EL 式。
  • Java EE 7 の WebSocket API は簡単に使えるように設計されている。
    • POJO
    • ポイントになるアノテーションは以下
      • @ServerEndpoint
      • @OnMessage
      • @OnOpen
      • @OnClose
      • etc.
    • Session#getOpenSessions で接続してきているすべてのクライアント情報を取得できる。 
  • GlassFish の JMS 実装は OpenMQ
  • JMS2.0 かんたん!
  • 途中で出てきた 4001 ってなに?


H-3 ユニットテスト改善ガイド


  • ユニットテストを組織に広めるためのヒントを紹介
  • (参考)渡辺さんのクラスメソッドのブログ記事
    • JUnit はあくまでテストするためのツールであり、「JUnit を使うこと」が目的ではない
    • ユニットテストを作るにはそれ相応のスキルが必要である
    • etc.
  • ユニットテストは適材適所であるべき
    • 全てやる派 vs 薄くやる派
  • テストは誰でもできる簡単なものではなく、トレーンングが必要
    • テスティングフレームワークの使い方やテスト手法を学ぶ
    • プロジェクトのコストとして扱わず、業務時間にトレーニングを実施する。
    • コーチができる人を探す。
  • テストが難しいコード、簡単なコードがある。いきなりすべてをやろうとせず、できるところからやる。
  • テストがしにくいAPI=使いにくいAPI。
    • テスト対象を直してはならないという勘違い。
    • 一度書いたものは変えたくないという抵抗感を減らす1つの方法は、テストファーストを行うこと。
  • CI を導入する前に、テスト文化を根付かせるのが先。
    • CI 導入にもノウハウが必要。一緒にテストも学ぶのは大変。
  • CI の効果
    • リグレッションをすぐに検知できる
    • 自動化が「見える」
      • モチベーションが上がる
    • 見える化のおかげで、管理者にも説明しやすい。
  • テストコード自体のメンテナンス・リファクタリングが必要。
    • テストは使い捨てでない
    • DRY をサボると確実にコピペ地獄になる。
    • 動かないテストは思い切って捨てるべき
    • テストは常にきれいにしておくこと。
      • ただし、整理しすぎるとかえって可読性が落ちることがあるので、あくまでテストとして読みやすいバランスを保つこと。
  • ユニットテストの効果を伝えずに押し付けても反発されるだけ。
    • メンバの手間を増やさない
    • 導入する目的を説明する
    • デバッガの代わりに紹介してみる
  • 上司の説得方法

R2-4 Javaアプリケーションサーバ構築・運用の勘所

ログ管理


  • トラブルシューティングの基本
    • GC ログ
      • 取っていないケースも多い。
      • 標準出力に出すのもあり
        • 普通の出力と混じってしまうのでは?
    • スレッドダンプ
      • ThreadLogic
        • WLS に特化した機能も含むものの、ほかの製品でも使える。
        • 侍のほうが直感的な UI だが、ThreadLogic は診断結果などが出
        • 大きなスレッドダンプも読み込み可能。
    • アクセスログ
      • JBoss/Tomcat はデフォルトで出るようになってほしい。
      • 性能劣化している時の切り分けとして、前段の Apache のレスポンスタイムと比べる。
    • CPU
      • ps auxwww -L プロセス単位でなく、スレッドごとのCPU使用率を知りたい。
      • コネクションプール不要論に対する反論
        • プールするのは性能だけでなく、リソースを制限することにも意味がある。

R5-5 JVMコードリーディング入門 ~JVMのOS抽象化レイヤーについて

対象のソースコード


  • jdk7u

読む前の準備


  • ビルドするかしないか
    • デバッグ実行しながら動作を調べるなら必要
    • 動かす前の調査としてコードを読むなら不要

JVM を読む基本的な方法


  • わからなくても全部をざっくり何週も読む
  • メモ・図解をする
    • わかったこともわからないこともメモしないと忘れてしまう。
  • 名言「理解とは真実との相対的な距離を縮める行為である。」
    • 仮設と懸賞を繰り返す。
  • 鳥の目と虫の目を交互に繰り返すことでわかることもある
  • ファイルサイズの大きい物を把握する
    • 重要 or ゴミの可能性大
  • 抽象度の高い名前を付けられたファイルを把握する
    • より重要度が高いファイルである可能性大
  • クラスの関係性を把握する
  • いろいろなクラスから継承されていたり、フレンド関数としてアクセスされてたり
  • C, C++ のレイヤを切り分ける
    • システムコールを行う層とそれを使う層
    • OS との境界
  • ざっくり読む
    • 読む部分と読み飛ばしても良い部分
      • assert -> 読む。なんらかの重要なチェックが行われている
      • non-PRODUCT -> 読み飛ばして OK。デバッグ情報など。
  • ソースコードのコメントをどう読むか
    • コード中のものはメンテされていない可能性もあるため、完全に信頼は置けない。
    • ヘッダファイルは基本的に読む。設計指針や専門用語の解説あり
    • ソース中でも以下のコメントは読む
      • 署名がついているもの
      • バグトラックの番号がついているもの。セキュリティホール対応だったりする。
      • 日付が書いてあるもの
    • JVM の抽象クラスの特性
    • メモリ周りのコードに億出てくる略語を押さえる
      • oop, RO, TLAB, BOT...
    • os <- 猫に見える

JVM の OS 抽象化レイヤ


  • memory <- 寝てる猫に見える
  • os.hpp
  • os.cpp
  • os:: を呼び出しているクラスは share/vm/memory にある
  • memory ディレクトリに含まれるクラスの継承関係を図示する。
  • allocation.hpp|cpp 中のクラスが大事そう。

R5-6 [BOF] Over the Node.js. An Introduction to Vert.x

Vert.x の概要


  • Vert.x は JVM 上で動くアプリケーションプラットフォーム。
  • ドキュメントが充実している(vertx.io)
  • Virt.x の作者 timfox は Red Hat で HornetQ とか関わっている。
  • 特徴
    • High Perf.
    • Distributed Event Bus
    • Polyglot
    • Module System
  • High Perf.
    • C10K問題。一般的に1つのスレッドあたり、256kb - 1mb 必要
    • EventLoop でノンブロッキング+非同期処理
      • EventLoop を止めてはいけない。
        • どうしてもブロックしたいときは、WorkerThread を利用する。
    • Java のスレッドを利用するので、デフォルトで CPU 数に応じたスケーリングが可能
      • node.js では、クラスタ機能を使わないとだめ。単体だと 1 CPU での動作になる。
  • Distributed Event Bus
    • JMS みたいな通信(P2P, Pub/Sub)
    • クラスタリングも可能
  • Polyglot
    • JVM 上で扱える様々な言語をサポート
    • Java JS Groovy JRuby Jython が公式でサポート
    • Scala Clojure PHP も開発中
  • Module System
    • node.js でいう npm のような機構
    • モジュールは Maven や Bintray に公開し、共有できる
    • モジュール間は Event Bus を介した疎結合
    • モジュールはいろいろな言語で実装されているが、Event Bus を介しているため、言語の差を意識しないで済む。

Vert.x による開発


  • JDK7 or later(must)
  • Project Template は、gradle を使うのがおすすめ。
  • Auto Reload
  • Remote Debug も可能
  • Node.js and the new web front-end
    • Backend は Virt.x

Vert.x の最新情報


  • Fat Jar(executable jar)
    • Virt.x Core を同梱しているので、実行に Virt.x のインストールが不要。
  • HA
    • HA Group を作る。HornetQ っぽい。
    • QUORUM スプリットブレイン対策
  • DNS / UDP Core API

Netty, Virt.x, Java EE アプリケーションサーバ

  • Netty, Virt.x, Java EE アプリケーションサーバの住み分けは?
    • Netty は低レイヤ向きのアプリケーション向け(ゲートウェイとか)
    • Virt.x は Netty より高レイヤかつ、M2M などのサービスに向いているのでは
      • あくまで LightWight を目指し、Java EE アプリケーションサーバの範囲を全て網羅するような作りにはならないように思える。

参考


R1-7 [BOF] Spring Frameworkの今(2013年版)


  • Spring は生きている。
    • ホストしている会が移り(Pivotal社)、どう扱われるかという意味で未来にはちょっと不安な部分もある。
  • spring.io にメインサイトが変更された。
    • 40 種類のサンプルを用意されている。
  • Spring Boot
    • 複雑化した Spring モジュールを簡単に扱えるようにする。
  • CDI(JSR-330)対応
  • SockJS 対応
    • レガシーブラウザでも利用できる WebSocket
  • STOMP に対応
  • Spring vs Java EE
    • Spring もどんどん JSR に対応していき、Java EE と差がなくなってきた。
    • JTA が使えるのでグローバルトランザクションもできる。
    • 外部 JMS との連携も可能。

その他


  • Tomcat 7.0.47 では JSR 標準の WebSocket API を制限付きで同梱している。
  • JSR356は低レイヤ過ぎる。なんらかのフレームワークが必要。

2013年11月9日土曜日

ブログアプリケーションを作ろう

@making さんのブログお手製であることに衝撃を受けて、自分でも作ってみたくなりました。

リポジトリは以下です。

https://github.com/emag/morecat

アプリケーション名は "MoreCat"

名前が無いと説明に不便(おれのブログアプリとか、あの例のやつだけどみたいになっちゃう)なので、MoreCat というアプリ名にしました。こちらから拝借しました。

以下、仕様を挙げていきます。

機能

ブログシステムというよりは、WordPress に近いもの


blogger や はてなダイアリーのように、開設者個々人のブログ環境を提供するのではなく、WordPress のように、MoreCat をインストールすると 1 つのブログ環境を構築するイメージです。WordPress のデータ構造が参考になるのかな。

デフォルトの記法は Markdown


なんだかんだ Markdown がいいですよね。凝った表とかが必要な場合は、生 HTML を書いてもらうか、Redmine みたいな textile を参考に Markdown を拡張する感じでしょうか。

管理クライアントは GUI と CUI をデフォルトで用意する


ブログエントリ投稿方法として、Web ブラウザによる GUI だけでなく、CUI も用意したいと思っています。イメージ的には blogger でいう GoogleCL とか blogger.vim です。more とか cat とかで読み進められるといいなあ。

アーキテクチャと実装

コンポーネントは3つ

  • morecat-backend
    • 全ての API を提供するサーバ。MoreCat のコア。
  • morecat-frontend
    • フロントエンド UI。
  • morecat-admin
    • 管理コンソール UI。

Backbone.js + Java EE(JAX-RS, CDI, JPA)


フロントエンドは Single Page Application(Backbone.js 、たぶん Brunch を利用) を提供し、バックエンド(サーバサイド)はすべて REST API(JAX-RS を利用) のみの提供とします。細かいライブラリは、作りながら必要に応じて採用していきます。アプリケーションサーバは WildFly です。

プラグイン機構


ブログの外観テーマや便利ツールなどは、外から差し替えできて、かつ、サーバの再起動不要だと嬉しいですね。後からこういうプラグイン機構を入れ込むのは難しい気がするので、最初から考えておきたいと思います。
なお、どうやって実現するのかは全然イメージできてません!! 参考になりそうな Java アプリケーションだと、Eclipse, IntelliJ IDEA, Jenkins とかでしょうか。Eclipse は OSGi ですよね。

データベースは好みのものが選べるようにする


といっても、RDMBS のみとなるかと思いますが。。ひとまず PostgreSQL, MySQL の2つで動作確認を行おうと思います。なるべく JPA で NativeQuery を使わないようにすれば大丈夫かなあ。開発用には WildFLy 同梱の H2 を利用します。

...

とりあえずここまで。仕様が変更されたら随時更新していきます。のんびり作っていきたいと思います。