Java EE にバグはあるのか?

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

そもそも Java EE にバグはあるのか?

Java EE API 仕様・実装ともにバグは存在します。API 仕様に問題があるケースは珍しいですが (Java EE 7 は一度だけ仕様の改訂が行われています)、API 実装のバグは絶え間なく発生しています (基本的にオープンソースなので、各プロジェクトの Issue Tracker を見ればわかります)。多くのバグはレアケースでのみ発生するもので、修正が遅れたり、あるいは修正自体が行われなかったりしますが、比較的多くの環境で再現するものについては重点的にリソースが割かれ、早期に修正されます。ただし、新しいバージョンの API 実装をいつアプリケーション・サーバーに取り込むかについては、各ベンダーの裁量に委ねられます。ということで、Java EE にバグがあるかないかで言えば「ある」が正しいです。

まずはアプリケーション・コンフィグレーション・オペレーションを疑え!

サポートをリクエストする側とそれに答える側の双方を経験してわかったことですが、システムでトラブルが発生した場合、最初に疑うべきものはアプリケーション、コンフィグレーション、オペレーションの 3 つです。開発中のシステムであればなおさらのことです。Java EE API やアプリケーション・サーバーは様々なユーザーが各々異なった環境で使用しているため、最新安定版であればメジャーなバグは解決されています。システムはそこまでテストされていないため (SIer では単体テストとノード内結合テストについては異常なまでに緻密なテストを行いますが、ノード間結合テストやシステムテストについてははっきり言ってザルです)、個別に構築した部分の方が多くの問題を抱えていると考えるのが自然です。

システムのトラブルと言っても、それはアプリケーションのバグであったり、コンフィグレーションのミスであったり、あるいは不適切なオペレーションに起因するものだったりします。これらはいずれもシステム開発の現場で解決できるものですので、問題を切り分けて可能な限り原因を追究します。その上で Java EE 側の問題だろうと判断した場合には、次のステップへと進みます。

Java EE にバグがある場合の対応について

Case 1 : アプリケーション・サーバーがオープンソースの場合

オープンソースのアプリケーション・サーバー (GlassFish、WildFly、Tomcat、TomEE、Payara、Open Liberty、etc.) を使用している場合、以下のいずれかで対応します。

  • Issue Tracker に登録して、解決されるまで待つ
  • 有償サポートが提供されるのであれば、それを利用する
  • 自力で直す
  • あきらめる

実を言うと、最も現実的な選択肢は「あきらめる」です。これがオープンソースの現実です。オープンソースを甘く見ないでください。

一般的に推奨されている (と思われる) Issue Tracker への登録はぜひ行って欲しいことではありますが、それだけで問題が解決するとは思わないでください。定期的にリリースを確約している Payara や、年中リリースを繰り返している Tomcat であれば、ある程度は期待しても良いですが、それでも提供時期については保証されません。

オープンソースであれば、自力で直すことも可能ではあります。ただし、あなたや同僚が Java EE API (あるいはアプリケーション・サーバー) の実装に精通していることが絶対条件になります。自ら修正したビルドの品質は誰も保証してくれません。

Payara と TomEE に関しては、それぞれ有償サポートが提供されていますので、素直にサポート契約をすれば OK です。ただし、オープンソースのアプリケーション・サーバーを「無料だから」採用するシステムが大半ですので、この選択は難しいかと思います。

OSS サーバー「私で費用削減するのは構わないけど私との可能性は感じないでほしい」

Case 2 : アプリケーション・サーバーが有償製品の場合

プロプライエタリなアプリケーション・サーバー (WebLogic、WebSphere)、オープンソース系有償アプリケーション・サーバー (JBoss EAP、WebSphere Liberty、Payara、TomEE) を使用している場合、以下のいずれかで対応します。

  • 有償サポート契約があればサポートをリクエストする
  • あきらめる

日本国内では、主に代理店の販売チャネルを利用してこれらの製品を導入します。有償サポートについても代理店が窓口を持っているため (日立、CTC、富士通、NEC、etc.) そちらと契約します。Oracle、JBoss、Payara などはベンダー直販もあり、そちらを利用した場合はベンダーと直接有償サポート契約を結ぶことになります。

サードパーティーの窓口は、最終的にはベンダーへ問い合わせることになるだろうから中間マージンを取られるだけでは? と思われる方がいらっしゃるかもしれませんが、彼らにはベンダーから提供される内部情報に加えて独自の情報網を持っていますので、その点を考慮すると費用に見合った価値は提供されると考えてよいでしょう。(代理店経由では多くの場合ディスカウントが効きますので、サポート費用を上乗せしてもベンダーの標準価格を下回ることさえ...)

