Java EE Advent Calendar 2017 を振り返って

この記事は Java EE Advent Calendar 2017 の最終日です。

昨年私は Payara Advent Calendar 2016 を作成し、25 日のうち 19 日を担当するというほぼ「全部俺」状態でやっており、Java EE Advent Calendar 2016 でも 2 日ほど担当しました。今年、気が付いた時に Java EE 関連の Advent Calendar がなく、Payara 関連の記事だけで 25 日すべてを埋める余裕もなかったため、全部ひっくるめて Java EE Advent Calendar 2017 として作成しました。私が Payara 関連の記事 (しかも Dev ではなく Ops に近いテーマ) ばかり出したのも、そのあたりが関連しております。

振り返ると、結局また私が 25 日のうち 19 日を担当してしまったわけですが、私がどうしても埋められなかった残り 6 日に助け舟を出してくださった方々―紅月さん (@koduki)、田中さん (@TTakakiyo)、菊田さん (@kikutaro_)、多田さん (@suke_masa) そして岩崎さん (@HirofumiIwasaki) さんにはこの場を借りて御礼申し上げます。

さて、私が作成する Advent Calendar の最終日では恒例となった、カテゴリ別の記事のまとめです。今年の Advent Calendar を振り返りながら、逆引きとしても使えるようにまとめてみました。

Java EE 8 関連 (新機能)

今年は Java EE 8 がようやくリリースされましたので、それに関する記事は当然出てきます。とは言うものの、Java EE 8 は目新しい機能が少なく、Advent Calendar が Java EE 8 一色で染まるまでは至りませんでした。全体像をつかむには岩崎さんの「Java EE 8で何が変わったのか」から読み始めると良いでしょう。また、私の「MVC のこれまでとこれから」と多田さんの「Java EEにMVCはなぜ必要なのか」を読み比べると、同じ仕様に対して対極の意見が存在し、それに対して標準仕様としての折り合いを付けながら Java EE がアップデートされている姿を垣間見ることができると思います。

Java EE 全般 (バージョン非依存)

Java EE 8 よりも前 (主に Java EE 7) の話題もまだまだ健在です。あまり古い仕様は最新の Java EE 環境で使えない場合もありますが (プルーニング=不要な仕様を次のバージョンで非推奨にして 2 世代のバージョンで完全に Optional にする仕様整理、の実施も影響します)、標準仕様の使命として可能な限り限り互換性を保つようなアップデートを行いますので、長期間に渡って使い続けられる安心感はあります。ただし、開発したアプリケーションは放置せずこまめにアップデートしてくださいね。

MicroProfile

Java EE 8 の大幅な遅延に業を煮やしたベンダーと JUG (Java ユーザー・グループ) が勝手に立ち上げた、Java EE 7 のサブセットをベースとしたマイクロサービス向けの仕様セットが MicroProfile です。昨年に初版の MicroProfile 1.0 がリリースされ、今年 7 月 (本当であれば 5 月の JJUG CCC 2017 Spring で私が MicroProfile のセッションを行っている最中にリリースされる予定でしたが間に合いませんでした) に MicroProfile 1.1、9 月には MicroProfile 1.2 とアップデートされ、この年末年始に MicroProfile 1.3 がリリースされる見込みです。当初だんまりを決め込んでいた Oracle が MicroProfile 入りを表明したのも大きなニュースでした。

Payara

Payara の Ops に関する話題も、私からいくつかご紹介しました。特に「Payara のセキュア管理における JMX 監視」と「クラスタ化された Payara Server のアップグレード方法について」は、私が Payara Support Engineer としてお客様からお問い合わせをいただいたケースをもとに、広く一般向けにご利用いただけるようアレンジして記事としたものです。

その他

その他雑多な記事です。すべて私の戯言ですが、「Java EE 8 ドキュメント翻訳に関する提案」についてはご一読いただきたいです。日本語情報の不足は国内における Java EE の最新情報が伝わりにくくなっている一因となっています。かといって、ドキュメント翻訳のスポンサーの当てがない我々にとっては、できるだけ多くの人達が各々の隙間時間を使って少しずつ翻訳したものをマージしていくほかありません。一度に全量を訳すのは不可能ですが、まずリソースをリストアップして、その中から優先順位を決めて (MicroProfile 関連の需要が多いでしょうか) 進めていくほかありません。必然的に参加者が多くなるため、実際に作業をする人、作業分担を調整する (仕切る) 人、全体を押さえる (責任を取る) 人、と役割を決めてプロジェクトとして組織的に進めていくことが不可欠だと考えています。

まとめ

来年も機会が得られれば Java EE Advent Calendar を実施したいと思います。それまでの間に Java EE がより良い方向へと進むことを願うばかりです。

それでは皆様、よいお年をお迎えください。

これから Java EE を始める方へ

この記事は Java EE Advent Calendar 2017 の 23 日目です。昨日分は @HirofumiIwasaki さんの「Java EE 8で何が変わったのか」です。

さて、今回は 1 日早いクリスマス・プレゼントとして、これから Java EE を始めようと考えている方へのアドバイスをお伝えします。すべて鵜呑みにしない方が良いですが、半分くらい私の失敗を踏まえているため、大きく外したことは言っていないはずです。ご参考までに。

心構え

初日の記事でも触れましたが、Java EE はライブラリとフレームワークの集合体です。全部を使うケースは極めてまれで、ほとんどは構築するシステムの特性に応じて必要なものを組み合わせて使います。現在は Web システムが多いため、Web の関連する仕様を中心に覚えておくと良いでしょう。

かつて私とうらがみさん @backpaper0 が語り合い、「Java EE をすべて理解するには人生は短すぎる」という結論に達しました。すべてを網羅しようと意気込むのではなく、よく使う機能から少しずつ覚えていきましょう。

以降、Java EE を始めるのに必要なもの―実行環境、開発環境、Knowledge―をご紹介します。

実行環境

Java EE アプリケーションは作成しただけでは動かすことができず、ライブラリやフレームワークを含む実行環境が必要です。具体的には、JDK と Java EE サーバーを用意します。

JDK

