いざStrutsからJSF 2へ! 移行における最大のポイントは?──最新Java EE開発“虎の穴” 第2回 岩崎浩文氏

Oracle Java & Developers編集部
2013-12-16 11:00:00
  • このエントリーをはてなブックマークに追加

StrutsとJSF 2は画面遷移の仕組みが異なる。それを理解すれば移行で戸惑うことはない

──Java EE 6への移行で最大の難所は、StrutsからJSF 2に作り返る部分なんですね。それはなぜでしょうか?

 StrutsからJSF 2への移行に手が掛かる理由は、両者の設計思想が大きく異なるからです。


※クリックすると拡大画像が見られます

 Struts 1を、アプリケーションを構成する画面の単位で見ると、各画面は「画面を表示するJSPファイル」、「JSPタグに対応するTaglib」、「テキスト・フィールドなど画面内のHTMLフォームに対応するAction Form(もしくは、XMLで定義されたDyna Action Form)」で構成されます。そして、それぞれの入力項目はAction Formのフィールドと1対1でひも付くという構成になります。

 そして、画面を遷移させる際には、HTMLフォームのSubmitボタンなどに対応したActionクラスを呼び出すわけですが、Strutsでは、例えばボタンが2つあるときには、それぞれに対応したActionクラスを用意します。

──画面単位でまとまっている部分と、そうではない部分があるんですね。

 そうなのです。これに対して、JSF 2ではStrutsのActionFormに相当するクラスとしてBacking Bean(Managed Beanの一種)を作り、画面はテンプレート・エンジンのFaceletsで実現します。


※クリックすると拡大画像が見られます

※クリックすると拡大画像が見られます

 Faceletsでは、入力項目が2つ、Submitボタンが2つある場合、Backing Beanには入力項目に対応した2つのフィールドと、Submitボタンに対応した2つのメソッドを作ります。つまり、FaceletsとBacking Beanは1対1対応で作るのが絶対条件となります。このように作らないと、いずれ破綻してしまうのです。

 そして、このように作るために、Backing Beanのセッション・スコープをViewScopedに設定します。これはJSF 2で導入されたもので、ASP.NETのCode Behind※1と同様のことを実現できる便利なスコープです。ViewScopedにすることで、この画面とのセッションが有効な間は、フィールドの情報が保持されます。つまり、ボタンをクリックすると、入力されたidとpasswordの値がセットされた状態でメソッド(submit1とsubmit2)が呼び出されるわけです。これはポストバック※2という仕組みで実現されています。

※1 各Webページにおいて、デザイン用のHTMLタグとロジック・コードを明確に分離するために導入された機構。

※2 画面で入力されたデータを、その画面自身にポストする(ポストバックする)ことで、セッションを通じてデータを保持し続ける仕組み。

──JSF 2では、すべてを画面単位で作るのですね。

 そうなんです。では、こうした仕組みのJSF 2にStrutsベースのアプリケーションを移植する際、どういった点に注意すべきかをお話ししましょう。

 まず、データを保持するAction Formの内容をBacking Beanのフィールドに移植しなければなりませんが、この部分はほとんど同じなので苦労はないでしょう。また、Actionクラスのメソッドexecuteは、Backing Beanのメソッドとして移植します。ボタンが2つある場合は、2つのメソッドexecuteを移植することになります。以上で画面そのものの移植は完了です。


※クリックすると拡大画像が見られます

※クリックすると拡大画像が見られます

 次に、画面遷移の部分を移植しますが、JSF 2の画面遷移の仕組みはStrutsとは異なります。StrutsからJSF 2への移行では、ここが山場になります。

 JSF 2アプリケーションにおける画面遷移を画面単位で考えると、遷移先となるのは、次の画面に相当するFaceletsとBacking Beanの組み合わせです。ここで、例えば最初の画面でSubmit1ボタンがクリックされたら(メソッドsubmit1が呼び出されたら)、次の画面(Facelets)が呼び出されるとしましょう。しかし、スコープにViewScopedを設定したBacking BeanはFaceletsと1対1でひも付くため、実はそのままでは次の画面に入力データを渡すことはできません。


※クリックすると拡大画像が見られます

 それでは、どうやってデータを渡すのかというと、javax.faces.context.FlashというMap型のオブジェクトを使います。これは画面を1つ遷移する際に、その瞬間だけ使えるオブジェクトです。前の画面でこのFlashにデータをセットして、次の画面に遷移が移ると、画面が表示される前にFlashオブジェクトにアクセスし、次の画面のBacking Beanが最初に呼び出されたとき(@PostConstructアノテーションが付加されたメソッドが呼び出されたとき)に、Flashオブジェクトから取得したデータをBacking Beanのフィールドにセットするのです。JSF 2では、こうした仕組みによって画面遷移を実現します。

──Strutsとは画面遷移の仕組みがまったく異なるのですね。

 ええ、設計思想がまったく違うのです。

 以上をまとめると、Strutsでは画面遷移を制御するActionクラスが画面とは独立に存在し、これが入力データを格納したAction Formからデータを読み取って次の画面に渡します。

 それに対して、JSF 2では1画面ごとに画面(Facelets)とクラス(Backing Bean)がセットになっており、次の画面に遷移したとき、そのままでは前の画面で入力されたデータを読み込むことはできない。そのため、Flashオブジェクトを使ってデータの受け渡しを行います。ちなみに、データの受け渡しにRequestスコープが使えそうだと思われるかもしれませんが、JSFの画面遷移では、ポストバックの後にリダイレクトがかかって次の画面に遷移するため、Requestスコープを使った場合はデータが破棄されてしまいます。Backing Beanを使って画面間でデータを受け渡すには、Flashを使うしかないのです。


※クリックすると拡大画像が見られます

 StrutsとJSF 2との間には、画面遷移に関してこのような違いがあります。このポイントを説明した記事は、書籍でもオンラインでも、あまり見かけないのですが、ここを理解して取り組めば、移行作業で大きな混乱が生じることはないでしょう。

──読者の皆さんにも、今回ご説明いただいたポイントを踏まえ、Java EE 6への移行をスムーズに進めていただきたいですね。岩崎さん、ありがとうございました。

【関連記事】

PaaSといっても、何を検討すればよいのか、違いがわからない…という方へ、Oracle Cloudの概要セミナーを開催!

オラクルのパブリッククラウドの成り立ちや代表的なサービス、価格体系等のクラウドサービスの基本情報から、具体的な活用事例までご紹介します。

最新のJavaを3時間で知る!Java解説セミナー

  • 日時:2014年4月17日(木)
  • 場所:オラクル青山センター

株式会社 構造計画研究所の菊田 洋一氏登壇