//rich client / パート1 JavaFX in Spring COMMUNITY クライアントでSpringフレームワークを使用する理由

STEPHEN CHIN avaでサーバー・サイドの開発 して、Springなどの依存性管 は、アプリケーションが大規模で複 イン・ユーザーの認証用モジュー BIO Jを行ったことがある開発者で 理フレームワークでそれらの 雑であればあるほど、得られるメリッ ル、SpringのRestTemplateを IN ACTION あれば、Javaエンタープライズ モジュールの関係をインジェク トも飛躍的に増します。 使用したバックエンドのWebサー Stephen Chin Webアプリケーションの構築や強 ション で き ま す 。 本記事では、実際のアプリ ビス統合機能、ロール別の適切な (@steveon java) 化のためにSpring Framework ■■ 1行で記述できるWebサービ ケ ー ション の 中 で こうし た メリッ 権限に基づく作成/削除操作が含 オラクルの Java の何らかの要素を使用した経験 ス̶クライアントとサーバーで トを実証するために、Spring まれます。アプリケーションの最終 Technology があるのではないでしょうか。 互換性のあるRESTフレーム FrameworkとJavaFXを組み合 的な外観は図1のようになります。

Ambassador。 Spring Frameworkには、強力な ワークを利用することで、同じモ わせたアプリケーションとして、フ 全2回のシリーズを通してこの JAVA TECH JavaFX の代表的技術文 依存性注入(DI)システム、Web デル・オブジェクトを再利用し、 ロ ント エ ンド・コン ポ ー ネ ント と バッ サンプルを完成させていきます 献である Pro JavaFX 版 の モ デ ル・ビ ュ ー・コ ント ロ ー ラ データの取得、作成、削除、更新 クエンド・コンポーネントの両方 が、GitHubではすでにサンプル 2(Apress、2012 年) (MVC)フレームワーク、さらには を行うWebサービスの呼び出し を含む顧客データアプリケーショ の完全なソースコードを閲覧でき を共同執筆。Devoxx、 データベース・アクセスからセキュ を1行の文で実装できます。 ンを一から構築します。この顧客 ます。また、ダウンロードして実行 CodeMash、OSCON、 リティ認証制御までのあらゆる機 ■■ 認証と認可̶クライアント上で データアプリケーションには、ログ することも可能です。 J-Fall、GeeCON、 能に対応するヘルパー・ライブラリ の認証/認可機能を一から開発 ABOUT US JAZOON、JavaOne が含まれています。 するのではなく、サーバー要求 など多くのJavaカンファ 一方、JavaFXでは2.xリリース のセキュリティ保護に使用して レンスで取り上げられ、 でPure Java APIが提供され、 いるものと同じ認証メカニズム Rock Star アワードを 2 SpringのようなJavaライブラリ を利用できます。また、詳細な 度受賞。 の統合が非常に容易になりまし 認可テストを行って、権限に応 た。Spring Frameworkをクライ じてUIの外観や操作性を変更 アント上で利用した場合、次のよ することもできます。 うなメリットがあります。 非常に単純なアプリケーション ■■ UIの制御の反転̶制御の反転 の場合、これらの機能によって得ら (IoC)は、タスクの実行をその れ る メ リ ッ ト は 、新 し い ラ イ ブ ラ リ の タスクの実装から切り離すた 学習や統合にかかるコストを大き め に 用 い ら れ る オ ブ ジ ェクト 指 く上回るほどではないかもしれま blog 向の技法です。UIの場合、IoC せん。一方で、複数の画面で構成さ はスタンドアロン・モジュール れ、バックエンド・サーバーへの接続 の作成に非常に便利です。スタ やユーザーの認証を伴う大規模な ンドアロン・モジュールを作成 アプリケーションを構築する場合に 図1 35