Java EE サーバーもつまるところ Java のプログラムですので、それを実行するための Java VM が必要です。一部の API で開発用ツールを呼び出すことがあるため、JDK 一式を用意しましょう。できれば JDK 9 を使いたいところですが、本稿執筆時点ではいくつかの Java EE サーバーで動作不具合が報告されているため、さしあたっては JDK 8 の最新版を選択するのが無難です。

Java EE サーバー

Java EE のメリットはマルチベンダーであることですが、それは同時に選択肢に悩まされることでもあります。これといった決め手 (例: 職場で使っている Java EE サーバー) がない場合には、とりあえず Open LibertyWildFlyPayara の 3 種類から最初の 1 つを選びましょう。これらはいずれもオープンソースであり、これらを基にした商用版 (WebSphere LibertyJBoss EAP、Payara) も用意されていることから、個人での学習から実際の業務システム構築まで一貫して使い続けることができます。本稿執筆時点ではいずれも Java EE 7 対応版ですが、そう遠くないうちに Java EE 8 対応版もリリースされるでしょう。

  • Open Liberty -- IBM WebSphere Liberty のコア部分をオープンソース化したものです。商用環境向けの高度な機能は除外されていますが、開発者の自習環境としては十分な機能を備えています。単独の Java EE サーバーとしても動作はしますが、基本的には統合開発環境と組み合わせて、Java EE 7 アプリケーションと一緒にパッケージして実行する使い方を想定しています。
  • WildFly -- Red Hat JBoss Enterprise Application Platform (JBoss EAP) の先行版として開発されているオープンソースの Java EE サーバーです。WildFly で発見された不具合を修正し、商用向けの管理コンソール等の機能を追加したものが次期 JBoss EAP となります。マイクロサービス向けに WildFly とアプリケーションを 1 つの JAR ファイルにまとめる WildFly Swarm という派生版もあります。
  • Payara -- Java EE のリファレンス実装である GlassFish を改良し、定期的に不具合修正や機能拡張を行っているオープンソースの Java EE サーバーです。ベーシックな構成の Payara Server とマイクロサービス向けの Payara Micro があります。日本語化された管理コンソールは好評です。この 3 種類では唯一、オープンソース版と商用版が全く同一のバイナリとなっています。

※Payara については、2018 年第1四半期を目途に Java EE 8 への正式対応が予定されており、既にプレビュー版がダウンロードできるようになっています。

開発環境

統合開発環境

高機能エディタ、デバッガ、開発ツールが一体となった統合開発環境 (IDE) を使うと便利です。IDE は何種類もあるので自分に合わないと感じたら他の IDE に乗り換えた方がいいでしょう。EclipseNetBeansIntellJ IDEA の 3 種類が最も人気のある IDE で、これらのいずれかを選択すれば使い方等の情報には困らないでしょう。IDE は難しく感じたら無理をしてまで使う必要はないツールですが、Java EE のアプリケーションは最小限のサンプルプログラムでもソースファイル 1 つで済むような規模ではないため、直接プログラミングと関係のない部分を自動化してくれる IDE を利用した方が得策でしょう。

  • Eclipse -- Java VM がまだこなれておらず IDE も動作が遅く不便だった時代に、軽快な動作とプラグイン方式の拡張機能を引っ提げて登場し開発の現場を席巻した IDE です。日本国内では日本語化プラグイン Pleiades とセットで広く普及しています。Java VM の完成度が高まった現在では他の IDE に対する速度的・機能的優位性は薄れており、他の IDE (特に IntelliJ IDEA) に乗り換えるユーザーも後を絶ちませんが、いまだに根強い人気があります。
  • NetBeans -- Java とともに発展してきた IDE で、一時期は Java で最も標準的な IDE として位置づけられ、各種サンプルが NetBeans 前提で作られていました。日本人開発者が多く携わり、完全な日本語対応がなされているのも特徴です。VisualVM や Oracle SQL Developer といったツールのベースにもなっています。現在は Apache Foundation に移管され、開発が継続されています。
  • IntelliJ IDEA -- 古株の Java IDE では Eclipse の勢いに押されず独自の地位を保ってきた製品で、最近では Eclipse や NetBeans に先行して Java の新機能をサポートしたり、開発を容易にするツールを多く同梱するなどして、ユーザーを多く獲得しています。チェコの JetBrains 社が開発する有償製品ですが、オープンソース化され基本機能に限定した無償の Community Edition も用意されています (Java EE 開発は有償の Ultimate Edition でのみ可能です)。ライセンスは JetBrains 社から直接購入できる他、日本国内に正規代理店 (サムライズムうぃる) もあり、法人での購入も比較的容易です。

構成管理ツール

現在は Apache MavenGradle 等のビルドツールで必要な外部ライブラリを含めて管理します。統合開発環境にも Maven や Gradle が含まれています。Maven には少々融通が利かない面もありますが、Maven の基本的な使い方を覚えておかないと詰むことが多々あります。現在では主要なライブラリが Maven Central Repository というサイトに集約され、そこから Maven 経由でライブラリをダウンロードする仕組みが普及しているため、IDE よりもむしろ Maven の知識の方が重要かもしれないとさえ個人的には感じています (私はいまだ Maven に苦しめられています)。Maven ではなく Gradle を使用する場合も Maven Central Repository にアクセスすることには変わりありません。

もう 1 つ、ソースコードのバージョン管理ツールも重要なツールといえます (システム開発の現場では必ずと言っていいほど使用していると思います)。これも主要なツールがビルドツール同様、統合開発環境に含まれています。おそらく CVS、Subversion (SVN)、Git、Mercurial (Hg) のうち少なくとも 1 つ (製品によってはすべて) をサポートしているでしょう。ただし、前述のビルドツールと異なり、学習し始めの頃はなくても差し支えないものではあります (せいぜいサンプルコードのダウンロードに Git を使用する程度)。全体的には Git がかなり普及していますが、システム開発の現場では Subversion もよく使われています。個人的には両方を見てそれぞれの長所・短所を理解した上で Git を選択するのがベストだと考えていますが、余裕がなければ最初に Git を選択しても外れではありません。

ネット上で Subversion (あるいは CVS) を使っている等公言すると、この世知辛いご時世では迫害されるケースもないとは言えません。Git より Subversion の方が自分にあっていると感じたのなら、そのことを黙って使い続けましょう。Subversion を愛用すること自体が悪いとは私は思いません。