ベンダーの窓口は、一般的には開発チームと直結していてレスポンスが速いというイメージがあるものの、サポートチームと開発チームの連携の程度についてはベンダーによりまちまちであるため、一概には言えません。また、ベンダーの日本法人窓口は開発チームと直結していないことが多々あり、例えば Oracle のサポートは最高レベルの優先度をつけてサポート・リクエストを送ると、日本オラクルのサポート窓口を経由せず直接米 Oracle Corporation の専用窓口につながる体制となっています (昔、Oracle Solaris 11 の GNOME (GUI) の不具合でカッとなって P1 で SR 送ったら米国窓口から「今回は答えるけど二度とやるな」と怒られたことがあります)。

たまに手違いで有償サポート抜きで製品を買ってしまった、というケースがあるのですが (私は Oracle Database 9i でやらかしました)、気付き次第購入した代理店に相談するか、それができない場合 (例: サポート窓口を持たない純粋な販売代理店) はベンダーの窓口に連絡して直接サポート契約を結んでください。特にプロプライエタリなアプリケーション・サーバーをサポートなしで使用することは自殺行為に等しいです。

有償サポートを使えば、ほとんどの不具合は何とかしてくれます。どのベンダーも有償サポート契約者専用のアップデート版 (一般公開版に先行して不具合修正が実施されます) を用意していますし、緊急の対応を要望すれば専用のパッチを作成してもらえるかもしれません。

Payara と TomEE はオープンソースですがオプションで有償サポート契約も付けられるため、無理をせず素直に有償サポート契約を結ぶことをお勧めします (これは宣伝ではなく一般論です)。自力での調査及び対応にかかる費用 (概算で 100~150 万円/人月) と、有償サポート費用を比較すれば、どちらが有利かわかると思います。

Java EE にバグがある場合のアンチパターン

けなす

最終的に誰も得をしないのでやめましょう。けなした本人が、けなした直後だけ気が晴れるだけです (経験則)。

少しクールダウンした後、ブログ等で不具合の情報 (前提、事象、発生頻度) を共有しましょう。オープンソースのアプリケーション・サーバーを使用しているのなら、Issue Tracker での報告も忘れずに。

個別の API 実装の Issue Tracker に報告する

安定版で発見されるバグの多くは、複数の API が連携した時に起こる事象です。また、Jersey (JAX-RS リファレンス実装) と Weld (CDI リファレンス実装) のように本質的に連携時の相性が良くない実装もあります。特に最近の Java EE はあちこちに CDI が顔を出しますので、単独の API で発生する事象と断定できないケースが多々あります。CDI は賢い面とシビアな面を併せ持った API なので、使い方をちょっと間違っただけでプログラムは正しく動作しなくなります (WELD-001408 とかもう見たくない...)。それは CDI と連携する API 実装にとっても同じこと。

個別の API 実装の Issue Tracker に報告しない方がいい理由は、いくつかあります。

  • 当該 API の実装に関する理解が不十分な人が多い。特に複数 API の連携時に発生するバグをきちんと説明できない (意味不明な Issue は無視される)。
  • オープンソースのアプリケーション・サーバーの場合、サーバー側の Issue Tracker に報告した方が回答を得やすい。少なくとも再現可能であることを示せば反応は得られる。
  • プロプライエタリのアプリケーション・サーバーの場合、個別 API の採用についてはベンダーがすべて握っているため、仮に個別の API 側で修正してもらえても取り込んでもらえる保証がない。そもそも、ベンダー側で API 実装のカスタマイズを行っている可能性もある。

なお、単独でも利用可能 (≒ Java SE 上から実行可能) な API で、かつ単独利用時に発生したバグについては、この限りではありません。

GlassFish に何かを期待する

問題切り分けとしてリファレンス実装 GlassFish での挙動を見る行為は、現状ではやめておいた方が得策です。Java EE の TCK は通せても、アプリケーションを動かせるとは限りません。代わりに Payara を使いましょう。

無理な問題解決を行う

これは SIer で、かつウォーターフォール・モデルで開発している場合に発生しやすいのですが、設計書 (Excel 方眼紙で書いたアレ) の記載を絶対視して、Java EE のバグを踏んでしまった際にも設計書通りに動作するよう試行錯誤しながらトリッキーなコードを組み上げていくことがあります。こうしたコーディングはバグが直った途端に動かなくなることが多いです。SIer はアプリケーション・サーバーのバージョンアップを敬遠しがちですが、セキュリティ・フィックスについては別で、たまたま当該のバグ修正が同時に行われていると、その時点で詰みます。Java EE のバグだと分かったら、素直に設計書を修正して設計レベルでバグを回避しましょう (こういうことがあるからウォーターフォール・モデルはやめろと言っているのですが...)。