Good-bye EJB, Hello CDI – Java EE Advent Calendar 2015

This is for the “Java EE Advent Calendar 2016” event material among Japan. Thanks for using auto translator for English. 

Java EE アドベントカレンダー2015の12月23日分です。寺田さんの記事からの続きになります。

※注: 内容がエンタープライズ開発の中核方面に寄っているので難度高かなという気がします。

今年のJavaOne 2015ではキーノート発表に日本人として超久しぶりに登壇させてもらったり去年に引き続きセッションを一枠喋ったりとなかなかのプレッシャーでしたが、なんとか無事終わりほっと一息、なんて余裕が全くないのですが、そんなことより個人的にショックなことがあったのでそれを書きます。

こういう記事が雑誌(そもそも消えてしまった)や日本語商用技術サイトに載らなくなったってのが、多分日本全体の技術力の低下&乗り遅れの証なんだろうなと思いつつ、日本語で情報発信しなくなった私も元凶の一人かもしれないですね。が、個人的に日本語で発信する意味が全くない(私はSIerでもベンダーでもない)ので、逆に来年のAdvent Calendarは多分英語で書いてる気がしています。

さよならIIOP

ショックだったのがこれ。JCPに加入しているので仕様策定の状況を見てた訳ですが、IIOPが遂にJava EE 8からオプショナル扱いになるかもしれない、という話題が急遽入ってきた訳です。で、最近使ってないからいいんじゃねパーフェクト、みたいなノリでガンガン話が進んでいくわけです。

で、Java EEを丸17年間ほぼフルで使ってる私としては、おいおいちょっと待った、と。使ってない輩が勝手に仕様を削るなよと。使ってる側の話を聞いたのかよと。とまあそんな感じをまとめて私も投稿するわけですが焼け石に水。一人で世界は変えられないのでした。

で、多分IIOP (アイアイオーピー)って何よ?とほぼ10人に9人が謎に思うと思うので改めて。ざっくり言うとIIOPはCORBA仕様の通信部分のGIOPをTCP/IP互換にしたものなんですが、それはどうでも良くて、最も重要な部分はXAに対応してるJava EE内唯一の汎用通信プロトコルなわけです。RMIとの互換性を持たせてるのでRMI-IIOP (アールエムアイ・オーバー・アイアイオーピー)という仕様になってます。WebLogicではそれを更にラップしてT3 (ティースリー)という高機能プロトコルが提供されてます

で、次にXAって何よ?の回答なんですが、JDBCにXA対応、ってのがあるのでそれで気付く人が居たら嬉しいのですが、分散トランザクションの標準プロトコル、ってのがざっくり回答でしょうか。要は、複数のシステムに跨がってACIDトランザクションを制御できるってものです(ACIDはぐぐってね)。複数システムで処理する内容があったとして、どこかでエラーが起きたら複数台丸ごとロールバックできるという素敵仕様です。金融系処理には欠かせない処理、と言えばなんとなく想像付くでしょうか。お金情報が壊れたら嫌ですよね。ある日突然増えてたりとか減ってたりとか。

このXAはTuxedoや日立のOpenTP1などで1990年代後半に一世を風靡するのですが、まあそれをWebLogicがサポートして、J2EE 1.2の標準仕様に盛り込まれ、金融系システムに2000年代前半に広まっていくというサクセスストーリーな訳です。私もだいぶお手伝いさせて頂きました。

で、IIOPをオプショナルにするとなると、アプリケーションサーバーとしては標準としてサポートしなくても良くなるわけで、三大Java EE商用アプリケーションサーバーであるWebLogic, WebSphere, JBossのどれかが将来にサポートを外してくる恐れがあるわけですね。こいつぁ困った。ということでJavaOneで直談判に行ってきました。

さよならEJB

でまあいろんな偉い人とディスカッションしていくわけですが(仔細は割愛。言えないこととかも沢山出てきた気がするので)、そこで追加で分かったのは、やっぱりEJBも将来無くなりそう、ということでした。あーやっぱり・・・時代はCDIなのです。

個人的にはEJBこそがJ2EE–>Java EEの華であり中核であり、WebLogic 3.0からEJBを使ってきた身からすると大変寂しい話ではあります。が、やはりEJBは機能がてんこもり過ぎて、必用な分だけ能動的に選択できるCDIは時代の要請でもあります。