参考までに、Git と Subversion の参考書を挙げておきます。必要になった時、書店で探してください。

わかばちゃんと学ぶ Git使い方入門

湊川あい (著)

現時点で Git の参考書を 1 冊選ぶのであれば、私個人的にはこちらをお薦めしています。表紙から受けるイメージに反して、比較的深いところまで触れています。

実用 Subversion 第2版

C. Michael Pilato、Ben Collins-Sussman、Ben Collins-Sussman (共著)

Subversion の開発者が自ら執筆した解説書です。以前は Web で日本語訳が公開されていたのですが、今は書籍だけのようです。

Hello, world のためだけに、我々は多数のツールの使い方を覚えなければならなくなっている。寒い時代だと思わんか?

Knowledge

学習書

多少英語が読めるようであれば、Java EE チュートリアルをおすすめします。よく使う機能から他ではあまり触れられていない機能まで、一通りを学ぶことができます。

Java EE チュートリアルの関連である「Java EE SDK」とは、GlassFish に Java EE チュートリアルのサンプルプログラムを同梱したセットです。サンプルプログラムは単体でも配布されていますので、他の Java EE サーバー (Payara 5 のプレビュー版がおすすめ) で試すこともできます。

日本語の場合は、Webで体系的な知識を得るのがほぼ不可能であるため、書籍に頼るところとなります。Java EE 7 対応版によりますがいくつか書籍が出ています。Java EE 8 も Java EE 7 + α 程度の仕様であるため (詳細は昨日の岩崎さんの記事にて)、内容はそのまま活かせます。

パーフェクト Java EE

井上 誠一郎、槙 俊明、上妻 宜人、菊田 洋一 (共著)

内容を Java EE 7 Web Profile (Web アプリケーション向けサブセット) に限定する代わり、中核技術―CDI、JSF、JPA、JAX-RS 等―に的を絞って重点的に解説しています。どの章も良質ですが特に CDI の解説は秀逸です。筆者曰く「初心者向けではない」とのことですが、実際のところそれをどう捉えるかは読者次第でしょう。

Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築

寺田 佳央、猪瀬 淳、加藤田 益嗣、羽生田 恒永、梶浦 美咲 (共著)、小田圭二 (監修)

Java EE 7 に関する実質的な日本オラクル公式解説書という位置づけです。Web Profile 中心の解説は「パーフェクト Java EE」と似ていますが、品質においてはやや劣ります。ただし JSF の解説は必見。複数章を割き基礎から丁寧に解説しています。

わかりやすいJavaEEウェブシステム入門

川場 隆 (著)

Web アプリケーション開発に特化して Java EE 7 を解説した書籍です。内容はかなり丁寧に書かれていますので (GlassFish の Java DB 関連バグ回避手段をあたかも必須手段であるかのように説明するのはどうかと思いましたが...) 前 2 冊よりも敷居が低いのは確かでしょう。その代わり、取り上げる内容は限定され、JAX-RS が取り上げられていないなどの妥協点は見られます。

アプリケーションアーキテクチャ設計パターン

斉藤 賢哉 (著)

名著「マスタリング Java EE 5」の斉藤さんによる新しい書籍です。本著は表題通り、アプリケーションをどう作るかに焦点を置いた解説がなされていますが、コーディング例に最新の Java EE 8 が取り入れられているのは特筆すべきです (もちろん、他の要素技術も紹介されています)。Java EE + 周辺を学ぶのに適しているかと思います。先の 3 冊よりはやや高難易度かもしれません。

FAQ、Tips

ある程度まとまったものとしては、個人的には IBM が公開している developerWorks がおすすめです。日本語で、丁寧かつ詳細に書かれています。Open Liberty に最も適しますが、WildFly や Payara にも当てはまります (そこが標準規格である Java EE の利点でもあります)。また、内容は上級向けですが、ドイツのJava Champion Adam Bien のブログは興味深い内容が満載です。Tips だけでなく読み物やインタビュー記事もあります。

はじめのうちは「やってみた」系 (How) の記事よりも、「なぜそうなるか」系 (Why) の記事を多く見ておいた方が良いでしょう。「やってみた」系記事だけでは知っておかなければいけない背景知識が身につかないのと、「やってみた」系の記事には筆者が偶然できただけの再現できない方法が載っている場合があるためです (もちろん、有益な情報も多くあります)。日本人の技術ブログ (Qiita 記事含む) で圧倒的に多いのが「やってみた」系なのですが。

FAQとしては Stack Overflow (英語) が定番です。日本語版 Stack Overflow もありますが、内容は薄めであまり期待はできません。他の技術にも共通していますが、英文の読解能力が問われます。

文献一般、特に Web に言えることですが、情報は鮮度も重要です。日付を確認し、古いものについてはもう通用しない内容かもしれないことを考慮しましょう。

Java EE は、思い立ったら今日からでも始められます。では、ともに行きましょう!

サーブレット昔話

この記事は Java EE Advent Calendar 2017 の 21 日目です。

今日はまたお話回です。

今回はサーブレットの黎明期について取り上げたいと思います。サーブレット登場当時、私は大学生でその存在を知っていましたが、同時にあまり興味がなかったこともあって (ちょうど専攻分野の建築環境工学・都市環境工学が面白くなってプログラミングから遠ざかっていた時期と重なります)、リアルタイムではそれほど多くの情報を得ていなかったことをはじめにお断りしておきます。

サーブレット前史

World Wide Web (WWW) が CERN の Tim Berners-Lee によって開発され、初めてインターネットに公開されたのは 1991 年のことになります。最初に開発された Web サーバーである CERN httpd は静的コンテンツしか扱えませんでしたが、1993 年に登場した NCSA httpd にはコンテンツを動的に生成するいくつかの仕組みが備わっていました。そのうちの 1 つ、Common Gateway Interface (CGI) は、Web サーバーから外部のプロセスを呼び出し、そのプロセスの標準出力をコンテンツとして返すことができる機能でした。CGI の登場により Web アプリケーションというものが発生し、インターネットの商用開放によって爆発的に普及することになります。NCSA httpd は CGI の普及とともに大きくシェアを伸ばしますが、メンテナンスの停滞から派生版の Apache HTTP Server (1995 年) に取って代わられてゆきます。その後に登場した Web サーバーの多くも CGI をサポートし (実は Apache Tomcat にも CGI が備わっています)、NCSA httpd の独自仕様だったものがデファクトスタンダードとなりました。