ORACLE.COM/JAVAMAGAZINE NOVEMBER/DECEMBER 2012 //rich client / LISTING 1 アプリケーション・テンプレート 者が考慮する必要はありません。一方、 public class CustomerApp extends Application { Springを基盤としたサーバー・サイドの アプリケーション・スレッドに対しては少し COMMUNITY public static void main(String[] args) { 開発に関わったことがある方は、Spring 注意が必要です。 launch(args); を使用する新規アプリケーションの設定 JavaFXでアプリケーション・コードを } が簡単であることをご存じでしょう。JAR 呼び出す場合は、startやstopといった ファイル(またはMavenの依存関係)を アプリケーションのメソッド内であろうと @Override 追加し、web.xmlファイルにコードを数 イベント・ハンドラ内であろうと、その呼 public void start(Stage stage) throws Exception { 行追加するだけです。 び出しは必ずアプリケーション・スレッド ApplicationContext context = 一方、クライアントでは、メイン・クラス 上で実行されます。そのため、アプリケー new AnnotationConfigApplicationContext JAVA IN ACTION から手動でSpringランタイムを起動す ション側で新しいJavaFXオブジェクト CustomerAppConfiguration.class); る必要があります。本項で作成するアプ を安全に作成して、シーン・グラフを自由 ScreensConfiguration screens = context. リ ケ ー シ ョ ン・テ ン プ レ ー ト に は 、ス レ ッ ド に操作できます。ただし、アプリケーショ getBean(ScreensConfiguration.class); セーフの状態でJavaFXランタイムと ンをメイン・スレッドで実行する場合や、 screens.setPrimaryStage(stage); Springランタイムを起動する方法が示 独自のスレッドを生成する場合は、描画 screens.loginDialog().show(); されています。 ツリーに影響を及ぼすJavaFXのメソッ }

その前にまずは、スレッドセーフにする ドを呼び出さないように注意してくださ } JAVA TECH 理由を理解するために、JavaFXのスレッド い。呼び出した場合は、例外やデッドロッ に関する背景情報を少し確認しましょう。 クが発生することや、さらに悪い結果に JavaFXには、目的の異なる2種類の つながることもあります。 Download all listings in this issue as text スレッドがあります。 リスト 1(CustomerModel.java) ■■ アプリケーション・スレッド̶JavaFX は、CustomerAppデ モ・プ ロ ジ ェ クト のシーン・グラフに対するすべての操 の メ イ ン・ア プ リ ケ ー シ ョ ン・ク ラ ス で す 。 定義できる利便性があるだけでなく、 ンドウを使用するJavaFXオブジェクト ABOUT US 作と、トップレベル・ウィンドウを使用す JavaFXアプリケーション・スレッドの初 SpringのXMLベース設定で実現される を作成した場合は、この問題を示す例外 るオブジェクトの作成を行うスレッド。 期化や、JavaクラスからのSpring設定 強力な機能や容易なデバッグ処理もそ が発生します。一方、リスト1のstartメ Swingのイベント・ディスパッチ・スレッ のロードを行っています。 のまま活用できるためです。本記事のサ ソッドはJavaFXアプリケーション・スレッ ドに相当します(ただし、同じスレッド startメソッドの手前までは、定型的な ンプルではアノテーションベースとXML ド上で呼び出されます。そのため、任意 というわけではないため、Swingとの JavaFXアプリケーションに非常に近い ベースの設定、両方のスタイルを組み合 の型のJavaFXオブジェクトを安全に作 相互運用のためのコードでは注意して コ ード で す 。startメソッドでは、Springの わせて宣言しています。アプリケーション 成し、それらのオブジェクトをSpring設 く だ さ い )。 ApplicationContextを初期化していま の目的に応じて、こういった組み合わせ 定内からでもシーン・グラフに追加でき ■■ 描画スレッド̶表示するシーンを準備 す。その際、Java設定を使用する場合は た方法も便利です。。 ます。 するために、グラフィックが変化するた 新しいAnnotationConfigApplication アプリケーションのメイン・メソッド内 リスト 1 のサンプルでは、Screens びに呼び出されるスレッド。グラフィッ Contextを作成し、XMLからロードす でSpringのコンテキストを初期化した Configurationというサブ設定クラ クの変化としては 、アニメーション/ る場合はClassPathXmlApplication くなるかもしれませんが、これは非常に スをロードし、その設定オブジェクトに CSS/レイアウトの処理、シーン・グラ Contextを作成します。 危険です。Springのコンテキストをロー stageを 設 定 し て 、ロ グ イ ン・ダ イ ア ロ blog フと描画ツリーの同期、マウス・ホバー ここでは、Spring Framework 3.0 ドした場合に、Springを起動したスレッ グ・ボックスを表示するメソッドを呼び出 の状態の更新などがあります。 で新たに導入されたアノテーションベー ドにJavaFXのオブジェクトがロードさ しています。 ほとんどの場合、描画スレッドはシー スのJava設定サポートを利用すること れる可能性があるからです。Stage、 ンのバックグラウンドで実行され、開発 を強くお勧めします。コード内で設定を Popup、Menuなどのトップレベル・ウィ 36