で、Java EE 7のCDI仕様を見ると、EJBでサポートされてるけどCDIでサポートされてない機能がまあ沢山あります。どこからEJBでどこからCDIかさっぱり分からんというところもありますが、両方で使えるもの、という意味だとざっと考えて・・・

  • 既にサポートされてるもの(両方で使える)
    • 自動トランザクション制御 (@Transactional)
    • SOAP通信 (@WebServices)
    • REST通信 (@GET, @PUT)
    • JPA系制御
  • まだサポートされてないもの(EJBでしか使えない)
    • インスタンスプーリング
    • セキュリティー制御
    • 呼出のJNDI登録・参照
    • Message-Driven Bean (みたいなJMSサーバー側簡易機能)
    • Singleton Bean (みたいなSingletonパターン機能)
    • EJB Timer (みたいな時間制御)
    • IIOP通信 (EJB Remote) + XA制御 (with IIOP)

※Entity Beanは?とか聞かないで下さいね・・・もう無いです

と見ていくと、「まだサポートされてない」ものの中で落とされていくものがなんとなく色分けされていきます。どれが落とされるか分かりませんけど、少なくともIIOP+XAは当確な感じになって参りました。あーあ。

でまあ、そんなに後ろ向きだと生きるのが辛くなるし代替技術も無いので、しゃーないですなと気持ちを切り替え、XA使わないアーキテクチャーに変えていけばいいんじゃね?という方向にシフトしていく訳です。そもそもXAは完璧ではない(in-doubt windowとかあるし)ので、この方向もアリはアリです。

但し、現在動いているシステム群は一体どうするのよ?という疑問も当然あります。Webスタートアップ系の単一システムならまだしも、例えば金融系はアホみたいにシステムがある(数百から数千規模)のが普通なので、それをひとつにしていくというのも何となく無謀な感じもします。書いてると絶望感しか沸いてこない・・・で、唯一の方策というのは、製品利用企業が正しく声を上げてベンダーにIIOPをサポートさせ続けるということでしょう。プレッシャーかけていきましょう。

こんにちはCDI

さて、悩み深いリアル金融系システムはさておき、大半の利用側はCDIバンザイな気がします。配備時に実装クラスを自動生成&コンパイルして動作するEJBに対して、単純に機能がインジェクトされて動作するCDIの方が、エラー発生時も分かりやすいですし、何せテストがやりやすい。

あとは現在EJBから移行されてない機能が恐らくJava EE 8〜9で追加されていくはずなので、それを待てばEJBがこの世から消える算段ができ、初学者はCDIだけ勉強すればあとはJSFもJPAもOKな幸せな世界になると思います。そう考えてCDIに仕様を移してきているので当然です。

CDIそのものの説明は既に大量にあるので省きますが、EJB特にSession BeanからCDIに移行するために何が必用か、というところだけ補足しておきます。

Session BeanからCDIへの移行はアノテーションの一括置換で概ね行けます。ざっくりとこんな感じと考えればいいでしょうか。

EJB Session Bean CDI
Class宣言箇所 @Stateless @Named
@Dependent
@Transactional
EJB呼出し箇所 @EJB @Inject

他を言い出すとあれやこれやありますし、EJB Remoteどうすんの(=移行先が無いので削ってアーキテクチャー変更)とか沢山有りますけど、こんな感じでの基本移行パターンを考えておく必要があるかと思います。

さてそろそろ長くなってきたので結論ですが、次の世代のEJB (特にSession Bean)は以下の書き方になっていくことでしょう。ただ、現在のJava EE 7だと機能が足りなさすぎる気もするので、ご自身のソフトウェア特性に応じて使いこなしましょう。ツールに踊らされるのは本末転倒です。

@Named
@Dependent
@Transactional
@Path
public class AnBusinessLogic {

    @Inject
    private NextBusinessLogic theLogic;

    @Inject
    private ThirdBusinessLogic thirdLogic;

    @POST
    @Consumes("application/json")
    @Produces("application/json")
    public AnReturnValue theMethod(AnParam param) throws BusinessException {
        // Check param values.
        AnReturnValue result = new AnReturnValue();

        // Call other logics to operate.
        result.theResult = this.theLogic.businessMethod(param);

        result.thirdResult = this.thirdLogic.otherBusinessMethod(param);

        return result;
    }

    ....
}

明日12/24の回はhondaYoshitakaさんの番です。Merry christmas and a happy new year!