CGI は画期的な仕組みでしたが、いくつかの欠点も抱えていました。

  • CGI はリクエストのたびに外部プロセスが呼び出されるため、1990 年代のコンピュータの性能ではプロセス起動のオーバーヘッドが無視できませんでした。特に当時は Unix のシェルスクリプトや Perl スクリプトといったインタプリタが多用されていたため、その傾向が顕著でした (パフォーマンス改善のため C などのコンパイラ言語で実装し直すケースも少なくありませんでした)。これを改善するために、起動したプロセスを使いまわす FastCGI や、スクリプトのインタプリタを Web サーバーと直結させる mod_perl 等が開発されます。
  • CGI から呼び出されるプロセスは最終的な出力をすべてレンダリングしなければならないことが挙げられます。特に動的な HTML コンテンツを生成する場合、タグの出力処理は相応の負担になりました (CGI で Perl が好まれて使用された背景には、文字列操作が容易な Perl で HTML 出力にかかる手間を軽減させる意図がありました)。なお、私は当時 Sun OS 4 上の C コンパイラで CGI のプログラムを作成していましたが、これはパフォーマンスを考慮したものではなく、単純に当時の私が Perl を知らなかったからです。これに対する抜本的な対策として考案されたのがいわゆるテンプレートエンジンであり、代表的なものが PHP (1995 年) です。
  • CGI の処理は 1 回の呼び出しで完結しなければならず、複数回の呼び出しをまたいで状態を保持することができません。これは CGI の欠点というよりは HTTP そのものが持つ制約でもありますが (状態を持たない故に HTTP は簡潔な仕組みになったとも言えます)、Web アプリケーションとしては状態を持てないことが不利に働くこともあります。例えば、ネットショッピングのショッピングカートのような仕組みは、複数回かつ複数プログラムにわたる呼び出しで状態を保持できないと成り立ちません。この問題を解決するために導入されたのが Cookie という仕組みですが、当時はすべての Web ブラウザが Cookie に対応していたわけではなく、また Cookie に対応した Web ブラウザであってもユーザー設定により Cookie を無効化されることもあり、確実な方法とは言えませんでした。

サーブレットの登場は、はっきりとは覚えていませんが、1998 年頃には最初のバージョンが登場していたと記憶しています。CGI が登場してから約 5 年後のことになります。

サーブレットと CGI

サーブレットが採用し、そして Struts の流行によりサーバーサイド Java で一般的となったリクエスト・レスポンス・モデルは、原理的には CGI とほぼ同じものです。言い換えると、サーブレットと CGI は類似技術ということになります。

サーブレットでは CGI の低レベル API 故の複雑さを、Java 技術とオブジェクト指向プログラミングで改善したものです。

サーブレットにはリクエストとレスポンスをハンドリングするのに最低限必要な機能セットを定義した Servlet インタフェース、Servlet インタフェースの汎用的な実装である GenericServlet クラス、そして GenericServlet を HTTP に特化させた HttpServlet が標準で用意されていました (後の JavaServer Faces では HttpServlet を拡張した FacesServlet がコア部分となっています)。サーブレットの設計では典型的な継承中心のモデリングがなされていたことが伺えます。

私のような CGI からサーブレットに移行した者にとって、サーブレットでは CGI のようなヘッダー文字列の出力処理を記述しなくてよいことが大きな驚きでした。CGI プログラミングではこのヘッダー出力がかなりの負荷になっており (Perl が CGI の標準的言語として使われるようになった背景には Perl であればヘッダー文字列の編集が比較的容易で、さらには CGI.pm というユーティリティが用意されていたことが挙げられます)、それがなくなるだけでもプログラミングはだいぶ楽になりました。

サーブレットでは、ランタイム環境であるサーブレット・コンテナがプロセスとして動作し、各サーブレットはその中のスレッドとして動作するよう設計されていました。スレッド生成のオーバーヘッドはプロセスのそれに比べるとはるかに小さいため、パフォーマンス向上に大きく貢献しました。マルチスレッド環境では通常、スレッド間の協調動作が課題となってきますが、サーブレットはリクエストごとに生成され独立したスレッドで動作するため、そうした問題とも無縁でした。Java EE サーバーがリクエストを受け取ってそれをサーブレットに渡すまでの過程は、現在では複雑になっていますが (「C10K 問題」で検索してみてください)、サーブレットから見た限りでは特に変化はありません。

サーブレットが CGI よりも優れている点として、HttpServlet に限定されますが、状態を保持する仕組み (セッション・オブジェクト) が備わっていることが挙げられます。CGI では専ら Cookie に頼っていましたが、サーブレットではサーブレット・コンテナで状態を保持できるようになっています。状態を保持してもそれを Web ブラウザと共有できなければ意味がないのですが、それについてはセッションの ID (JSESSIONID) を Cookie で保持するか、Cookie が使用できない場合にはクエリ文字列に付加することで、それを可能としています。

Java Server Pages の導入

サーブレットは CGI と比較すると Web アプリケーションを容易に構築することが可能となりましたが、出力の HTML をすべて動的に生成する手間についてはそれほど大きくは変わりませんでした。サーブレットが登場した時点で、PHP や Active Server Pages (ASP) といった、HTML のひな型にデータを流し込んで出力 HTML を生成するテンプレート・エンジンが既に登場していました。これらに対抗して開発されたものが Java Server Pages (JSP) です。

JSP は、厳密に言うとテンプレート・エンジンではありません。JSP は HTML のひな型に Java のコードを含める、ASP に酷似した形式のファイルで画面を記述しますが、実行時には同じ動きをするサーブレットに変換して、それを実行する方式を採っていました。JSP からサーブレットへの変換には、Apache Tomcat の Jasper をはじめとする JSP エンジンが用いられ、通常 JDK (JRE ではなく) を必要としました。JSP は実行時に実質的なコンパイルが行われるため、純粋なテンプレート・エンジンと比較して実行速度において不利でした。それでもサーブレットよりも容易に画面を実装できる手段であり、Java EE 5 までは代替技術がなかったこともあり広く用いられました。Java EE 6 になって Facelets が JSP 代替技術として採用され、Java EE 7 の構想初期段階では JSP を Java EE から削除することも検討されましたが、結局は現状維持とされ、Java EE 8 に至るまでその地位を保ち続けています。

