Java EE とは何か?

この記事は Java EE Advent Calendar 2017 の初日です。まず Java EE とは何か、について考えたいと思います。技術的なことはあまり出てこないので退屈かもしれませんが、重要なことではあるので今しばらくお付き合いください。

Java EE とは何か?

Java EE とは、Java プラットフォームを用いて業務システムを構築する上でよく利用される機能を、ライブラリまたはフレームワークの形で標準化したもの、と考えればよいでしょう。もう少し具体的に表現すると、Java EE は以下の 2 つの役割を担うものと言えます。

  • いわゆる「車輪の再発明」を防ぎ、開発生産性を向上させる
  • ベンダー中立なオープン・スタンダードである

オープン・スタンダードの重要性

2 点目はとても重要です。身の回りを見てみると、オープン・スタンダードにあふれています。例えば、プリンタ用紙。日本では ISO が定めた A 版と呼ばれる一連のサイズ、中でも A4 サイズが多く使われます。日本の官公庁が A4 を書類の標準サイズとして採用し、ほとんどの企業がそれに追従しています。実寸では 210mm × 297mm です。もし、プリンタ用紙のサイズが規格化されていなかったとしたら? 封筒、ファイル、郵便受け、etc. のサイズを決めるのに何を基準にすればいいかわからなくなります。今は A4 が標準サイズですから、それを基準にサイズを決めればよいわけです。用紙自体も基準となるサイズが分かっていれば大量生産できます (当然、値段も抑えられます)。標準でないサイズ、例えばアメリカやイギリスで多用されるレターサイズやリーガルサイズは、A4 サイズに近いですが寸法がやや異なります。レターサイズの書類は A4 サイズ用の封筒やファイルには収まりませんし、リーガルサイズの用紙を日本国内で手に入れようにも近所の事務用品店には置いていないことの方が多いです。A4 サイズは世界中の国々が認める ISO という標準化組織が決めた規格で、誰でも 210mm × 297mm の用紙を作成して A4 サイズと称することができますし、規格がコロコロ変わることもありません。Java EE が真のオープン・スタンダードかと言うと若干異なる点もありますが、基本的にはオープン・スタンダードです。

オープン・スタンダードは、規格制定に多くの利害関係が絡むことから、立案から最終案確定まで時間がかかります。Java EE も例外ではなく、特に近年では幹事役の Oracle がきちんと仕事をしなかったことから、規格のアップデートに過大な時間を費やした挙句、当初予定よりも規模を縮小せざるを得ない状況が続いていました。その点、単独のベンダーが開発したフレームワークの方が改善のスピードが速く、一見すると多くのニーズに応えられるように思われます。しかし、そうしたフレームワークはいわゆる「ベンダー・ロックイン」の温床となりがちで、十分な市場シェアを獲得した後にベンダーの好き勝手に改変される恐れがあります。最悪なケースは、突然の開発中止でしょう。一方、オープン・スタンダードな Java EE は、仮にベンダーのうち 1 社が抜けたとしても、残った他のベンダーが支えるため、そう簡単には潰れません。事実、Oracle は Java EE を放棄して Eclipse Foundation に擦り付け移管することに決めましたが、IBM、Red Hat、Payara といったベンダーが結集して Eclipse Enterprise for Java (EE4J) プロジェクト傘下での再建が始まっています。Oracle が主導しなくても他のベンダーが後を引き継いでくれる、オープン・スタンダードならではの安心感です。

本稿執筆時点では、EE4J 内で "Java" や "javax.*" パッケージの使用について揉めて議論されています。

車輪の再発明を防ぐ

Java EE の主要な機能の中でも、JavaServer Faces と Java Persistence API は車輪の再発明を防ぐ意味で重要です。他の機能も同様ですが、特にこの 2 つを挙げたいと思います。

JavaServer Faces (JSF) は、端的に言うと、Web システムの画面を Visual Basic 風に組み立てるためのフレームワークです。Web システムは元来、HTTP のリクエストとレスポンスのやりとりで組み立てるものですが、JSF は HTTP 通信を隠ぺいして Visual Basic のようにボタンやリストといったコンポーネントを組み合わせて画面を構成します。Visual Basic 等の画面はコンポーネントがそれぞれ状態を持っていますが (例: リストの 3 番目が選択されている)、HTTP は一対のリクエスト・レスポンスで完結し状態を保持しないプロトコルであるため、HTTP 通信を隠ぺいしてコンポーネント・ベースの画面を作るのは大変な労力が必要です。JSF はそれを一手に引き受け、プログラマーは画面に配置するコンポーネントに注力すればよいことになります。最終的には実現しませんでしたが、JSF には GUI によるビジュアル・プログラミング環境を整備して、RAD のように使えるようにする計画もあったと聞きます。