ORACLE.COM/JAVAMAGAZINE NOVEMBER/DECEMBER 2012 //rich client / LISTING 2a LISTING 2b DIによるUIのモジュール化 体で1つのみ存在します。 @Configuration 以上でSpringをロードできるようになり また、設定クラス全体に対して@Lazy COMMUNITY @Lazy ました。次にSpringの一部の機能を利 アノテーションを指定しています。その public class ScreensConfiguration { 用して、JavaFXアプリケーションをモ ため、それぞれのBeanは初回のアク private Stage primaryStage; ジュール化します。この顧客データアプリ セス時まで作成されません。ただし、@ ケーションは最終的に次の画面で構成さ Lazyアノテーションを指定しただけで public void setPrimaryStage(Stage primaryStage) { れます。 は、アプリケーションの起動時にBeanが this.primaryStage = primaryStage; ■■ ログイン画面 作成されないことを保証するためには不 } ■■ データ表示画面 十分です。複数の画面の間に直接リンク JAVA IN ACTION ■■ エラー画面 がある場合は、最初の画面がロードされ public void showScreen(Parent screen) { ■■ 「顧客の追加」画面 た際に、他の参照先の画面もすべて連鎖 primaryStage.setScene(new Scene(screen, 777, これらの画面は、それぞれ別個の 的 に ロ ード さ れ ま す 。 500)); JavaFXクラスまたはFXMLファイル 全画面が一度にロードされないよ primaryStage.show(); として実装します。また、他の画面の参 うにするには、リンクする画面の参照 } 照(ナビゲーションを行う場合)とモデル をインジェクションするのではなく、

(データ・アクセスやデータの更新が発 ScreensConfigurationクラスの参 @Bean JAVA TECH 生する場合)も必要になります。さらに、 照を渡します。この方法によって、別の CustomerDataScreen customerDataScreen() { 最初の利用時に画面が作成され、かつ、 ScreensConfigurationインスタンス return new CustomerDataScreen(customerDataScreen Controller()); 画面ごとに一度に1インスタンスしか保 を設定して実装を入れ替えるという柔軟 } 持しないようにします。 性を確保しながら、特定の画面をロード リスト 2 a と 2b( Screens す る メ ソ ッド が 呼 び 出 さ れ る ま で オ ブ ジ ェ @Bean Configuration.java)は、各画面をそ クトの作成を遅らせることができます。 CustomerDataScreenController customerDataScreenCon- ABOUT US れぞれ別個のBeanとして定義する モデルおよびWebサービス troller() { Spring設定クラスです。 に関するその他の設定は、別 return new CustomerDataScreenController(this); ScreensConfigurationファイルで の ク ラ ス・フ ァ イ ル に 定 義 し ま す } は、@Beanアノテーションを使用して、 (CustomerAppConfiguration. 各画面および関連コントローラを別個の java、リスト 3 参照)。このクラス @Bean Beanとして定義しています。また、一部 では、アノテーションを使用して @Scope("prototype") のBean(本記事のサンプルでは、ダイ ScreensConfigurationを ロ ードし て FXMLDialog errorDialog() { アログ・ボックスを表示するBeanのすべ います。 return new FXMLDialog(errorController(), て )を @Scope("prototype")アノテー getClass().getResource("Error.fxml"), primaryStage, ションを使用して定義しています。これ FXMLへのコントローラのインジェク StageStyle.UNDECORATED); により、インスタンスを取得しようとする ション } たびに新しいインスタンスが作成されま 前項では複数の画面を、Javaクラス・ blog す。一方、メインのデータ表示画面のス ファイルまたはFXMLとして定義しまし コープはデフォルトの" singleton"です。 た。Springによって初期化されたコン そのため、メソッドを何回呼び出したとし トローラをJavaオブジェクトに割り当 Download all listings in this issue as text ても、メイン画面はアプリケーション全 てることは非常に簡単ですが、同様の 37