Model 1 と Model 2、そして Struts

JSP は HTML のひな型に Java のコードを含めることが可能です。これをスクリプトレットといいますが、スクリプトレットを多用すると画面とロジックが密接に結びついてしまい、時としてメンテナンスを困難にさせてしまいます (これは ASP や PHP にも共通して言えることです)。そこで当時の Sun Microsystems では、Smalltalk の Model-View-Controller (MVC) アーキテクチャを参考に、JSP からロジックを分離して View に見立て、Controller としてサーブレットを置き、両者を JavaBeans の Model で連携するアーキテクチャを提案します。ロジックの動作によって得られた結果は、Controller であるサーブレットに伝わり、そこから Model である JavaBeans によって View の JSP へと伝えられます。ただし、オリジナルの MVC アーキテクチャでは Model の変更が View に対して通知されるのに対して、Sun の提案では View である JSP が Model である JavaBeans の状態を確認する (つまり Model-View 間のデータの流れが逆になる) ため、厳密には MVC とは言えないところがあります。そのため、この Sun の提案は Model 2 アーキテクチャと名づけられました。一方でスクリプトレット主体の方法を Model 1 アーキテクチャと呼んで区別しました。実際のところ Model 2 アーキテクチャという呼び名はそれほど普及せず、多くの開発者は MVC と呼んでいます。

この Model 2 アーキテクチャに準拠したアプリケーション開発フレームワークとして一世を風靡したのが、現在ではレガシー Java システムの代名詞ともなった Apache Struts (Struts 0.x~1.x) です。サーブレットと JSP で Model 2 アーキテクチャ準拠のアプリケーションを開発しようとすると、幾分ぎこちない上に相応量の定型処理が発生していました。Struts はそれに対して明確な答えを持っており、オープンソースでもあったことから拡張も比較的容易でした。多くの開発者が Struts を受け入れ、各々のやり方で Struts をカスタマイズしながら普及させてゆきました。Struts 自身は 2007 年頃から更新されておらず、その数年後に正式な開発終了が宣言されましたが、現在に至るまで使用され続けています。

Struts 2 は Apache Foundation に寄贈された WebWorks という Web アプリケーション・フレームワークを Struts 風のネーミングにリファクタリングしてリリースしたもので、ここで取り上げた Struts とは本質的に異なります。

Struts は多くのライブラリを発明しました。Apache Commons のいくつかは Struts 発祥のライブラリで (Log4J も Struts 標準ロガーとして名を挙げたコンポーネントです)、後に JSTL として採用される JSP のタグライブラリも Struts のタグライブラリをベースに開発されたものです。タグライブラリは Model 2 アーキテクチャが目指した画面とロジックの分離をさらに強固なものし、後の JavaServer Faces (JSF) にまで影響を与えています。


明日は @suke_masa さんです。

GlassFish Users Group Japan 勉強会 2017 Winter

この記事は Java EE Advent Calendar 2017 の 20 日目です。昨日分は @kikutaro_ さんの「Payara-Examplesで始めるJava EE」です。

昨日 (12 月 19 日) に GlassFish Users Group Japan で勉強会を行いました。前回の催し物が 6 月に行った Payara との共催イベント Payara初来日記念!「Payara Meetup」で、ユーザー会単独の催し物としては 2015 年 9 月 16 日の 帰ってきたGlassFish Users Group Japan勉強会 以来となります。企画当初は週末を使った Payara Micro のハンズオンを検討していたのですが、Payara Micro の機能は現在では多岐にわたるため、基本編と応用編に分けて実施するのが妥当なこと、そして何よりハンズオン資料が全く手つかずの状態で (ごめんなさい)、ハンズオン会場の第一候補であったカサレアル様に 12 月 19 日の勉強会開催を打診して、快く引き受けてくださいました。カサレアル様、ありがとうございます。

今回は初めての試みで、勉強会と忘年会 (懇親会) を 19:00~22:00 の間に完結させようと、勉強会をショート・セッション (20 min) × 3 にして 20:30 までに終了させ、その後 1 時間強を忘年会 (懇親会) に充当しました。

勉強会&忘年会について

セッション 1 -- MicroProfileの概要と最新状況 (@n_agetsu)

1 本目は上妻さんのMicroProfileの話。スライドが公開されているので以下に挙げます。

上妻さんと言えば、トラブルシューティング、あるいは CDI のイメージが強く、MicroProfile のセッションと聞いて意外な方の方が多かったのではないでしょうか。MicroProfile の成り立ちから将来予定されている MicroProfile 2.0 まで、一通り網羅されていると感じました (※活動休止中ですが、実は私も MicroProfile の末端メンバーです)。一番嬉しいのは、MicroProfile 1.1 以降に導入された新 API のツアーです。私も立場上、MicroProfile API の仕様書を読むことがありますが、(英文か和文かということを抜きにして) 文章だけの説明となるため、数ページの仕様書を読んでもはっきりしないことがたった 1 枚の図説スライドに集約されると助かります。

セッション 2 -- Java EEでもOAuth 2.0!~そしてPayara Micro on Cloud Foundryで遊ぶ~ (@suke_masa)

続いて、多田さんから OAuth 2.0 のお話。

セッション副題に「遊ぶ」と入ってはいますが、そこまで易しい話題ではないです。セッション自体は過去の JJUG CCC で失敗したデモを見事成功させつつ、「ここは必ず押さえるべし」「ここは (ややこしいので) 必ず図に書いて理解すべし」と現役研修講師らしいアドバイスを交えたセッションでした。1 回 20 分のセッションで理解できるほど OAuth 2.0 は易しくはありませんが、このセッションをきっかけに多くの方が OAuth 2.0 のはじめの一歩を踏み出せたら、と思います。なお、OAuth 2.0 は Facebook 等で用いられている (はず) もので、Twitter で用いられている OAuth 1.0 とは全くの別物です。多田さん曰く「Struts 1 と Struts 2 くらい違う」―本来は同じ名前を冠してはいけないくらい違っているということですね。

セッション 3 -- 2018年のGlassFishとPayaraの動き (@khasunuma)