JSF の対案として、画面を JavaScript (ECMAScript) だけで構成し、Java EE のバックエンドと Web サービスで連携する設計手法もあります。多くの場合、RESTful Web サービスが採用され、Java EE の該当機能である Java API for RESTful Web Services (JAX-RS) が利用されます。JAX-RS は Java EE の数ある機能の中でも特に優れたもので、あと数年早く JAX-RS が登場していれば Ruby on Rails が普及することはなかったとさえ言われています。この案が有力視されているのは、近年 JavaScript のフレームワークが強力になり、サーバー側のサポートなしで画面を構成できるようになってきたためです。

Java Persistence API (JPA) は、データベースと Java のデータ構造をマッピングする役割を果たします。現在はリレーショナル・データベースとのマッピングが対象ですが、将来は他のデータベースにも対応するかもしれません。データベースと Java とでは、同じデータを保持する場合でもデータ構造が異なります。リレーショナル・データベースはリレーショナル代数に基づいてデータを扱いますが、Java は List (動的配列) や Map (連装配列) 等でデータを保持します。本来であれば両者の変換をプログラミングしなければなりませんが、JPA ではデータ構造を Java 側に合わせ、必要に応じてデータベース側とのデータ変換を行ってくれます。感覚的には、Java 側でデータを設定するとデータベースが更新され、Java 側でデータを取得するとデータベースの問い合わせが行われます。実際のところは、データベース側の変更はデータの問い合わせが発生する直前まで遅延させることが可能で、複数回データを更新しても最終的な更新結果がデータベースに反映されていれば問題ありません。この更新の遅延をうまく使えば、データベースのアクセス回数を減らし、アプリケーションのパフォーマンスを向上させることができます (JPA ではさらにキャッシュ・メモリも規定されています)。また、一般的にデータベースへの問い合わせには SQL を使用しますが、SQL は標準規格は存在するもののほとんどのベンダーが標準に従っていない、名ばかりの標準です (SQL 標準化が遅れている間にベンダー各社が独自に SQL を拡張したのが大きな原因です)。JPA では JPQL という形で SQL に関する「車輪の再発明」を行っています。これはあまり良い方法とは言えないでしょうが、SQL をそのまま使用するとデータベースごとに問い合わせ文が異なってしまうため、ポータビリティの観点からやむを得ず JPQL を導入したと考えるのが妥当でしょう。これは個人的な見解ですが、SQL の標準化が徹底されていれば JPQL を導入せずに済んだはずです。こうした泥仕事を一手に引き受けているのが JPA です。JPA のような仕組みは「O/R マッピング」と呼ばれ古くから存在するデータベース・アクセスの抽象化手法ですが、フレームワーク乱立を抑制する意味でも JPA の存在は重要になっています。現在では古くからの O/R マッピング・フレームワークの多く (TopLink、Hibernate 等) が JPA に準拠するようにアップデートされています。

Enterprise JavaBeans ― Java EE の光と影

Java EE と言えば、Enterprise JavaBeans (EJB) を思い浮かべる方も多いでしょう。古くからの開発者にとって、EJB は触れたくないものかもしれません。確かに昔の EJB は複雑怪奇でしたが、現在は非常にシンプルなビジネスロジック用の便利機能に変貌を遂げています。

EJB が生まれたのは、ちょうど分散コンポーネントがもてはやされていた時期です。Microsoft の COM (ActiveX) は色々な意味で有名ですね。Java には黎明期から Remote Method Invocation (RMI) というクラスのリモート呼び出し機能があり、これにトランザクション管理等を組み合わせて「再利用可能」なコンポーネントを作成するためのフレームワークが EJB でした。この頃の分散コンポーネントは EJB に限らずどれも複雑で、通信プロトコルも独自のため、不具合発生時にトレースしづらい等の欠点がありました。EJB では特にその複雑さが叩かれ、Dependency Injection (DI) コンテナのようなより軽量なフレームワークに取って代わられてゆきます。

EJB もこうした現状を踏まえて、Java EE 5 から DI コンテナとしても動作するよう改良され、プログラミング・スタイルも非常にシンプルなものになりました。Java EE 6 からは本格的な DI コンテナを志向した Contexts and Dependency Injection (CDI) が導入され、Java EE 7、Java EE 8 とアップデートを重ねるごとに Java EE における比重が EJB から CDI へシフトしています。EJB はいずれ CDI に取って代わられるでしょうが、それにはもう少し時間がかかりそうです。

EJB は時代に合わせて生まれ、時代に合わせて変化しましたが、かつての悪評はいまだ払拭しきれていません。

これからの Java EE

2017 年 9 月、Java EE の最新アップデートである Java EE 8 がリリースされました。しかし、大幅な開発遅延と機能縮小で登場した Java EE 8 に対する評価は微妙で、特に国内の Java コミュニティは冷淡でした。JavaOne や Deboxx 等、海外のカンファレンスでは Java EE 8 に関するセッションがそこそこあったようですが、国内のカンファレンスでは完全にスルーされ、新規システム開発における Java EE の採用も激減しているようです。

現在、Java EE は EE4J プロジェクトに移管されつつあり、よりオープン・スタンダードな規格として再出発しようとしています。それまでに日本国内で Java EE の灯が消えないようにしたいという思いから、今年の Java EE Advent Calendar を始めたいと思います。