[Java] 2017/03/21 JJUG ナイト・セミナー 参加メモ #jjug

2017/03/21に開催されたJJUG ナイト・セミナー 「Enterprise Java最新動向〜Java EE 8とMicroprofile〜」に参加した際のメモ書きです。
気が向いたら内容を整理するかも。

Java EE 8の最新状況について

Java EE 8は仕様はFIXしていないので注意

GlassFish5

  • Promoted Buildがリリースされた3/13
    • Java EE 8 CTS実施済み
    • Nightlyは限定したテストケースのみ

Schedule

  • Final: 2017/07

Spec Status

  • 大体は、Public Draftが出ている
  • MVC 1.0はdropされているのは周知の通り(コミュニティに移管)

各Specについて

JAX-RS 2.1

  • Reactive Client API
  • Server-Sent Events
  • Non-blocking I/O

歴史

  • 1.1: クライアントAPIが未定義のため、各JAX-RS実装の独自API、Apache HttpClient等が使われた
  • 2.0
    • クライアントAPI追加
    • RESTリソース(WebTarget)の生成が可能に
    • 非同期呼び出し(.async()をコールするだけ、コールバックオブジェクト(InvocationCallback)の登録も可能)
    • リアクティブプログラミング的な実装をする場合、InvocationCallbackがネストしてかなり気持ち悪い(callback hell)

2.1

  • SyncInvoker, AsyncInvoker(.async())に加えて、RxInvoker(.rx())が追加された。戻り値はCompletionStage
CompletionStage<Number> price = client.target(...);
CompletionStage<String> wheather = client.target(...);

price.thenCombine(wheather, (price, wheather) -> reserveIfAffordable(price, wheather));
// ^ priceの結果とwheatherの結果を受けて次の処理を行う。chain
// ^ TODO 後で調べる: CompletableFuture
  • Reactive API Pluggability
    • 3rd party Reactiv Frameworkを利用できる
    • RxJavaの場合、RxFlowable<Response> flowable = client.target(...).request().rx(RxFlowableInvoker.class).get();
      • .rx()の引数に、RxInvoker継承クラスを指定する