私のセッションです。コミュニティが知り得る範囲とは言え将来の計画 (コミュニティに伝えられているもの) を含んでおり、Safe Harbor Statement をどう書けばいいのかもわからなかったので、スライドは非公開とさせていただきました。GlassFish、EE4J、Payara がそれぞれ 2018 年に何を目指そうとしているのか、コミュニティ視点からご説明しました。大筋は以下の通りです。

  • GlassFish は EE4J 入りを目指しており、また、マイナーアップグレード (GlassFish 5.0.1?) が予定されている。ただし、今後は国際化サポート (日本語化) 等が削除され全体的にダイエットが図られる見込み。
  • EE4J には Java EE 8 の中核機能から 8 プロジェクトが新たに合流する見込み。スペックリードは全員入れ替え。JMS の共同スペックリードには Tomitribe の David Blevins (某 N 川氏曰くいろいろ熱い人)、JSF のスペックリードには Payara の Arjan Tijms、といった感じに。
  • Payara は現時点では 2018 年から Java EE 8 対応の Payara 5 がコミュニティ・リリースになる予定で、最初のバージョンは Payara 5.0.181。サポート契約者向けには Java EE 7 対応の Payara 4.1.2.181 も提供される。

忘年会 (懇親会)

GlassFish Users Group は設立以来、たとえ勉強会を開催しない年があったとしても、忘年会だけは欠かさず実施するようにしていました。私が会長になってからはその伝統は崩れてしまいましたが、今回はささやかながら忘年会を実施しました。年の瀬のこの時期にお店を予約するのは大変なので、ピザと飲み物 (ビール & ソフトドリング) のデリバリーにしました。

まとめ

やればできるじゃん!

2018 年は計画的に勉強会&イベントを開催したいと思います。ご都合が付きましたら、ぜひご参加ください。


明日はサーブレット黎明期 (Struts が登場するころまで) のお話についてお伝えします。例によってコードが一切出てこないお話ですが、WWW の誕生から Web アブケーションが誕生し、サーブレットをはじめとする技術が登場した背景について、私の知る限りでお話します。

Java EE 8 ドキュメント翻訳に関する提案

この記事は Java EE Advent Calendar 2017 の 17 日目です。今回は、Java EE 8 の日本語ドキュメントを整備したい、それによってより多くの開発者に Java EE を使ってもらいたい、という個人的な思いからの、ちょっとした提案です。当初は 21 日目に提案を予定していましたが、早めの方がいいと思って 17 日目と入れ替えました。

現在、@megascus 氏を中心に個人レベルで Java EE 8 API の日本語訳が行われているようです。私も先ほど翻訳を拝見しまして、とてもありがたいことなのですが、この先を考えるといろいろ大変なことが待ち受けていると感じました。Java EE のドキュメントはとても 1 人では翻訳しきれない量で、必然的に多くの人達のコントリビューションによってはじめて形になるものです。また、Java EE API は多岐に渡ることから個々人の得意・不得意が発生しやすく、不得意分野の翻訳は想定以上の負荷がかかります。また、今回は GlassFish / Java EE 配下のリポジトリを眺めていて偶然 @megascus 氏が servlet-spec をフォークして翻訳しているのを発見しましたが (以前から話には聞いていましたが現物を見たことがありませんでした)、せっかくの成果物も誰の目にも触れないようでは役に立ちません。

さらに本家へのマージとなると Oracle Contributor Agreement (OCA) という障壁が立ちはだかるわけですが、少なくとも私は OCA を締結していますし、当面本家へのマージ提案はないので、OCA の件はしばらく保留にしておいて問題ないと考えています。

そこで提案なのですが、特定の誰かのリポジトリではなく、日本の Java コミュニティとしてリポジトリを用意して、そこに翻訳を集約するようにしたらいかがでしょうか。日本語翻訳のハブのようなものがあれば、翻訳する側もそれを利用する側もわかりやすいと思うのです。単に提案するだけでは私を含めて誰も動かないこともあり得るため、取り急ぎ私の方で javaee-japanese という GitHub Organization を作成しておきました。

Java EE 8 API リファレンス

Javaa EE 8 チュートリアル

ご協力いただける方は、これらのリポジトリをフォークして、ご自身が担当する部分を Issue Tracker で表明した上で、翻訳したものを Pull Request していただけると幸いです。あわせて、この GitHub organization の管理者 (PR のマージ権限を持つ人) も募集したいと思います。このような試みは何分初めてなもので不慣れな点も多いかと思います。お気づきの点がございましたら k.hasunuma@coppermine.jp までご連絡ください。

※各リポジトリとも Issue Tracker が有効になっています。ご自身の担当範囲の表明 (および変更)、翻訳していてわかりづらい点の質問、翻訳済み個所の改善提案などにご活用いただければと思います。

私が Payara Support のお仕事に就いてから約 1 ヶ月が経ち、ローカリゼーション (L10N) / インタナーナショナリゼーション (I18N) も意外と侮れないものだと実感しています。突然の提案で恐縮ですが、ご協力いただけると幸いです。よろしくお願いします。

JAX-RS 2.1 の Server-Sent Event

この記事は Java EE Advent Calendar 2017 の 16 日目です。

Java EE 8 の JAX-RS 2.1 には 2 つの大きな機能拡張があります。1 つは非同期通信のサポート強化です。JAX-RS 2.0 でもクライアント・サーバーともに非同期通信をサポートしていましたが、マイクロサービスを見据えた JAX-RS 2.1 では本格的なテコ入れが行われています。よく話題に上るのがリアクティブ・クライアントの追加です (リアクティブ API は必ずしも非同期になるとは限りませんが)。いい加減見飽きたでしょうが、リアクティブ・クライアントの使用サンプル (JAX-RS 2.1 仕様書から引用) を以下に示します。

CompletionStage<Number> csp = client.target("price/{destination}")
    .resolveTemplate("destination", "mars")
    .request()
    .rx()
    .get(Number.class);

CompletionStage<String> csf = client.target("forecast/{destination}")
    .resolveTemplate("destination", "mars")
    .request()
    .rx()
    .get(String.class);

csp.thenCombine(csf, (price, forecast) -> reserveIfAffordableAndWarm(price, forecast));