ORACLE.COM/JAVAMAGAZINE NOVEMBER/DECEMBER 2012 //rich client / LISTING 3 LISTING 4 LISTING 5 LISTING 6 LISTING 7 し、その中で、パラメータとして @Configuration 渡されたコントローラを返して COMMUNITY @Import(ScreensConfiguration.class) います。 @ImportResource("classpath:applicationContext-security. このようにコントローラを作 ") 図2 成してインジェクションするテ public class CustomerAppConfiguration { ク ニ ッ ク に よ っ て 、コ ン ト ロ ー @Bean コントローラをFXMLに割り当てること ラがSpringで管理される他のあらゆる CustomerModel customerModel() throws IOException { は、JavaFX 2.0リリースでは不可能で オブジェクトと同様に扱われます。その CustomerModel customerModel = new CustomerMod- した。しかし、JavaFX 2.1リリースで 結果、DIや「Autowiring」(自動関連付 el(); JAVA IN ACTION は、この問題を解決して各種IoCフレー け)などのフレームワークの機能を利 customerModel.setRestTemplate(restTemplate()); ムワークに対応するためのAPIが追加 用できます。ErrorControllerのソース・ customerModel.loadData(); されました。ここでの各種IoCフレーム コ ード 全 体 をリスト 6(ErrorController. return customerModel; ワークには、コンテキストと依存性の注入 java)に 示 し ま す 。ま た 、基 底 イ ン タ } (CDI)、Guiceなどのほか、言うまでも フェースのDialogControllerはリスト 7 なくSpringも含まれます。 (DialogController.java)のとおりです。 @Bean

例として 、ErrorDialogの定義を詳し 本記事のFXML UIはSceneBuilder RestTemplate restTemplate() { JAVA TECH く見てみます。ビューとコントローラは を使用して作成しました。 RestTemplate restTemplate = new RestTemplate(); 両方ともScreensConfigurationクラ SceneBuilderは、JavaFXの各種コン restTemplate.setMessageConverters Collections.>singleton ス内で作成されます。クラスを作成する ポーネントについて学習し、UIのモック List( コ ード をリスト 4 に示します。 アップを簡 単に作 成 できる優 れたビジュ new MappingJacksonHttpMessageConverter())); errorControllerが、FXMLDialogク アル・ツールです。作成した最終的なエ return restTemplate; ラスに依存関係としてインジェクション ラ ー・ダ イ ア ロ グ・ボ ッ ク ス は 図2のように } ABOUT US されていることにお気づきでしょうか。 なります。 } FXMLDialogは、FXMLファイルのロー ド・ロ ジ ッ ク と コ ント ロ ー ラ・オ ブ ジ ェ クト まとめ のインジェクション・ロジックをまとめて 本記事では、SpringとJavaFXを組み合 カプセル化したカスタム・クラスです。 わせて使用するアプリケーションのテン FXMLDialogのソース・コード全体をリ プレートを紹介しました。このテンプレー スト 5(FXMLDialog.java)に 示 し ま す 。 トは各自のプロジェクトで再利用できま Download all listings in this issue as text FXMLDialogクラスは、FXMLファ す。Springの設定とDIを利用するだけ イルを新しいダイアログ(Stage)とし で、Pure Javaでの開発を基盤としたア てロードするために通常必要となるコー プリケーションの設計上のメリットが得ら ス な ど 、サ ン プ ル・ア プ リ ケ ー シ ョ ン の 残 ドの一部を一般化したものです。特に、 れます。 りの部分を構築します。