Server-Sent Events(SSE)

  • Jersey 2.8では先行して実装
  • サーバーからクライアントへの一方向通信のチャンネル確率
  • event, data, id, retry, comment
  • モダンブラウザサポート
  • WebSocketは専用のプロトコル(ws://)だが、Server-Sent EventsはHTTPベース
  • SseEvent, OutboundSseEvent(サーバサイド), InboundSseEvent(クライアントサイド)
    • SseEventSync(サーバサイド), SseEventSource(クライアントサイド)
    • 2017/02 SSE周りの仕様は変更されているので、最新の情報に注意(Jersey独自実装部分が変わっている

JSON-P 1.1

  • RFC 7159に対応(1.0はRFC 4627)
    • トップレベルにおける要素がObject,Arrayしか無かったが、RFC 7159では全部置ける
  • JSON Pointer
    • JSON中の特定の値を参照するための文字列の構文
    • /0/user/address
    • JsonPointer, JsonPointer#getValue
  • JSON Patch
    • JSONを部分的に変更するような演算
    • add/remove/replace/move/copy/test
    • パッチ自体もJSONで記述される
    • op(操作)とpathと(必要なら)値を指定するJSONで記述されたパッチを、別のJSONドキュメントに適用する
  • JSON Merge Patch
    • RFC 7386
    • Key-Value形式のパッチを渡すと、ReplaceなりAddなりをしてくれる(同一のキーがあればreplace, 無ければadd, Valueがnullならremove)
  • Patch Diff
    • JsonPatch#diff, JsonMergePatch#diff`
  • Stream API対応: JsonCollectors

JSON-B 1.0

  • XMLに対するJAX-Bに似たAPI
  • ClassとJSONのマッピング、マッピングのカスタマイズ
  • デフォルトであればAnnotation/Configは不要
  • @JsonbFooBarアノテーションで、カスタマイズ可能
    • Keyを変える
    • Nullを出す/出さない
    • 日付/数値のフォーマット
    • etc…
  • JAX-Bと同様に、Adaptersも使える
    • アノテーション使いたくなければこっち

Servlet 4.0

  • HTTP/2 サポート
    • Request/Response Multiplexing(ストリーム多重化)
    • Server Push
    • Upgrade From HTTP 1.1 (HTTP Upgrade)
      • ALPNはJava 9で対応予定
  • Server Push
    • PushBuilder

JSF 2.3

  • CDI統合
    • Legacy Managed Beansは非推奨に
    • CDIのManaged Bean対応
    • より多くのJSF成果物へのInject

CDI 2.0

  • Java EEコンテナの外部でCDI動作定義(Java SE上で動く)
  • ^ のために仕様の分割
    • Core, for Java Se, for Java EE
  • 非同期イベント
    • Producer側で.fireAsyncをたたく、Observer側は@ObserveAsync

Bean Validation 2.0

  • Java SE 8サポート
    • Date/Time APi
    • Optional
    • アノテーションの繰り返し
      • 従来はコレクションを使っていたが、同じアノテーションを併記できる(Java SE 8による
    • コレクション要素への制約適用
      • 型パラメータに対してアノテーションをつける
  • 組み込みアノテーションの追加
    • @NotEmpty
    • @NotBlank

Security API for Java EE

  • セキュリティ周りの標準化
  • Authentication Mechanism
    • アプリケーションがアクセス可能な認証機構
    • 従来: 各APサーバや3rd partyの実装を用いる
  • Identity Store
    • アプリケーションがアクセス可能なアイデンティティストアの標準化
  • Security Context
    • プラットフォーム・スコープのセキュリティ・コンテキストの標準化

wrap-up

  • 今まで欠けていた部分を補い、Java EE 9に向けてポータビリティの強化が図られている
    • Cloud Platformを見据えた対応

MicroProfile 背景と意義、そしてこれから

  • @kkzr https://www.slideshare.net/kenjikazumura/
  • MicroProfile.io
    • 複数ベンダーによるEnterprise Javaのアーキテクチャ
    • ゴールはStandardization

Java EEではだめなのか

マイクロサービスアーキテクチャ(MSA)

  • 疎結合なサービスの集合体
  • 意思決定とビジネスの速さを実現するための”手段”
    • フィードバックループ(いわゆるOODAループ)による進化

MSAレイヤーと構成技術

  • アプリケーション
    • サービス分割、ステートレス、API
  • アプリケーションサーバー
    • REST, 非同期, memory footprint
    • MicroProfileはこの辺
  • VM/コンテナ
    • docker, IaaS, サーバレス

Java EEのProfile

  • Full Profile / Web Profile
  • Java EEにProfileを追加できるのはOracleだけなので、ここにMicro Profileを追加するのはOracleの判断が必要

Java EEの状況

  • J2EE 1.2 ~ Java EE 7まで、リリースの間隔はだんだん延びている
  • Public Review から Final Releaseまで、結構時間がかかるが、Java EE 8はまだPublic Reviewに到達していない
  • 2016/03の段階で、主な仕様はEarly Draft Reviewか、そこに到達していない状態
  • GlassFishのissuesは、V4以降はcreated/resolvedは少なくなっている
    • マイクロサービス、クラウドの進歩は早いが、このGlassFishの開発状況でついて行けるのか?
    • “Java EEが悪い”のではなく、”JCPのプロセスが悪い”かもしれない(アジャイル的ではない

仕様が先か、実装が先か

  • 仕様を先に決めるアプローチ(JCPのアプローチ)
    • Pros: 公正な議論、複数実装による適切な競争(よーいドンで実装着手できる
    • Cons: 仕様策定に時間がかかる
  • 実装を先に作るアプローチ(Linux Kernel等のアプローチ
    • Pros: イノベーション向き(変化が早い
    • Cons: 誰がどこで仕様を決めるか不明

JCP vs OpenJDK

  • JDKの側面
    • Java SEのRI
      • JCP, JSRによる開発
    • JDKのOSS
      • openjdk.java.net, JEPによる開発
    • JCPから見ると、JSRで決まっていないJEPの仕様が(なし崩し的に)JSRになってしまう > 議論されない
  • MicroProfile
    • MicroProfileの仕様が(最終的に)Java EEの仕様になる(といいなぁ
    • OpenJDKに基づいて別のJava SE実装を作るのは難しく、競争が起きにくい
    • MicroProfileははじめから競争を起こす前提(マルチベンダによる開発)

MicroProfile #とは

  • 2016.06に設立
    • RedHat, IBM, Payara, LJC, SOUJava等
  • 2016.09 JavaOne でVersion1.0リリース
  • 2017.01 富士通が参加
  • 2017 2Q Ver1.1(plan)
  • 2017 3Q Ver1.2(plan)

  • APSベンダーがMicroProfileを提供 > 市場が評価 > [OK]JCPへ提案, [NG]フィードバックを反映

  • アジャイル的にOODAループを実践して、最終的にJCPへ提案する

MicroProfile 1.1

  • 1.0は、JAX-RS、CDI、JSON-P
  • 1.1は、2017/2Qリリース予定
    • Configuration API
    • Health Check API
    • JWT Token Definition
    • Fault Tolerance
      • stretch goal: できなければ次のリリースで

Configuration API

  • 設定の外だし
    • 別環境への移動など、設定変更でリビルドを不要にする
  • 設定の動的反映
    • Netflix/archaiusの考え方
    • 環境変更のたびにリデプロイを不要に
      • 接続先URLの変更など(DBが死んだから切り替える、とか)
  • 優先度付けされた複数の設定(ConfigSource)で構成
    1. システムプロパティ
    2. 環境変数
    3. 設定ファイル(META-INF/microprofile-config.properties)
  • Apache DeltaSpike由来のAPI
    • メソッドベース
    • アノテーションベース
      • @Inject @ConfigProperty ConfigValue<Integer>

Interoperable JWT RBAC

  • OpenID ConnectベースのRole Based Access Control
  • 認証/認可
  • まだ具体的な仕様は少ない
    • JSONのフォーマットはあるがAPIがまだ進んでいない
    • Priority高いはずだが・・・

Service Healthchecks

  • アプリケーションのヘルスチェックをするRESTエンドポイント仕様
  • Kubernetes health check互換
  • チェック対象のアプリケーション(Producer)で、Health Check Procedureを定義(複数可)
    • すべてのProcedureがUpならUpを返す
  • GET /health > 200 Up or 503 Down
    • Procedureの結果をJSONでまとめて返す
  • (たとえば)JAX-RSのリソースで、@Healthをつけて、HealthStatusを返す

Fault Tolerance

  • アプリケーションの実行論理と、実行時のエラーハンドリングの分離
  • RetryPolicy, Fallback, CircuitBreaker, BulkHead, Timeout
    • RetryPolicy: 条件(.retryOn)、間隔(.withDelay)、回数(.withMaxRetries)を指定
    • Fallback: RetryPolicyを指定して、リトライに失敗した際の処理(.withFallback)を指定する
    • CircuitBreaker: NetflixのHystrixインスパイア
      • closed: 正常稼働
        • 何度か失敗すると(10回中3回など)、open状態に遷移
      • open: リクエスト送信遮断
        • 一定時間後に(1分など)、half-open状態に遷移
      • half-open: リクエスト送信を再開
        • 指定回数成功したら(5回など)、closed状態に遷移
        • 指定回数失敗したら(5回など)、open状態に遷移
      • メソッドAPI、アノテーションAPI

BulkHead

  • 処理毎に個別のスレッドプールを使用することで、異常時の影響を極小化したい

Timeout

  • リクエスト先がハングした時など、タイムアウトを指定しておく

サマリー

  • MicroProfileは、フィードバックループによるマイクロサービスのオープンなイノベーションを実践
  • 実装(ベンダー)を選択可能
    • アプリケーションのポータビリティを担保
  • 最終的にはJCPで標準化を目指す
    • 既存のJavaコミュニティを分裂させるものではない
    • Javaの特徴の1つである”互換性”は損なわない

質疑

  • 実装は早くても、Java EE 8とMicroProfileが両方存在する状態(HTTP/2とSPDYのような)になり、きれいなループが実現できないのでは?
    • 確かに、MicroProfileの方向とJava EEの方向が違ってくる可能性はある。しかしMicroProfileのメンバーはJCPにも参画しているので、方向性を合わせるような動きがあるのではないか。
      ※危惧としては、確かにあるので、努力していく

Javaで(サーブレットコンテナ|EJBコンテナ|メッセージブローカー)を組み込む話

※この記事は丸太式 Advent Calendarの18日目です

Javaに組み込めるミドルウェアを調べてみました。
それぞれ解説リンクを掲載していますので、参考にご覧ください。

サーブレットコンテナ

EJBコンテナ

メッセージブローカー

Javaだといろんなミドルウェアがあるのが”当たり前”みたいな感じがして、本格的な入門にもハードルが高いのが現状だと思います。
特にJavaEEになると、日本語の書籍がほぼ無いのもあって業務で使わない限りなかなか勉強する機会が無いですね・・・

「ぼくがかんがえたさいきょうのアプリケーションフレームワーク2014.12」※実装は無いよ!

※この記事は丸太式 Advent Calendarの17日目です

前提

バックエンドはJavaで構築することが前提です。今Javaプログラマなので。

構成と妄想

クライアント <- JSON -> Web <- JMS -> AP <- JPA -> DB
  • それぞれのサーバはスケールアウト出来る物とします。
    そのためにはセッションはDBに格納する必要がありますね。
    今の段階ではXOOPS CubeのDBセッションみたいな管理方法をイメージしています。
  • あえて特定のプロダクトに依存しない書き方をしています。
    それぞれの実装は好きな物を組み合わせることが出来ます(EclipseLink or Hibernate, ActiveMQ or RabbitMQ, Tomcat or Jetty, …)。
    まあ、プロダクト間の差異を吸収するのはフレームワークの仕事ですしね。
  • 基本的にはAPIを通じてアプリケーションを利用することになります。
    そのため、クライアントがWebブラウザだろうがSwingアプリだろうがSWTアプリだろうが全く気にしません。
    ただし、Webサーバにプログラムと一緒にビューをデプロイするのはあまり好みではないです。
  • The Twelve-Factor Appの影響を大いに受けています。
    従ってWeb/APそれぞれのサーバに特別なミドルウェアはインストールしない想定です。
    Webは組み込みTomcatかJettyを使えば良いですし、ActiveMQならアプリケーションに埋め込めるのでメッセージブローカーをインストールする必要はありません。RabbitMQはどうなのかな?

まとめ

「なんていうか・・・すごく言葉にしづらいんだけど・・・・・・あんまりまとまっていませんね!
タイトルに「2014.12」って付けてしまったので、またそのうちやるかも。

[Sonatype NEXUS][メモ] 自前のMavenリポジトリを使って依存関係を管理できるようにする

※この投稿は、丸太式 Advent Calendar 2014の11日目です

概要

世の中に公開されているOSSのJavaライブラリは、大抵MavenやGradle等の構成管理ツールで管理できます。
しかし、自分で作ったライブラリや会社の都合で公開できないライブラリを使う場合、自分でJarファイルを追加したり、依存関係を管理しなければなりません。
Javaは1個のライブラリが大量の依存ライブラリを必要とすることもよくあるので、これは非常に面倒です。

そこで今回は、OSSのMavenリポジトリ実装である”Sonatype NEXUS OSS”にライブラリを登録する手順の1例を(かなりざっくりと)紹介します。

手順

  1. 追加したいライブラリのJarを(ダウンロード、自前ビルドなどの方法で)用意する
  2. それっぽいpom.xmlを作る
  3. Sonatype NEXUSのUIからデプロイ

※ソースが用意できる場合、pom.xmlを作ればビルド・デプロイをmvnコマンドでやれます。

Jarを用意する

バイナリのJarを調達します。ソースやJavadocのJarを追加で調達すればEclipseやNetbeansなどのIDEで便利になりますが、今回はとりあえずバイナリだけ登録します

pom.xmlを作る

追加したいライブラリのためのpom.xmlを作ります。
依存しているJarがMaven Central等でホスティングされていれば、その依存関係も記載します。

デプロイ

NEXUSにログインし、repositoriesを開きます。
NEXUSは標準で「3rd party」というリポジトリが用意されているので、これを選択します。
下側に出ている「Artifact Upload」タブからデプロイできます。

GAV Definitionで「From POM」を選択するとファイルアップロード用のフィールドが表示されるので、先ほど作ったpom.xmlをここで指定します。
「Select Artifact(s) to Upload」ボタンからアップロードするJarを選択して「Add Artifact」ボタンを押すと、その下のグリッドに表示されます。
pom.xmlとJarを選択・追加したら、「Upload Artifact(s)」ボタンをクリックすることで、アップロードが完了します。

デプロイした物の利用

デプロイした物を利用するには、pom.xmlにNEXUSのリポジトリを設定して参照できるようにします。
初期状態のNEXUSには{NEXUSのURL}/content/groups/public/というリポジトリが有り、これを指定すると色々と幸せになれる層ですよ。

#jjug_ccc #ccc_r16 JJUG CCC 2014 Fall 参加レポート / R1-6 Concurrent Mark-Sweep Garbage Collection 再入門

※この投稿は、丸太式 Advent Calendar 2014の9日目です

今日はJJUG CCC 2014 Fallの参加レポート3本目です。

概要

R1-6 Concurrent Mark-Sweep Garbage Collection 再入門
by 久保田 祐史さん (@sugarlife)

メモ

CMS GC

  • GC: 不要なメモリ領域を探し、解放して再利用可能とする
  • Parallel GC: アプリケーションを止めて動く。GC時間は短いが、応答しなくなる
  • Concurrent GC: アプリケーションと同時に動く
  • Concurrent Mark-Sweep GC: ゴミじゃない領域をMarkし、Markされていない領域をSweepして再利用可能にする
    Compactionしないので、メモリ空間が断片化する

HotSpot VMのCMS GC

  • Heap -> New Gen.(Eden, Survivor0, Survivor1), Old Gen.(Tenured)
  • Minor GC: New Gen.に対してParallel Copy GC: アプリケーションを止めて、メモリが断片化しないようにGC
  • Major GC: Old Gen.に対してCMS GC

  • Minor GC: Eden -> Survivor 0, Survivor 0 -> Survivor 1

  • Promotion : Survivor -> Tenured
  • Major GC: Old領域の占有率やHeap使用量増加速度によって発生する
  • CMS GCは安定していない。失敗してSTW:Stop The Worldを伴うFull GCが発生することがある

  • Full GC (with STW): 全領域がGC対象
    Promotion failed, Concurrent mark failed

GCログの読み方

  • タイムスタンプ: Java processのuptime (sec.)
    -XX:+PrintGCDateStampsで、読める時間表記で出力
  • Minor GC: ParNew GC前のNew領域サイズ->GC後のNew領域サイズ(総容量)
    かかった時間は後ろの方に出るtimes (real)を参照
  • Minor GC (promotion): PromoteされたサイズはNew領域の差分 – 全体の領域の差分

  • CMS GC: initial mark
    STWをかけて、ルートオブジェクトから直接たどれるオブジェクトをマーキング

  • concurrent mark
    アプリケーションを再開しつつ、initial markでマーキングされたオブジェクトからたどれる全オブジェクトをマーキング。
    処理中に生成・変更されたオブジェクトはDirty Cardにされる
  • cuncurrent preclean
    STWが発生するRemarkを短縮するため、concurrent mark中にDirty Cardのオブジェクトをマーキング
  • concurrent abortable preclean
    Minor GCによってEden使用量が2MBになるまで最大5秒待つ
  • Remark (Final mark)
    STWしてNew領域を全スキャンして、New領域からOld領域を参照しているものにmark
  • concurrent sweep
    未マークのオブジェクトを改修
  • concurrent reset
    次のCMS GCで使う関連マップをクリアして、initial markの処理にゴミを残さない

注意すべきパターン

  • Full GC: promotion failed: Minor GCでOld領域にPromoteできなかった場合に発生
    断片化を解消するためのFull GC

    • 短命オブジェクトはNew領域で改修するべき(断片化を防ぐ)
    • New領域のサイズを調整する
    • PromoteさせずにNew領域で粘る
    • 兆候: Minor GC後のOld領域より、次のMinor GCの前のOld領域が大きい->短命オブジェクトがOld領域に飛んでる
    • 兆候: Old > NewだがPromotion Failed: Newに大きいオブジェクトしか入っていない
  • Full GC: concurrent mode failure: CMS GC中にもう一度CMS GCが発生しようとした場合

    • CMS GCの改修が間に合っていないので、開始タイミングを早める
    • サーバのスペックをあげる
      • 単純にいメモリを増やすより、CPUスペックをあげるべき
  • GC locker: GCを止める機構。HotSpot初期化や、JNI API呼び出しの一部

  • GC locker: Trying a full collection because scavenge failed
    • GCが止まっているのでNew領域にはいらずOLD領域に割り当て
    • 深刻な断片化、Promote失敗
  • 対策
    • GC Lockerの頻度を下げる
    • 断片化しないGCを使う
    • 短命JVM

自分用Mavenリポジトリを作る

※この投稿は、丸太式 Advent Calendar 2014の8日目です

自分で作った物のJAR(fat jarではない)をMavenリポジトリにデプロイしておけば何かと便利な気がしたのと、ExCellaをMavenで管理できないのはやっぱり不便なので、自前のMavenリポジトリを用意してみました。

必要なもの

  • Javaの実行環境
  • 適当なサーバ
  • Nginx等のフロントサーバがあるといいですね

やること

  • Sonatype NEXUS OSSをダウンロード
  • 適当なディレクトリに展開
  • 展開したディレクトリで、以下のコマンドをを実行
    % bin/nexus start
    ※Windowsならbin\nexus.bat startで良いんじゃないでしょうか
    フォアグラウンドで実行するなら、startの部分をconsoleにすれば良かったはず。

ExCellaを使ってJavaアプリケーションからExcel出力

※この投稿は、丸太式 Advent Calendar 2014の4日目です

ExCellaとは

JavaのプログラムからExcelファイルを操作するライブラリとしては、Apache POIが有名ですが、決まったテンプレートに値を設定して出力するような使い方をする場合に必要なコード量が多いと思います。
また、出力する項目は変えずに値を設定するセルをかえるだけでもプログラムを書き換える必要があり、とても扱いやすいとは言えません。
ExCellaは、そんな扱いづらいPOIのラッパーとして利用できるOSSのライブラリです。

ExCellaのコンポーネント

ExCellaは3つのコンポーネントで構成されており、それぞれのJarと、一緒にダウンロードできる依存ライブラリのJarをクラスパスに追加することで利用できます。
※現状Mavenで管理することはできませんが、GitHubのリポジトリを見る限りでは今後対応する方針のようです。
* ExCella Core
ExCellaのコアとなるコンポーネント。
他のコンポーネントから共通で利用される。
* ExCella Trans
データ移行の為のコンポーネント。
ExcelファイルやCSVファイルからSQLやJavaオブジェクトを生成できる。
* ExCella Reports
Excelの帳票を出力する際に用いるコンポーネント。
テンプレートに埋め込まれたタグを置換して、ファイルに出力できる。

Excel帳票出力のサンプルコード

ExCella Reportsを使った帳票出力のサンプルコードです。
単純にタグと値を一対一で置換する場合、これだけのコードで出力できます。

String templatePath; // テンプレートファイルのパス
String outputPath; // 出力先のファイルパス
 
// 1. ExCellaのReportBookオブジェクト(Excelのワークブックに相当)を生成する
ReportBook reportBook = new ReportBook( templatePath, outputPath, ExcelExporter.FORMAT_TYPE);
// 2. ExCellaのReportSheetオブジェクト(Excelのシートに相当)を生成する
ReportSheet reportSheet = new ReportSheet( "シート名");
// 3. テンプレートのタグを置換する値を設定する
// この例では、テンプレート中の ${tagName} を tagValue に置換します
reportSheet.addParam( SingleParamParser.DEFAULT_TAG, "tagName", "tagValue"); 
// 4. ReportBookにReportSheetを追加する
reportBook.addReportSheet( reportSheet);
// 5. 帳票出力処理を行う
ReportProcessor processor = new ReportProcessor();
processor.process( reportBook);

ExCella Reportsは単純な1対1の置換だけでなく、指定範囲の繰り返し置換にも対応しています。
詳しくは、公式のドキュメントをご覧ください。

最後に

ExCellaはOSSのプロダクトとしてはコミュニティがあまり活発ではありませんが、帳票文化が根付いている日本ではかなり便利に使えると思います。

参考リンク