CompletionStage を用いてサービスを次々と呼び出し、レスポンスを組み合わせて処理しているのが見て取れるかと思います。JAX-RS 2.0 のクライアントでは非同期通信のコールバック内でさらに他のサービスを呼ぶような形を取らざるを得ませんでしたが、リアクティブ・クライアントの導入により呼び出し処理がシンプルになります (厳密な同期・非同期も考慮しなくて済みます)。この他にも非同期通信の扱いは全面的に強化されています。

今回の主題はもう 1 つの新機能である Server-Sent Event (SSE) です。少し前の発表資料ですが、再掲します。

当時はまだ Jersey の独自機能でしたが、JAX-RS 2.1 の SSE は概ね Jersey の SSE を踏襲しています。特にクライアント側の API はとても良く似ています。

まずはサーバー側のサンプルコードから見てみましょう (JAX-RS 2.1 仕様書からの引用です)。

@GET
@Path("eventStream")
@Produces(MediaType.SERVER_SENT_EVENTS)
public void eventStream(@Context SseEventSink eventSink, @Context Sse sse) {
  executor.execute(() -> {
    try (SseEventSink sink = eventSink) {
      eventSink.send(sse.newEvent("event1"));
      eventSink.send(sse.newEvent("event2"));
      eventSink.send(sse.newEvent("event3"));
    }
  });
}

ここでは SseEventSink と Sse という 2 つのコンテキストをメソッド引数に inject しています。簡単に言えば、Sse でイベントを作成して SseEventSink に送ると、それがクライアント側に Push される、といった具合に動きます。Jersey SSE よりもシンプルに書けるよう工夫がなされています。try-with-resources は SseEventSink のクローズを行うために少し強引な書き方 (変数 sink は使用されない) をしています。また、ManagedExecutorService.execute() を使って別スレッドで実行していますが、SSE は最後のイベント Push が完了するまで HTTP セッションを閉じないため、リソースクラス本体のスレッドで実行すると処理が固まってしまう恐れがあるためです (JavaFX や Android のような GUI プログラミングにおけるイベント処理では必ずと言っていいほど用いられる方法です)。

次にクライアント側のサンプルコードです (こちらも JAX-RS 2.1 仕様書からの引用です)。

WebTarget target = client.target("http://...");
try (SseEventSource source = SseEventSource.target(target).build()) {
  source.register(System.out::println);
  source.open();
  Thread.sleep(500); // Consume events for just 500 ms
} catch (InterruptedException e) {
  // falls through
}

これは try-with-resources が使えるようになったことを除いてかつての Jersey SSE そのままです。

  • SseEventSource がイベント Push を受け取るもの
  • SseEventSource.register() でイベントを受け取った時のコールバック処理 (ここでは System.out.println() を用いて出力するだけ) を登録
  • SseEventSource.open() でイベントの受信開始

となります。SSE ではクライアント側がインバウンド通信 = 待ち受け処理を必要とするため (通常はサーバー側がインバウンド通信となる)、クライアントと言いながらサーバー的なプログラミングが要求されます。ただし、複雑な待ち受けではないため、すぐに慣れるでしょう。

最後に、同じサーバー Push を実現する WebSocket との棲み分けですが、WebSocket は HTTP 101 によるプロトコル・スイッチにより HTTP(S) 上の独自プロトコルとして双方向通信をサポートします。一方、SSE はプロトコル・スイッチが発生せず、サーバーからクライアントへの片方向通信になります。

JSON-B のご紹介

この記事は Java EE Advent Calendar 2017 の 15 日目です。今日はちゃんと技術的なことを書きます。

Java EE 8 から JSON-B (JSON Binding) という、JAXB の JSON 版のような API が新たに加わりました。これまでも Jackson や EclipseLink MOXy 等のライブラリが JAXB に加え独自の JSON バインディング機能を持っていましたが、それを標準化するべく誕生したのが JSON-B (JSR-367) です。最初に聞いた時のリファレンス実装は EclipseLink MOXy だったので、MOXy の JSON バインディング機能をそのまま採用するのかと思いきや、気付いたらリファレンス実装が Yasson というライブラリに変わっていて、JAXB とは似ても似つかない API に仕上がっていました。なお、Yasson は EE4J 発足直後に参加を表明しています。

JSON-B は Java EE 8 準拠のサーバーであればすぐに使用できますが、Java SE から呼び出して使うことも可能です。その時に必要となるライブラリの Maven 依存関係を以下に示します。

<!-- JSON-P API -->
<dependency>
  <groupId>javax.json</groupId>
  <artifactId>javax.json-api</artifactId>
  <version>1.1</version>
</dependency>

<!-- JSON-P RI -->
<dependency>
  <groupId>org.glassfish</groupId>
  <artifactId>javax.json</artifactId>
  <version>1.1</version>
</dependency>

<!-- JSON-B API -->
<dependency>
  <groupId>javax.json.bind</groupId>
  <artifactId>javax.json.bind-api</artifactId>
  <version>1.0</version>
</dependency>

<!-- Yasson (JSON-B RI) -->
<dependency>
  <groupId>org.eclipse</groupId>
  <artifactId>yasson</artifactId>
  <version>1.0.1</version>
</dependency>

依存関係に JSON-P 1.1 (Java EE 7 の JSON-P 1.0 ではない) が含まれていることに注目してください。JSON-B/Yasson は単独で動作する API ではなく、JSON-P 1.1 の存在を前提として作られています。可能な限り JSON-P のコードを生かそうとする設計思想が伺えます。

Java EE 7 上では JSON-P の新旧バージョンが重複して存在することになるため、できれば使用しない方がいいと思われます。お使いのアプリケーション・サーバーのクラス・ローダーに関して専門的な知識を有していて、その上で自己責任で行うのであれば話は別ですが。

これは JSR-367 の仕様書にも記載されていることですが、JSON-B は RFC 7159 に従って JSON のシリアライズ・デシリアライズとデータ・バインディングを行います。ただし、JSON の規格にない日付型の変換がサポートされている (JSON 側は ISO 8601 準拠で扱う) など、独自色も少しあります。Date and Time API にも完全対応です!

基本的な使い方は、以下のようになります。

  1. JsonbBuilder.create() メソッドから Jsonb オブジェクトを取得する (この時に null の扱いやフォーマット等のオプションを設定できる)
  2. Jsonb.toJson() メソッドで JSON に変換、Jsonb.fromJson() メソッドで JSON をパース

メソッドは IDE のサジェスト機能だけで全容をほぼ把握できる程度です。バインディング対象の Java クラスも、基本的にはアノテーション不要です。

マッピングを明示する場合 (Java 側と JSON 側で異なる名前のマッピングを含む) は @JsonbProperty アノテーション、マッピングから除外する場合は @JsonbTransient アノテーションをそれぞれフィールド、getter、setter のいずれかに付けます。フィールドにアノテーションを付加した場合はシリアライズ・デシリアライズ両方、getter はシリアライズのみ、setter はデシリアライズのみ、それぞれ作用するようになります。

最初はサンプルを載せようかと思って途中まで用意したのですが、あまりにシンプルでむしろ pom.xml に依存関係を追記する方が大変なくらいだったので、そこは各自にお任せします。GlassFish 8、Payara 5、あるいは Java SE で試してみてください。

なお、Java SE で試す場合、Yasson のバージョンは 1.0.1 にしてください。バージョン 1.0 はたぶんバグだと思うのですが JsonbBuilder.create() のタイミングで ClassNotFoundException がスローされます (しかも見つからないと言っているクラスは存在している謎)。

この記事は Java EE Advent Calendar 2017 の 14 日目です。

そろそろ Java EE 8 を本格的にフォローしないとまずいかと思い、Java EE 8 の仕様 (JSR 366) を斜め読みしていたのですが、今さらながらその中に JCache (JSR 107) が含まれていないことに気づきました。JCache は Java EE 7 にギリギリ間に合わなかった後、比較的早くに完成していたので、いくつかのアプリケーション・サーバーが独自にサポートを始めています。Java EE 8 の当初案でも JCache は入ると言われていたので、この事実には少々驚きました。

どうやら JCache、本当に落ちていたらしいです。

実を言うと、今回は当初「Java EE 8 における Web Profile」として考えていたのですが、それに至る調べ物の中で JCache の不在に気付き、急遽内容を変更しました。なお、Java EE 8 の Web Profile は、JSON-B が追加されたことを除き Java EE 7 を踏襲しています。

Eclipse MicroProfile 1.2

この記事は Java EE Advent Calendar 2017 の 13 日目です。

Eclipse MicroProfile 1.2 がリリースされています。このバージョンには、以下の API が含まれています。

  • JAX-RS 2.0.1
  • CDI 1.2
  • JSON-P 1.0
  • Eclipse Config API 1.1 Upgraded!
  • Eclipse MicroProfile Fault Tolerance 1.0 New!
  • Eclipse MicroProfile Health Check 1.0 New!
  • Eclipse MicroProfile Metrics 1.0 New!
  • Eclipse MicroProfile JWT Authentication 1.0 New!

Config API 1.1 については 8 日目に触れたとおりです。

Fault Tolerance は、サービス呼び出しのタイムアウト、リトライ、フォールバック、サーキット・ブレーカーなどに関する API セットです。

Health Check は、サービスの状態監視に関する API を提供します。サービスの死活監視を自動化するケースなどで使用します。

Metrics もサービスの状態監視に関する API ですが、こちらは従来であれば JMX によって提供されるようなメトリクスを REST API で提供できるようにする仕組みです。

JWT Authentication は名前だけでは少々わかりにくいですが、OpenID Connect ベースのトークン認証と RBAC 制御の実装に用いる API を提供します。JWT は JSON Web Token の略です。

今回追加された 4 つの仕様は、当初 MicroProfile 1.1 に導入するべく作業を進めていたものの結局間に合わなかったものです。MicroProfile 1.1 自体が遅延したため、ほとんど間を置かず MicroProfile 1.2 に含まれることになりました。

それぞれの機能の細かな使い方については、いずれご紹介する時が来るかもしれません。

MicroProfile のブログによると、今後は MicroProfile 1.3 でもう少し API を増やしたのち、MicroProfile 2.0 で Java EE 8 と足並みを揃える (JAX-RS、CDI、JSON-P のアップグレードと JSON-B の導入) 模様です。

JavaFX 9 WebView の WebGL 対応について

この記事は JavaFX Advent Calendar 2017 の 12 日目です。昨日分は @boochnich さんの「JavaFX 3Dで赤道座標系の地球表示(1)」です。

1~2 年前の情報になりますが、JavaFX 9 から WebView が WebGL に対応するという話を聞き、ひそかに期待していました。本日はその希望が絶望へと変わった瞬間についてお伝えしようかと思います。

Storm Tracks WebGL Too というサイトがあります。このサイトは WebGL を使用して過去に発生したハリケーンや台風などの進路を 3D グラフィックスの地球儀上に表す (地球儀はマウスのドラッグで動かせる) というものです。以下は Google Chrome で開いたときのスクリーンショットですが、Edge 等の他のブラウザでも見られます。

webgl-chrome.png

JavaFX の WebView は WebKit を使用しているため、WebKit 派生の Blink を使用した Chrome とは近い結果が得られるはずです。

テストに使用したプログラムは、以下の通りです。

package webgltest;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage stage) throws Exception {
    WebView webview = new WebView();
    webview.getEngine().load("http://callumprentice.github.io/apps/storm_tracks_webgl/index.html");
    System.out.println(webview.getEngine().getUserAgent());
    
    AnchorPane root = new AnchorPane();
    root.getChildren().add(webview);
    
    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.setTitle("WebView Test on JavaFX 9");
    stage.show();
    
  }

  public static void main(String[] args) {
    launch(args);
  }

}

そして実行結果がこちら。

webgl-javafx9.png

ロード画面から先に進みません。WebGL 対応とか全然できていません。ダメダメです。

一応、UserAgent の値を見ておきます。

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/604.1 (KHTML, like Gecko) JavaFX/9 Safari/604.1

いったい JavaFX 8 からどのくらいアップデートされているの? と疑いたくなったので、先ほどのテストプログラムを JDK 8 Update 152 で動かしてみました。結果はこちら。

webgl-javafx8.png

こちらは想定通りですが、UserAgent の値が...これ、どう思います?

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/604.1 (KHTML, like Gecko) JavaFX/8.0 Safari/604.1

以上です。