17454 words
87 minutes
Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築

Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築#

Chapter 1 Java EEの基礎知識#

1.1 Java EEのこれまで#

  • 1995年 Sun Microsytems,Inc

    • JDK1.0 α版
  • 1998年 Sun JPEと呼ぶプロジェクトを立ち上げ

    • サーバー側の企業アプリケーション開発にJavaを利用できるようにするために立ち上げ
  • 1999年12月 フレームワーク提供(J2EE 1.2)

    • 10個の機能から構成
      • JSP+Servlet → 急速に普及
      • EJB
  • 2001年 J2EE 1.3

  • 2003年 J2EE 1.4

    • XML対応
  • このころ、オープンソースのフレームワークも台頭

  • 2006年5月 簡単開発(Ease of Development)をテーマに、名前を改名

    • Java Platform Enterprise Edition(JavaEE)と改め新バージョンをリリース
    • Java EE 5
      • 普及には至らず
      • 改善をすすめる
  • 2009年12月 JavaEE5をさらに大幅改善したJavaEE6をリリース

    • CDI
    • プロファイル:全仕様に対するサブセットを提供
    • プルーニング:使われなくなって古くなった使用を整理するための仕組み
    • → ミッションクリティカルな企業システムでも採用されるようになった

1.1.3 Java EE 7 へ --- 3つのテーマ#

  • JavaEE6のリリース後、すぐに次期バージョンの検討

    • 目をつけたのは「クラウド」
    • より簡単にJavaEEアプリケーションをスケールするような機能を考え、GlassFishというアプリケーション・サーバー上で実際に動作するサンプルも作成
      • 外部からのフィードバックやスペックリードが集まって再検討した結果次期が早いと判断し見送り
  • Column JavaEE7 におけるクラウド対応の見送り

    • 2012年8月12日 開発の遅れと、仕様化に対する十分な経験、検討が足りなかったため見送りを決定
    • 期待があった分失望の声もあったが
    • 有識者やベンダーの多くはこの決断を支持
  • 新しいテーマを考えた

    • HTML5対応
    • 開発用意/生産性の向上
    • エンタープライズニーズへの対応

1.2 Java EEの全体像#

  • Java EEに含まれる機能の全体像を把握してください

  • JavaEEは企業システムのアプリケーション開発に必要なさまざまな機能を1つにまとめた包括仕様(umbrella specification)の総称

  • 大小さまざまな39個の仕様から構成されています。

  • 主に

    • インテグレーションテクノロジー
    • ビジネスロジックテクノロジー
    • プレゼンテーションテクノロジー
      • を組み合わせながらシステムを構築する
  • インテグレーションテクノロジー

    • 外部システムと連携するための機能を提供
    • 外部システム
      • データベース
      • メールサーバー
      • メッセージングプロバイダ(OpenMQ,WebShereMQ)
      • エンタープライズ情報システム(ERP,メインフレーム)等がある
  • ビジネスロジックテクノロジー

    • 外部システムと連携するプログラムの実装とユーザーインターフェースのプログラムの実装の間に入り、企業システムの業務で必要とされる処理を実装
      • トランザクションの処理や業務のフローの実装など
  • プレゼンテーションテクノロジー

    • 様々なデバイスからアクセスされることを考慮する必要がある
    • 人だけでなく、物も含め、企業システムに対してアクセスするためのインターフェースを提供

1.2.2 Java EEに含まれる機能#

  • Java Persistence API(JPA)

    • ORM機能
    • JavaSEでも利用可能
  • Java Messagge Service(JMS)

    • 外部のメッセージングプロバイダを経由して非同期でテキストメッセージやバイナリメッセージを送受信
    • JavaSEでも利用可能
  • Batch Applications for the Java Platform

    • データをまとめて一括処理する場合に利用
    • JavaSEでも利用可能
  • Java Mail API

    • 電子メールクライアントを作成するために必要な機能を提供
  • Java EE Connector Architecture(JCA)

    • EAIを行うために必要な機能を提供
  • DI/CDI

    • JavaEEに含まれる技術を疎結合で結び合わせるための技術
  • Enterprise JavaBeans(EJB)

    • もともと、分散コンポーネントを作成するための技術として作られました
    • JavaEE5以降、EJBはビジネスロジックを簡単に実装するための技術として大きく生まれ変わりました
    • XMLの設定は不要で、クラスに対して宣言的に定義できるようになっています。
  • Java Transaction API(JTA)

    • トランザクション管理を行うための技術
  • JavaServer Pages(JSP), JSP Standard Tag Library(JSTL)

    • JSPは動的ページ作成
    • JSTLは、ページ内のループ処理やSQLを使用したデータベースアクセスなど、JSPで共通する機能を隠蔽して利用できるようにした専用タグ
      • JSFの導入以降は徐々に置き換えが進む
  • JSON-P

    • JavaEE7から新たに導入されたJavaEEでJSONを扱うための機能
    • 次期バージョンでは、JSONデータとJavaオブジェクトをマッピングするJSON Bindingの提供も予定されている
      • → もう対応されている?
  • Expression Language(EL)

    • 簡単な式や変数などを用いて、記述内容の評価が行える言語として作られました
  • Servlet

    • ServletのプログラムはServletコンテナ(Webコンテナとも呼ばれる)と呼ばれる実行環境上でどうsあ
    • HTTP/1.0及び1.1のリクエストに応答する
    • ServletはHTTP処理に対する低レベルAPIしか提供しないため、現在はServletのAPIだけでプログラミングを行う場面は少ない
    • JSFのようなServletコンテナ上で動作する上位フレームワークへ処理を以上するための仲介役として利用されることが多い
  • WebSocket

    • HTTPプロトコルをアップグレードした、双方向/全二重通信が可能なプロトコル
    • HTTPと比べてメッセージ送受信の際のオーバーヘッドが少ないため、効果的にリアルタイムメッセージの送受信ができる
  • Java API for RESTful Web Services(JAX-RS)

    • RESTアーキテクチャに基づいてWebサービスを実装するための機能を提供
    • 従来、Webサービスの実装にはSOAP Webサービス(JAX-WS)とXMLを用いるのが主流だった
    • 現在は、分散システム間連携を行うために、RESTful WebサービスとJSONを組み合わせて実装する場面が多くなっている
    • JAX-RSの仕様は、HTTPの仕様と密接に関連しており、HTTPメソッドに対応するアノテーションを用いて処理を実装する
      • JAX-WSからJAX-RSへと主流が変わってきたことを理解した
  • JavaServer Faces(JSF)

    • コンポーネントベースで開発が可能なWebアプリケーション開発フレームワーク
    • 画面は、フェースレット(Facelets)と呼ばれるXHTML形式のテキストファイルに、HTMLタグやJSF専用タグを記入してデザイン
    • バックエンドの処理はマネージドビーン(Managed Bean)と呼ばれるPOJOクラス、もしくはCDIクラスで処理を実装
    • JSFは標準でHTML5やAjaxへも対応しており、Javascriptの知識がなくても簡単にAjaxプログラミングが行えます
  • ビーンバリデーション

    • データの整合性を検証するための機能
  • Common Annotation

    • JavaEE5でMetadata facility for Javaという機能が追加された
    • これに関連して、JavaSE環境、JavaEE環境の両方で共通して利用可能なアノテーションが定期された
    • 例えば
      • インスタンスの生成時、破棄時になんらかの処理を行うことを規定したもの
      • 処理に対する実行権限を規定したもの
      • データベース設定を規定したもの
    • これらのアノテーションを利用して宣言的にプログラミングを行う
  • Managed Bean

    • Common Annotationの中に、Managed Beanというアノテーションがある
    • JavaEE環境で管理されているBeanであることが明示される
    • Managed Beanは、アプリケーション・サーバーで管理されているリソースの参照や、インスタンスのライフサイクル管理ができる
    • 通常、Managed Beanのアノテーションを付加したクラスを実装することはほとんど無い
      • しかし、Managed Beanの機能を持つ上位機能(CDI、EJB)でManaged Beanの機能を利用する
  • Interceptors

    • 複数の機能間で横断的な関心事の実装を行うための機能です。
    • 例えば
      • ログの出力や各処理時間の計測、セキュリティの検査などは、特定部分の実装に限らず、システムの全体で必要な実装
  • Concurrency Utilities for Java EE

    • JavaEE環境で新たにスレッドを生成するための機能
    • JavaEE6まではサーバー環境上で新たなスレッドを生成することは非推奨でした。なぜならば、作成されたスレッドがアプリケーション・サーバーから管理できないスレッドとして動作するためでした
    • たとえば
      • セキュリティ情報や、トランザクション情報、コンテキスト情報などを一切含まないため、アプリケーション・サーバーから制御することは不可能
    • そこで、サーバーが管理できるスレッドを作るために、JavaEE7からConcurrency Utilities for Java EEが新たに導入された

1.2.3 Java EE の仕様策定#

  • Javaの仕様はJCP(Java Community Process)という団体で管理

    • Java Specification Requests(JSR)と呼ぶ仕様のリクエストに対して、一意の番号を割り当てて管理している
  • JSRをJCPに提出するために必要な成果物について記載(割愛)

1.2.4 Java EEの実行環境とプロファイル#

  • 割愛

1.3 Java EEアプリケーション開発の基本#

1.3.1 Java EEアプリケーションモデル#

  • 3階層アプリケーションの開発モデルを採用している
    • ビジネスロジックとユーザーインターフェースを切り分けて実装することが大事
    • 柔軟性の高いシステムを構築していくことが大事

1.4 開発環境の準備#

  • サンプルアプリケーション
    • JavaSE8
    • JavaEE7
    • GlassFishv4.1.1 (JavaEE参照実装)

1.4.1 Oracle JDKのインストール#

1.4.2 NetBeansのインストール#

1.4.3 NetBeansの起動#

1.5 サンプルアプリケーションの概要#

1.5.1 ナレッジバンク#

  • 個人が保有する知識情報(ナレッジ)を共有するためのWebアプリケーション

  • JavaEE7で一般的なWebアプリケーションを実装するために必要な機能を使用して構築されている

  • 画面遷移などの説明

1.5.2 ナレッジバンクのセットアップ#

  • プロジェクトを読み込み

1.6 まとめ#

  • この章のまとめを記載(割愛)

Chapter 2 プレゼンテーション層の開発――JSFの基本#

  • 以下の3層に分けて開発を行う
    • プレゼンテーション層
    • ビジネスロジック層
    • インテグレーション層

2.1 JSF概要#

2.1.1 JavaSErver Faces(JSF)とは#

  • JSFとはJavaEE5から追加されたプレゼンテーション層を作成するための仕様

    • 今まではServletを使用していた
      • サーブレットとは:ブラウザとHTTP通信を行う基礎的な仕様で、最小限の機能を提供
        • 入力値とJavaオブジェクトのマッピング
        • 入力値のチェック
        • エラーメッセージのハンドリング
          • など多くの機能が不足していた
  • Column MVC1.0

    • 次のバージョンのJavaEE8には、「MVC1.0」というプレゼンテーション層を開発する新しい仕様が加わる予定
    • Webアプリケーションを開発するフレームワークには、HTTPの通信に紐付けて処理を記述するアクションベースのフレームワーク
    • 入力フィールドやボタンに紐付けて処理を記述するコンポーネントベースのフレームワークがある
    • 本書で記述するJSFはコンポーネントベースのフレームワーク
    • そのため開発者から、アクションベースの選択肢も必要という意見があがり、JavaEE8でアクションベースのフレームワークである「MVC1.0」を追加することになった

2.2 JSFの構成要素#

2.2.1 画面と処理(フェースレットとマネージドビーン)#

  • フェースレットとは

    • 画面レイアウトを記述するXHTMLベースのテンプレートエンジン
    • XHTMLとは、HTMLをXMLの文法に適合するように定義し直したもの
  • フェースレットとBeanがどのように紐付いているかを確認

  • Column マネージドビーンとバッキングビーン

    • フェースレット似バインドするJavaクラスはマネージドビーンといいますが、
    • フェースレットの裏側で処理を行うという意味で、バッキングビーンと呼ばれることもあります。
    • マネージドビーンがCDIでも代用できるようになった頃からJSFで使用するマネージドビーンをバッキングビーンと呼ぶことが多くなった

2.2.2 マネージドビーンとスコープ#

  • スコープ:マネージドビーンのデータをいつまで保有するかを指定する

  • スコープの一覧の紹介

2.3 JSFの画面遷移#

2.3.1 画面遷移の方法#

  • JSFで次の画面に遷移する場合、遷移先の名前を文字列で指定

    • この画面遷移に使用する文字列を「outcome値」といいます
    • 遷移するフェースレットのパスを指定
  • 静的な遷移

    • マネージドビーンの処理を行わずに直接次の画面に遷移する方法
  • 動的な遷移

    • マネージドビーンで処理を行い、その結果を基に任意の画面へ遷移する方法
    • EL式でメソッドをバインドしている

2.3.2 画面のリダイレクト#

  • 画面遷移

    • フォワード:処理後に直接Web画面を生成して結果を返す
    • リダイレクト:一度ブラウザに処理を返した後にサーバーに再アクセスしてWeb画面を生成する
  • JSFではリダイレクトを使用して次の画面に遷移する方法を提供している

    • 1画面前のURLを表示することを避けるためにこの機能を提供
      • ?faces-redirect=trueというパラメータを付与すると動くらしい
    • 問題:リクエストスコープが効かなくなる
      • 対策:フラッシュスコープという特別なスコープを提供している

2.4 JSFの内部処理#

2.4.1 コンポーネント指向#

  • JSFではWebアプリケーションをより直感的に開発するためにコンポーネントという考え方を導入している

  • メリット

    • Web画面と処理の紐付けを直感的に行える(HTTPの理解が不要)
    • コンポーネントが再利用しやすい
    • Web画面のプロトタイプ作成が容易に行える
  • コンポーネントツリーとしてアクセスできるJavaクラスが存在するらしい

2.4.2 ライフサイクル#

  1. ビューの復元(Restore View)
  2. リクエスト値の適用(Apply Request Values)
  3. 入力チェック(Process Validations)
  4. モデル値の更新(Update Model Values)
  5. アプリケーションの実施(Invoke Application)
  6. 画面の生成(REnder Response)
  • 最初のアクセスの場合
    • ①の復元フェーズ終了後に、⑥の画面生成フェーズに進み、画面を表示
  • ポストバックの場合
    • すでにコンポーネントツリーがあり、値の入力やボタンの操作が実施されているので、
    • ①→⑥まで順番に実施

2.5 JSFの基本設定#

2.5.1 フォルダ構成#

  • JSFを使用したWebアプリケーションを作成するにはWAR形式のプロジェクトを作成

  • EAR形式もある

    • 複数のWARファイルやJARファイルを1つにまとめてZIPにしたもの

2.5.2 設定ファイル#

  • 必要な設定ファイル

    • web.xml
    • faces-config.xml
    • アプリケーションサーバーの設定ファイル
  • web.xml

    • デプロイメントディスクリプタというWebアプリケーションの設定を記述するファイル
      • webアプリケーションの初期設定
      • サーブレットの設定
      • セキュリティの設定
    • WebアプリケーションでJSFを使用する場合は、web.xmlにJSFが提供するFacesServletを設定
  • サーブレットの定義

    • JSFは内部でサーブレットを使用している
    • そのためJSFを使用するにはJSFのサーブレット指定が必要
    • ロードオンスタートアップの指定はサーバーの起動時にサーブレットのインスタンス化と初期化を行うという指定
  • サーブレットのマッピング定義

    • URLパターンとサーブレットの定義で指定したサーブレット名を指定
    • URLパターンは「/faces/*」という指定がJSFでは一般的らしい
    • facesで始まっている場合に、JSFのアクセスであるとみなされる
  • faces-config.xml

    • JSFの設定を記述するファイル
      • 国際化のせてい
      • フェーズリスなのクラス指定など
  • アプリケーション・サーバー用の設定ファイル

2.5.3 リソースフォルダ#

  • JSFの仕様でresourcesフォルダに配置するフォルダ構成が決められているらしい
  • resouces/[ローカルプレフィックス]/[ライブラリ名]/[ライブラリバージョン]/[リソース名]/[リソースバージョン]
    • →わかりにくいと感じた

2.6 フェースレットタグライブラリ#

2.6.1 タグライブラリの種類#

  • タグライブラリ

    • 画面レイアウトで使用するタグを定義したもの
  • 種類

    • コアタグライブラリ:他のタグライブラリのサポート的な機能を提供するタグライブラリ
    • HTMLタグライブラリ:HTMLのタグを生成するタグライブラリ
    • フェースレットテンプレーティングタグライブラリ:画面のテンプレート処理や繰り返し処理などを提供するタグライブラリ
    • コンポジットコンポーネントタグライブラリ:コンポジットコンポーネントの作成に使用するタグライブラリ
    • JSTLコア/ファンクションタグライブラリ:JSPで使用するタグライブラリ
  • 最も使用頻度が高いのは「HTMLタグライブラリ

  • JSTLコア/ファンクションタグライブラリ:JSPというJavaEEの仕様で使用するライブラリでJSFでも使用できるが、他のフェースレットが提供するタグライブラリとの実行タイミングが違うため不具合が発生しやすく、基本的に利用しない

  • ※ここで再確認

    • JSF
      • フェースレット
        • フェースレットタグライブラリ
        • EL式
      • マネージドビーン
  • タグライブラリを利用するには、冒頭でネームスペースの宣言が必要

2.6.2 HTMLタグライブラリ#

  • 一覧を表で記載(割愛)

2.6.3 ヘッダーとボディ#

<h:head> <h:body>

2.6.4 リソース#

2.6.5 文字の出力#

2.6.6 リンクとボタン#

(割愛)

2.7 EL(Expression Language)#

2.7.1 ELとは#

  • ELとは、演算の結果や値の参照結果を返却するための簡易記法
  • #または、$で始まり、波括弧で囲んだ中に式を記述
    • $を使用した場合:ページがレンダリングされた時点で即時評価
    • #を使用した場合:コンポーネントに式として渡され、ライフサイクルのタイミングで遅延評価される
      • JSFでは基本的に$を使用せずに、#を使用する

2.7.2 オブジェクトの参照#

  • @Namedを付与したマネージドビーンの名前はEL式から参照できる

2.7.3 暗黙オブジェクト#

  • 暗黙的に参照可能なオブジェクト一覧を記載(割愛)

2.7.4 演算子#

  • 算術演算子
  • 関係演算子
  • 論理演算子
  • 三項演算子
  • 空演算子
    • empty a : aがNullまたは空文字の場合trueを返す

2.7.5 メソッドの呼び出し#

  • メソッドも呼び出せるよって言う説明(割愛)

Chapter 3 プレゼンテーション層の開発――JSFの応用 その1#

3.1 入力チェック#

3.1.1 入力チェック(バリデーション)とは#

  • JSFのライフサイクルの中にある
  • JSFでは入力した値をチェックする機能を提供している
  • バリデーションの方法として以下の2つを提供
    • JSFの初期から提供されているJSFのバリデーション
    • JavaEE6で導入されたビーンバリデーション★

3.1.2 JSFのバリデーション#

  • バリデーションタグを利用する(割愛)

3.1.3 JSFのカスタムバリデータ#

  • 細かなチェックをするために独自でバリデータを作成する方法
    • メソッドを作成する方法
    • クラスを作成する方法

3.1.4 ビーンバリデーションとは#

  • ビーンのフィールドにアノテーションを付与するだけでチェックができる

3.1.5 ビーンバリデーションのバリデータ#

  • ビーンバリデーションのアノテーション一覧

    • @NotNull
    • @Null
    • @Max
    • @Min
    • .....
  • point: 入力値が空文字の場合NULL値として扱う場合、web.xmlにパラメータを追加する必要がある

    • javax.faces.INTERPRET_EMPTY_STRING_SUBMITED_VALUES_AS_NULL

3.1.6 ビーンバリデーションのエラーメッセージ変更#

  • メッセージを変更する方法は2つある
    • アノテーションに、message属性を指定する
    • propertiesファイルで管理する
      • 多言語対応などする場合、こちらが得策

3.1.7 ビーンバリデーションのバリデータ統合#

  • MEMO: ★このテクニックは覚えておきたい
  • 入力チェックに複数の条件がある場合には、フィールドに標準のアノテーションを複数設定するが、同じような条件を何度も設定するのは面倒なので、アノテーションを作成してまとめる

3.1.8 ビーンバリデーションのカスタマイズバリデータ#

  • ビーンバリデーションのカスタマイズも可能
    • MEMO:(実装方法省略)

3.2 コンバータ#

3.2.1 コンバータの役割#

  • Web画面に表示する文字列とマネージドビーンのプロパティで保持するJavaのオブジェクトを変換するための仕組み

  • JSFにより自動的に変換されるオブジェクトも存在する

    • short
    • int
    • long
    • float
    • double
    • boolean
    • byte
    • char
    • BigInteger
    • BigDecimal
  • JSFでは任意のフォーマットで画面表示を行うため、標準のコンバータを提供している

3.2.2 標準のコンバータ#

  • JSFが標準で提供するコンバータは、日付や数値とおじ列を相互に変換するコンバータ
    • f
    • f

3.2.3 カスタムコンバータ#

  • 独自で作成したクラスなどの標準のコンバータでは対応できないクラスでは、独自にコンバータを作成する

    • JSFが提供するjavax.faces.convert.Converterインターフェースを実装したクラスを作成する
  • MEMO: 確かに変換が必要な場面は絶対あるはずなので、thymeleafとかがどのように変換を持っているか確認する

  • MEMO: DBSlectした結果をList(category)にかかえているような書き方をしている

3.3 コンポーネントのカスタマイズ#

  • JSFではフェースレットが提供するコンポーネントを使用してWeb画面を作成
  • 独自のコンポーネントを作成することもできる
  • 方法として2つある
    • コンポーネントクラスを作成するカスタムコンポーネント
    • フェースレットでコンポーネントを組み合わせて作成するコンポジットコンポーネント★

3.3.1 コンポジットコンポーネント#

  • 1つのフェースレットファイルを作成するだけで、複数の画面で使い回せるコンポーネントを作成することができる
    • MEMO: thymeleafでincludeしている感じと同じ

3.3.2 より高度なコンポジットコンポーネント#

<!-- テンプレート側 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:knowledge="http://xmlns.jcp.org/jsf/composite/knowledgecomp">
<h:head>
<meta charset="UTF-8" />
<h:outputStylesheet library="css" name="style.css" />
<h:outputScript name="jsf.js" library="javax.faces"/>
<h:outputScript library="js" name="application.js" />
<title>Knowledge Bank</title>
</h:head>
<h:body>
<div id="top_content">
<h:form id="form">
<h1><h:graphicImage library="img" name="logo.png" /></h1>
<div class="notice">
#{flash.notice}
</div>
<knowledge:login userId="#{loginBean.userId}" password="#{loginBean.password}" loginButtonAction="#{loginBean.login()}"/>
<div>
<h:link outcome="account/register" value="アカウント登録"/>
</div>
</h:form>
</div>
</h:body>
</html>
<!-- 利用する側 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:knowledge="http://xmlns.jcp.org/jsf/composite/knowledgecomp">
<h:head>
<meta charset="UTF-8" />
<h:outputStylesheet library="css" name="style.css" />
<h:outputScript name="jsf.js" library="javax.faces"/>
<h:outputScript library="js" name="application.js" />
<title>Knowledge Bank</title>
</h:head>
<h:body>
<div id="top_content">
<h:form id="form">
<h1><h:graphicImage library="img" name="logo.png" /></h1>
<div class="notice">
#{flash.notice}
</div>
<knowledge:login userId="#{loginBean.userId}" password="#{loginBean.password}" loginButtonAction="#{loginBean.login()}"/>
<div>
<h:link outcome="account/register" value="アカウント登録"/>
</div>
</h:form>
</div>
</h:body>
</html>
  • Column: コンポーネントで利用可能な暗黙オブジェクト
    • カスタムコンポーネント内でよく利用する暗黙オブジェクト
      • cc: コンポジットコンポーネントの情報が取得できる
      • component: 現在のコンポーネントの情報や、親や子のコンポーネントの情報にアクセスすることができる

3.4 フェースレットテンプレート#

3.4.1 フェースレットテンプレートの利用#

  • ヘッダーやサイドバーなどはテンプレート化して管理する説明
    • こっちがthymeleafのincludeに近い

3.5 HTML5フレンドリマークアップ#

  • JavaEE7(JSF2.2)からHTML5の進化へ対応するためにフレンドリマークアップという機能が導入された
    • 以前のJSFでは任意の属性をHTMLとして出力する場合にコンポーネントをカスタマイズして提供していた
  • 画面デザインをWebデザイナーが行い、リッチなWeb画面を作ることが一般化

3.5.1 パススルーアトリビュート#

3.5.2 パススルーエレメント#

3.6 Ajax#

3.6.1 JSFのAjax対応#

  • 一般的なAjaxの作りでは、データの取得処理や画面の再描画処理をJavascriptで記述する必要がある

  • JSFのAjax機能を利用するとJavascriptをほとんど記述せずにWeb画面の部分更新が可能

  • Ajax専用のタグを使用して、結果をRenderingしている

  • MEMO: 専用のタグでAjax処理ができるのは、コンポーネントベースのフレームワークであるJSFの特徴だと感じた

3.6.2 Ajaxを使用した入力チェック#

3.6.3 Ajaxのイベントハンドリング#

  • イベント実行中や完了、エラー発生時の処理を記述するための方法
  • 共通化するための方法を紹介

Chapter 4 プレゼンテーション層の開発――JSFの応用 その2#

4.1 認証/認可#

4.1.1 認証/認可の仕組み#

  • JavaEEのログイン機能を実現するための認証認可の仕組みについて

  • ログイン機能を利用する手順

    1. アプリケーションサーバーの認証/認可設定をする。
    2. アプリケーションの認証/認可設定をする。
    3. プログラムでログイン/ログアウト機能を作成する。

4.1.2 アプリケーションサーバーの認証設定#

  • アプリケーション・サーバーに認証の設定を行う必要がある

    • 認証データの指定先に
      • ファイル
      • データベース
      • LDAPサーバー などを指定する
  • ナレッジバンクではデータベースを指定している

  • Glasfishを使用した認証の設定方法を説明

  • Glasfishの管理コンソール

    • http://localhost:4848/
  • 認証設定を行うには

    • Configurations>server-config>Security>Realms>New
  • ナレッジバンクではJDBCレルムを使用するので

    • ClassNameにJDBCRealmを選択する

4.1.3 アプリケーションの認証設定#

  • アプリケーションサーバーの認証設定が終了したら、
  • 今度はアプリケーションの認証設定を行う

4.1.4 ログイン/ログアウト機能の作成#

  • Oracle18cで接続を試していたがどうしてもうまく行かなかった

  • Oracle11gだとすぐにうまく行った

  • ログインの仕組みを作って、

  • 実際にloginのfaceletでコンテキストのログインメソッドを呼び出して、認証を済ませる

    • MEMO: springsecurityみたいなやつ 認証設定は必ず実装しておく

4.2 国際化#

4.2.1 JSFの国際化#

  • プロパティファイルでロケール管理して、faces-config.xmlで切り替え
  • UIViewRootクラスのgetLocaleメソッドやsetLocaleメソッドでも切り替えることができるみたい
    • MEMO: ロケール切り替えは実装しておくべき

4.3 ブックマーカビリティ#

4.3.1 ブックマーカビリティとは#

  • JSFでは最初にブラウザからアクセスが来た際に、処理をせずに画面を表示する

  • しかし、Webアプリケーションでデータの一覧や詳細を表示する画面では、なにかしらの事前処理やデータの取得処理が必要

    • そこで、JSFでは初回アクセス時に処理を実施する機能を提供している
  • 使い方について説明(割愛)

4.4 フェーズリスナ#

  • JSFのライフサイクル

    1. ビューの復元(Restore View)
    2. リクエスト値の適用(Apply Request Values)
    3. 入力チェック(Process Validations)
    4. モデル値の更新(Update Model Values)
    5. アプリケーションの実施(Invoke Application)
    6. 画面の生成(REnder Response)
  • フェーズ前後で横断的に行う処理はフェーズリスナを使用する

package knowledgebank.web.listener;
import java.util.logging.Logger;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
public class KnowledgePhaseListener implements PhaseListener {
Logger logger = Logger.getLogger(KnowledgePhaseListener.class.getName());
@Override
public void beforePhase(PhaseEvent event) {
logger.info(event.getPhaseId() + " beforePhase");
}
@Override
public void afterPhase(PhaseEvent event) {
logger.info(event.getPhaseId() + " afterPhase");
}
@Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}

4.5 Java EE 7で導入されたJSFの機能#

4.5.1 JSF 2.2 の追加機能#

  • JSF2.2の仕様には大きな特徴として以下の4つが紹介されている
    • HTML5フレンドリマークアップ(パススルーアトリビュートと、パススルーエレメント)
    • リソース・ライブラリコントラクト
    • Faces Flows
    • ステートレスビュー

4.5.2 リソース・ライブラリコントラクト#

リソースの塊を簡単に切り替えることができる仕組み

  • あまり便利に思わなかった

4.5.3 Faces Flows#

  • フロー処理について記載されている
  • スコープを設定ファイルやJavaアノテーションで保持できるみたい
    • MEMO: 他のフレームワークではどのようにスコープ持っているのか確認

4.5.4 ステートレスビュー#

  • 状態を保持しないビューを作成する機能

  • JSFでは画面を表示する際にサーバー側似コンポーネントツリーを作成し、同一画面を表示している間はそのコンポーネントツリーを保持していると説明しました。

  • ステートレスビューを使用すると、そのコンポーネントツリーを毎回破棄市、アクセスが来るたびに再作成する動きに変わる

  • ステートレスなアプリを作る上で欠かせない

    • MEMO: 他のフレームワークの場合は、redisなどでセッション管理している

4.6 まとめ#

  • ここまでの内容を理解していれば、十分JSFを使用してWebアプリケーションを作成することができる

  • 紹介していないライブラリ

    • PrimeFaces
    • RichFaces
    • OmniFaces
  • MEMO: 時間があれば見てみる程度で良いかも

Chapter 5 ビジネスロジック層の開発――CDIの利用#

  • 本章と次章ではCDIとEJBについて解説

  • 本章ではCDI

    • CDIとEJBの違いについて解説
    • CDIがJavaEEに採用された経緯
    • CDIの機能 について解説

5.1 CDIとEJB#

5.1.1 ビジネスロジック層の部品#

  • CDI,EJB

    • いずれも「ビジネスロジック」を記述するための部品である
  • CDI

    • JavaEE6から採用された新しい技術
  • EJB

    • Java2Enterprise Edition(J2EE)の頃から存在する歴史ある技術

5.1.2 CDIとEJBの違い#

  • CDIとEJBの違いは「設計の柔軟性」
  • CDIの方が自由度が高い

5.2 DI(Dependency Injection)#

  • CDIについて知る前にDIについて理解しておく必要がある
  • DIが考案された歴史的な背景をたどって、CDIの意義について知ることにする

5.2.1 DIとは#

  • DI

    • 部品間の依存関係を少なくすることで、部品の分離と結合をコントロールするための考え方、及びその仕組みのこと
  • 「依存」とは、クラス同士が強いつながりを持つことを意味している

  • 直接クラスを宣言し、インスタンス化している強い依存関係は、それ自体で処理が完結しているプログラムモジュール、例えば、

  • ビジネスロジック層でしか動かないクラス間の依存については問題ありません。

  • 一方で各層をまたがる依存関係はできる限り弱い方がよいという考えがある

  • 依存関係を弱く保つことができれば、変更点は少なくてすむ

5.2.2 DIによる依存関係の解消#

  • DIコンテナがあれば、実行時に動的にクラスを選択できる

  • 用途としては以下

    • ある条件において別の実装クラスを必要とするケース
      • 処理の流れ自体は変わらないが、ユーザーやリクエストの状況に応じて手続きが異なる、あるいは出力先が異なる
    • テストや開発中のモック入れ替え
      • 層をまたぐ処理や開発中のクラスを利用しなければならないときに、仮となるモックを利用し、将来的に完成したクラスを入れ替える場合。
      • あるいはテストデータを返却するテスト用のモックと完成したクラスを入れ替える場合
  • COLUMN ファクトリメソッドパターン

    • DIが実現している実装の入れ替えは、ファクトリメソッドパターンと呼ばれるデザインパターンを採用することでも実現可能
    • ファクトリメソッドパターンはオブジェクトの生成を管理するクラスを設けることで、任意の振る舞いを持つオブジェクトを取得する方式
    • ただし、ファクトリメソッドパターンを利用していても、結局返却するインスタンスを選択する処理をソースコードに記述しておく必要があり、
    • インスタンスをソースコード外で管理するには、プロパティファイルなどを用いる必要があるので、そうするよりはDIコンテナを利用するほうが楽
    • MEMO: 再読

5.2.3 JavaEEへのDI取り込み#

( 割愛 )

5.3 CDI#

  • CDIとはJavaEE6から導入されたJavaEEアプリケーションサーバー上でDI機能を提供するための仕様

  • CDIを使用するために必要な定義

    • インジェクションポイント:@Injectが指定された変数
    • CDIビーン:スコープに関するアノテーションが付与されたクラス
  • Column 設定ファイル beans.xml

    • JavaEE7 からCDIを使うための設定ファイルであるbeans.xmlは特定の用途を除き不要になりました
    • beanx.xmlはインジェクションポイントとCDIビーンの関係性を記述するためのものでしたが、現在では自動的に解決する用になっている
  • CDIの利点

    • インジェクションを行うのが簡単(アノテーションのみで設定ファイル不要)
    • DIを基礎とした様々な機能があらかじめ準備されている

5.4 CDI基本編#

  • CDI限定子:複数のインジェクション候補クラスが存在する場合に、クラスを特定するためのアノテーション javax.inject.Qualifier

5.4.1 CDIコンテナによるインジェクション#

  • CDIコンテナに存在するスコープを過ぎたオブジェクトは破棄される

5.4.2 CDIの型解決方法#

  • CDIがインジェクションポイントに対して注入する対象となるインスタンスを解決する方法は2通りある

    • インジェクションポイントと対象インスタンスが1対1の場合(自動解決)
    • CDI限定子もしくは、beans.xml(@Alternative)で解決する方法
  • 結論:CDI限定子(Qualifier)を使用して書いていくのがよい

    • 設定ファイルも必要ないし、ソースコードを柔軟に変更しながら開発ができるため
  • Column インターフェースを利用するべきか

    • 結論:インターフェースは準備しておくべき

5.5 CDI応用編#

  • CDIに関わる応用的な利用方法について記述
  • CDIの付加機能
    • イベント処理:CDIビーン上である条件を満たした場合に、別のクラスに対して通知を行う機能
    • ステレオタイプ:複数アノテーションをまとめて定義する機能
    • プロデューサ/ディスポーザ:クラスではなく、フィールドそのものやメソッドの戻り値をインジェクションポイントに注入する機能
    • インターセプター/デコレータ:処理の前後に別の処理を入れ込んだり、追加したりする機能

5.5.1 イベント処理#

  • イベント処理とは

    • 設定した閾値を超えるなど、特定の条件を満たす情報が発生したとき、その通知と情報をやりとりすることを指す
    • CDIではイベント発火はCDIビーン上で行い、それを処理するクラスを特別な呼び方として「オブザーバ」と呼ぶ
  • イベント処理の実装

    • イベント情報を格納するクラスを準備する
    • イベントを発火するCDIビーンを作成する
    • オブザーバクラスを作成する
  • イベント処理の留意事項

    • イベント発火からオブザーバの処理までがすべて同期で実行される
    • 非同期だと勘違いしないように
    • 参照関係を持たず、プログラムモジュール間似おける情報のやり取りを非同期で実行したい場合には、次章で説明するJMSを利用するなど別の方法を検討する必要がある

5.5.2 ステレオタイプの利用#

  • 複数のアノテーション定義をまとめて管理できる

  • @StereoTypeを付与してまとめていく

  • 上書きもできるが、あまり上書きしすぎると良くない

  • MEMO: 管理方法について

    • パッケージ名をstereotypeで切って管理する
    • クラス名称の接尾字にTypeをつけておくとアノテーションがステレオタイプで有ることを明示できる
  • MEMO: Springでもまとめていくアノテーションあるか

5.5.3 プロデューサ/ディスポーザの利用#

  • プロデューサを利用すると、インジェクションポイントに注入するオブジェクトをプログラム上で動的に変更することができる

  • プロデューサにより作成されたオブジェクトが終了処理の必要なオブジェクトである場合、ディスポーザを利用することで終了処理を記述することができる

  • プロデューサアノテーションをメソッドに付与して戻り値に@Inject指定した変数と同じ型を指定してあげる

  • メソッドで処理されたあとのオブジェクトがDIコンテナに格納され、インジェクションされる

  • Disposesアノテーションは、Producerメソッドで提供されたクラスの終了処理を行うためのディスポーザ

  • MEMO: Springにもこの概念があるかどうか確認

5.5.4 インターセプタとデコレータ#

  • インターセプターとデコレータについて解説

    • すでに作成済みのメソッドの処理に対して、外部のクラスを用いてその処理の前後や、処理内容に変更を加えることができる技術
  • インターセプター:対象となる処理の前後やライフサイクルに応じて処理を行うための仕組み

  • 定義方法

    • @Interceptorを付与したクラスを作成、メソッドに特定のアノテーション付与して機能に関与しない処理を実装
    • 利用側のメソッドで@Interceptors()の引数に作成したインターセプタークラスを追加する
    • または、beans.xmlに使用するインターセプターを定義する
  • Column どこでインターセプターを定義する?

    • 機能処理内にインターセプター(非機能処理)を記載するのはナンセンス
    • beans.xmlで管理する方が良いのではという意見が記載されている
  • デコレータ:機能追加をするための仕組み

    • 共通のインターフェースを実装したクラスに処理を委譲する
  • MEMO: デコレータの使い所について確認

    • Springで同様の機能あるかどうか
    • インターセプター=AOP?こちらも使い所についてまとめておく

5.6 まとめ#

機能が非常に豊富であることと、ルール似基づいた設計と実装が必要であることをご理解いただけたと思います。

Chapter 6 ビジネスロジック層の開発――EJBの利用#

6.1 Enterprise Java Beans(EJB)#

6.1.1 EJBとは#

  • アプリケーションサーバー上で動作するJavaのプログラムのうち、特に「ビジネスロジック」を担当する部品を指す

  • EJBは

    • サーブレットやJSF、Webサーバーなどアプリケーションサーバー外からのリクエストを受け付ける層と
    • データベースなどへ情報の永続化を行う層の中間の層の部品として機能する
  • 機能 EJB3.2

    • トランザクション制御
    • Java Persistence APIを介した永続化処理
    • Java Messageing Serviceを介したメッセージ駆動処理
    • 非同期実行制御
    • 同期実行制御
    • スケジュールに基づいた実行
    • JNDIを介したインスタンス取得(現在はアノテーションを利用)
    • リモートクライアントからの実行
    • セキュリティ

6.1.2 EJBの利点#

  • JavaEETutorialを参考
  • EJBの利点
    • EJBコンテナがシステムレベルのサービスを提供してくれるため、開発者はビジネスロジックの構築に集中できる
    • クライアントとの分離。クライアントにはビジネスロジックを実装する必要がない
    • JavaEE準拠のアプリケーションサーバー上であればどこでも動く

6.1.3 EJBの種類#

  • 3種類ある
    • セッションビーン
    • メッセージドリブンビーン
    • タイマー

6.2 セッションビーン#

6.2.1 セッションビーンとは#

  • EJBの中核を成すコンポーネント

6.2.2 セッションビーンの種類#

  • セッションビーンの種類
    • ステートレスセッションビーン
    • ステートフルセッションビーン
    • シングルトン
    • タイマー

6.2.3 ステートレスセッションビーン#

  • 一番良く利用されるEJBであり、ごくシンプルで基本的なEJB

  • ステートレスセッションビーンのクラスに@Statelessを付与

  • 利用側は@EJBを付与して使用する

  • @Statefulアノテーションを利用する

  • 留意点

    • クライアントごとにステートフルセッションビーンのインスタンスが作成される
  • サーブレットからステートフルセッションビーンを呼び出す場合、

  • 通常サーブレットは1リクエストスレッドにより1つのインスタンスが利用されるモデルであるため、

  • 状態を保持できない

  • ライフサイクルの制御

    • 生成
    • 活性化
    • 非活性化
    • 破棄
  • 非活性化されると、メモリ外にシリアライズ処理され出力される。

  • 必要になるとデシリアライズされ、メモリ上に復帰する

6.2.5 シングルトンセッションビーン#

  • @Singletonアノテーションを付与

  • 設定ファイルの読み出しの管理などで使う

  • COLUMN @Startupアノテーション

    • デプロイされたアプリケーションが有効化されたタイミングですぐにオブジェクトを生成するよう、アプリケーションサーバーに支持するもの
    • @DependsOnというアノテーションもある
      • 初期化の依存関係を解消するためのもの
    • MEMO: Springの場合初期化のアノテーションは何を使っているか

6.2.6 非同期処理#

  • 実装には「@Asynchronousアノテーション」を使用

  • クラスかメソッドに定義する

    • クラスの場合はすべてのメソッドが非同期になる
    • メソッドの場合は対象メソッドのみ非同期になる
  • MEMO: Futureインターフェースを介した操作について理解する

  • Column 非同期処理の再実行

    • EJBの非同期実行には処理の再投入(再実行)のためのAPIは定義されていないので
    • 自前で実装するか、他のアーキテクチャを利用する方法も検討する
    • キューを利用して後述のメッセージドリブンビーンを使うなどが考えられる

6.2.7 トランザクション#

  • @TransactionManagementアノテーション
  • @TransactionAttributeアノテーションを使用するらしい

詳しい使い方については割愛

6.3 メッセージドリブンビーン#

  • メッセージドリブンビーン(Message Driven Bean: MDB)について解説していく
    • メッセージと呼ばれるものを受け取ることで起動するという用途が限定的なコンポーネント

6.3.1 メッセージドリブン便とは#

  • MEMO: JMSも理解を深める必要あり

  • JMS

    • キューまたはトピックと呼ばれる方式を利用して、主にシステム間やアプリケーション間の情報を受け渡しを行うための仕組み
  • Column キューとトピック

    • キューとトピックの違いは、送信元と受取側の数の違いにある
      • キュー:1対1
      • トピック:N対M(多対多)
  • メッセージの受取を担当するのがメッセージドリブンビーン

  • MDBは常にキューまたはトピックにメッセージが配信されるのを待機し、監視している

6.3.2 実装例#

割愛

  • MEMO: JMSの使用方法とSpringJMSを使う

6.4 タイマー#

6.4.1 タイマーとは#

  • EJBには時間を指定して起動するための「タイマーサービス」というものが定義されている

タイマーはバッチ処理とは異なるので、むやみに使用するべきではない

  • 使用方法は以下の2種類存在する
    • TimerServiceAPIから登録する
    • @Scheduleを使って登録する

6.4.2 タイマーサービスのサンプル#

割愛

6.4.3 @Scheduleの実装サンプル#

割愛

6.5 EJBの設計#

  • EJBというのはあくまでビジネスロジックの実装を任されているコンポーネント

  • アプリケーションはビジネスロジックだけでは成り立たない

  • ブラウザの画面などのプレゼンテーション層

  • Webサービスなどのロジック呼び出し部分、データベース接続などの永続化層、外部サービスの呼び出しなどもある

  • EJBはこれらの処理の中間に位置することになる

  • EJBを設計する上でまず考える必要があるのは、この「外部の層との接点」

6.5.1 EJBメソッドの呼び出しに関する設計#

  • (1)やり取りする情報を保持するクラスを作成し、サーブレットとEJB双方から共通のクラスとして参照する

    • あまりにも多くの情報を保持し、データベースへの永続化が終わるリクエストの最後まで保持し続けるような長寿クラスにならないように注意する必要
  • (2)引数が増えた分についてはメソッドをオーバーロードして対応する

    • 注意:公開するメソッドが増えて、Webサービスのエンドポイントになるような場合はWSDLの変更が発生するため注意
  • Column JSPからのEJB呼び出し

    • 画面生成とビジネスロジックの分離ができないためやめた方がいい

6.5.2 ローカル呼び出しとリモート呼び出し#

  • リモート呼び出しは可能な限り使わないことをおすすめする

  • リモート呼び出しが必要なパターン

    • バッチの実装
    • GUIを持つクライアントからのビジネスロジック呼び出し
    • 多段アプリケーションサーバー構成(処理量による業務分離、接続形態によるレイヤー分割)
  • 代替手段としてはEJBはローカル使用のみにしておき

    • JAX-RSなどを使用した層を準備することが考えられる
  • MEMO: JAX-RS層について深堀り

6.5.3 同期/非同期#

  • 基本的に非同期にするメソッドはいかに絞るとよい
    • すぐに結果を必要としないもの
    • 結果を得るのに相応の時間がかかる処理

6.5.4 負荷量#

  • MEMO: 設計する際の負荷について考えるべき

6.5.5 データベースアクセス#

  • JPA

  • JPA以外のO/RマッピングもしくはDAOフレームワーク

  • JDBCの直接呼び出し

  • 通常はEJBと親和性が高いJPAをEJBトランザクション管理下に置くのが容易

6.6 EJBのテスト#

6.6.1 EJBのテストの必要性と難しさ#

  • EJBの最大の弱点はテストがしづらいものであった

  • JavaSEでも必要な資材を準備すれば動くようになったが、一部対応していないらしい

6.6.2 EJBテストの準備#

  • EJBContainerからEJBモジュールを取得し、Junitなどでテストを実施する説明

6.7 まとめ#

CDIとEJBをうまく組み合わせて設計していこうという説明

Chapter 7 データアクセス層の開発――JPAの基本#

本章と次章では、JavaEEのにおけるデータベースへのアクセス方法であるJPAについて解説

エンティティやクエリといったJPAの構成要素と、JPQLとCriteriaAPIの2種類のクエリについて説明

7.1 JPAの基礎知識#

  • 永続化:Javaのプロセスが終了しても、データが消えずに残るような状態にすること

7.1.1 JPAの構成要素#

  • エンティティクラス(データのレイアウトを規定)とエンティティオブジェクト(データを保持)
  • エンティティマネージャ
    • エンティティオブジェクトとレコードの紐付けを管理
  • クエリ
    • データを操作
  • 永続化ユニット
    • データベースへの接続情報などJPAの設定を記述する

7.1.2 エンティティクラスとエンティティオブジェクト#

  • そのまま、クラスとオブジェクトという理解
  • テーブルとレコード になぞらえて考えられる

7.1.3 エンティティマネージャ#

  • エンティティオブジェクトを取得したり、データベースへ反映、削除したりする
  • 永続化コンテキストの配下にないものは、データベースへは反映されない
  • persist()メソッドで管理下におくみたい

7.1.4 クエリ#

  • エンティティマネージャが持つ基本的なメソッドを利用する他に、より自由度の高いクエリを用いる方法がある

  • JPAが用意しているクエリの定義方法

    • JPQL: SQLに似た記法で記載でき、DBMSを意識しなくて良い
    • Criteria API: APIを使ってクエリを組み立てて行く手法。DBMSを意識しなくて良い
    • ネイティブクエリ: SQL文をかいていく必要があるので、DBMSが変わればここも変更しないと行けない
  • 理由がなければJPQLを用いるのが良いだろう

7.1.5 永続化ユニット#

  • 永続化似関する設定をまとめたもので、実態はpersistence.xmlという名前のXMLファイル

  • 設定項目としては以下のようなものがある

    • 永続化ユニットの名前
    • トランザクションマネージャの設定
    • 永続化プロバイダ(JPAの実行エンジン)のクラス名
    • 永続化プロバイダに与えるプロパティ
    • 接続先データソースの名前★
    • エンティティクラスの名前★
  • データベースの接続先を設定する方法

    • アプリケーションサーバーで定義されているデータソースの名前を指定する方法
    • 永続化プロバイダのプロパティとして、接続先アドレスやユーザー名、パスワードなどを設定する方法 が挙げられる
  • JPAの実行エンジンにどれがエンティティクラスなのか検知してもらう設定も入れる

7.1.6 JPAのメリット#

  • ResultSetからDTOにうつして..という処理を記述しなくてよい
  • メソッドかクエリでアクセスできる
  • コード量が従来よりも少ない
  • メモリ上にキャッシュされたエンティティオブジェクトを利用できる
    • アプリ開発者はキャッシュの有無を意識する必要はない

7.2 エンティティの基本#

(割愛)

7.2.1 エンティティクラスの実装#

  • エンティティクラスには@Entityを付与する

  • publicでなければならず、finalであってはならない

  • 引数のないコンストラクタを作成しとくべき

  • Column Serializableについて

    • EJBのリモート呼び出し
    • 複数のアプリケーションサーバーでJPAの2次キャッシュを構成する場合
    • MEMO: 他のORMはSerializableに定義しているか確認

7.2.2 ID#

  • エンティティクラスはIDとして定義したフィールドを使用してhashCodeメソッド、
  • equals(Object)メソッドを実装しなければ行けない→通常IDEで自動生成できる
  • toString()をオーバーライドしておくとデバッグに役立つ!
  • MEMO: 他のORMでもtoString()オーバーライドしたりしてるか確認

7.2.3 リレーション#

  • @OneToMany等によるエンティティの紐付け型を説明

  • MEMO: 他のORMでも存在するか確認

  • 1対1のリレーションについて

    • 通常1対1のリレーションだと、同一エンティティに保持してしまうことが望ましい
    • ただし、ライフサイクルが異なるデータだと、別のエンティティに分けた方が良いケースがある
    • 例)アカウント情報とアカウントに紐づく会社情報
      • アカウント情報:作成されてから削除されるまで
      • 会社情報:入社して初めてできる、会社に所属しなければレコードがない
        • などのような状況

7.3 エンティティマネージャの基本#

  • エンティティマネージャの実態は javax.persistence.EntityManagerインターフェース

  • このインターフェースに用意されているメソッドを通してエンティティを操作する

  • EntityManagerのインスタンスはCDIを用いてアプリケーションサーバーからインジェクションで取得する

  • @PersistenceContextアノテーションを付与し、属性似unitNameを指定

  • persistence.xml<persistence-unit>タグのname属性と一致した名前を指定

7.3.1 エンティティのライフサイクル#

  • ライフサイクル
    • NEW
    • MANAGED
    • REMOVED
    • DETACHED

7.3.2 エンティティオブジェクトの作成と永続化#

// NEW状態でまだ永続化コンテキストと紐付いてない
Account account = new Account();
// MANAGED状態になる 次のコミットのタイミングでデータベースに反映される
EntiryManager em = xxx;
em.persist(account);

7.3.3 エンティティオブジェクトの取得と更新#

// 取得したいEntityクラスとIDを指定
// MANAGED状態で取得される
Account account = em.find(Account.class, 0);
// setter経由で値を設定するとデータベースに反映される(コミットしたタイミングで)
account.setName('てらだよしお');

7.3.4 エンティティの削除#

em.remove(account);

7.3.5 デタッチ#

EJBのメソッドの外へ出るとDETACHED状態になる

  • MEMO: 通常アプリでEntityクラスをそのまま画面で使用することは良くないと考える

7.4 クエリAPI#

JPQLとCriteriaAPIを使ったQuery作成方法を記載

7.4.1 パラメータ#

JPQLとCriteriaAPIはパラメータを取ることができる パラメータは位置で指定する方法と名前で指定する方法があるが通常は名前で指定した方がよい

  • MEMO: 名前で指定するルールを作った方が良さそう

7.4.2 サンプルデータ#

ダウンロードデータの中にあるサンプルデータについての説明

7.5 JPQL#

  • JPQL(Java Persistence Query Language)

7.5.1 JPQLの基本構文#

7.5.5 フェッチ#

  • 取得するエンティティにリレーションが定義されている場合、リレーション先のエンティティを

  • どのタイミングでデータベースから取得するかを決めることができる

  • これを「フェッチ戦略」という

    • Eagerフェッチ
    • Lazyフェッチ
  • Eagerフェッチ

    • findメソッド実行時に、リレーション定義されている参照先のオブジェクトも取得する
    • リレーション先のエンティティオブジェクトを同時に使用することの多い場合は、
    • Eagerフェッチを使用する
  • Lazyフェッチ

    • 取得処理時には、リレーション先のエンティティオブジェクトを取得せず、
    • リレーション先にはじめてアクセスする際に取得する
    • リレーション先のエンティティオブジェクトを頻繁に使用しない場合はLazyにすべき
    • デメリット
      • どこでエンティティの取得が行われたか分かりづらい
      • 性能の劣化の場所を特定しづらい
  • N+1問題とJOINフェッチ

    • 1回のクエリを発行したあとにN回のクエリの発行を必要とすることをN+1問題という
    • リレーションが増えるほど、発行するクエリの数が増える
    • これに対応するためにJOIN FETCH節を利用する
    • JOIN句の後ろにFETCHがつくだけ

7.5.6 エンティティオブジェクトの集計#

  • シンプルにCountなどを使う方法
  • 型を意識する必要がある場合、コンストラクタ式を利用する必要があるらしい
    • 割愛))

7.5.7 名前付きクエリ#

  • 開発者はJPQLのクエリに名前をつけることができる

  • 名前をつけられたJPQLのクエリを「名前付きクエリ」と呼ぶ

  • @NamedQueries@NamedQueryを使って名前定義しておく方法

    • MEMO: 他のORMはSQLファイルで管理するのではと思う

7.6 CriteriaAPI#

  • Criteriaクエリを利用してクエリを構築していく
  • JPQLと役割は同じであるため、JPQL同様に以下の要素から構成
    • SELECT
    • FROM
    • JOIN
    • WHERE
    • ORDERBY

7.6.1 Criteria APIの基本構文#

(割愛)

  • 利用のメリットがあまりわかない
    • 発行されているSQLが分かりづらい
    • SQLNativeでかけない
    • メソッドなど覚えなくては行けない

Chapter8 データアクセス層の開発 JPAの応用#

  • エンティティとデータベースの関連付け
  • キャッシュなどJPAの応用的な使い方について紹介

8.1 高度なエンティティの利用方法#

  • 日時を指定する日時型、
  • 連続した一意の数字を設定するシーケンス、
  • リレーション先のエンティティへ処理を伝播するカスケードを紹介

8.1.1 フィールドに関する応用#

  • 日時

    • JPAで日時を使用するには、エンティティクラスのフィールドにjava.util.Date型を指定
    • @Temporalアノテーションを付与して、引数にTemporalTypeを指定
  • シーケンス

    • エンティティのIDにはサロゲートキーを使用するのが 一般的
    • サロゲートキーは人工的に作成されたキーであり、業務上の意味がないもの
    • MEMO: 一般的にサロゲートキーが使われているのか確認
    • @SequenceGeneratorアノテーションを付与し、作成したシーケンスからエンティティフィールドに自動で値を設定するには
    • @GeneratedValueアノテーションを使用する
    • MEMO: DBとどのように絡んでくるのか、DB定義側も自動的にシーケンス定義が作成されるのか
      • どのDBもだいたいシーケンス定義を作成できるのか
  • カスケード

    • エンティティオブジェクトに任意の操作をしたあと、リレーション先までその操作を反映させるための機能
    • MEMO: 他のORMはどのようにこの機能を持っているか確認
  • 複合ID

    • @IdClass@EmbeddedIdを使用して実装する
      • どちらも主キークラスとして定義する必要あり

8.2 ライフサイクルコールバック#

  • JPAではコールバックメソッドを使用することで、エンティティオブジェクトの操作に対応した処理を実行することができる
  • 実装方法は2種類
    • エンティティクラスに実装
      • エンティティの値を変更する場合にとどめてく
    • エンティティリスナに実装
      • エンティティの値を変更する処理は実装せず、共通で使用するような処理にとどめておく
    • →あまり複雑にならないように注意
  • MEMO: 他のORMにはコールバックメソッドの仕組みある?どんな処理を実装するのがベター?

8.3 エンティティクラスとテーブル構造#

Javaアプリケーション開発者がエンティティクラスを作成すると、JPAはエンティティクラスの定義を読み込み、 データベースへテーブルを作成する

  • MEMO: 他のORMはテーブル自動作成とかされるのか確認

8.3.1 テーブル名とカラム名#

エンティティの変数とカラム名を変更する方法について記載

  • 多対多の中間表の名前の付け方
  • LOB定義 @Lob

8.3.2 索引#

  • 索引を作成する方法について記載
    • @Index(columnList = "xxxxx,xxxxx,xxxxxx")

8.3.3 制約#

  • 精度とスケール、長さ

    • @Column(precision=15, scale=0)
    • @Column(length=500)
  • 一意制約

  • MEMO: 他のORMでもDBMSの方言を吸収しながらテーブル定義ができるか確認、できなければJPAってすごい

    • 他のシステムも同じDBを参照していた場合、衝突する可能性あるので、APが対になるようなシステムであればよいかも

8.4 トランザクション#

  • JavaEEには
    • EJBコンテナにより自動的に開始されるトランザクション
    • Java開発者が任意で開始するトランザクション
      • がある

8.5 キャッシュ#

8.5.1 これまでのデータアクセス#

8.5.2 キャッシュを使用したデータアクセス#

  • Column 複数アプリケーションによるデータ更新
    • 複数のアプリケーションが同一のデータベースを更新する場合や他のノードやデータベースでデータが更新されると、
    • キャッシュされているエンティティに伝播されないので、整合性が取れなくなる
    • MEMO: かなり致命的な問題だと思う… マスタテーブルに使うとか?
    • MEMO: 今キャッシュされているエンティティ情報をログに出力する方法などがあれば可視化されてわかりやすいが、ある?

8.5.5 プリロード#

  • EJBの@Startupなどを利用してアプリケーション起動時に1回だけSQLを実行したり、
  • JSFやWebサービスを利用して外から初期化処理を起動できるようにすること
    • 1回読み込んでおくことでキャッシュに乗せて処理を早くする
  • GlassFishではJPAの実行エンジンとして、EclipseLinkを使用している

  • EclipseLinkには

    • エンティティキャッシュ
      • エンティティオブジェクトをキャッシュする機能
    • 問い合わせキャッシュ の2種類が存在する
      • クエリの結果をキャッシュする機能
  • MEMO: EcllipseLink以外の実行エンジンなどが存在する?

8.6 永続化ユニット#

アプリケーションからJPAを使用する場合,次のような情報を定義する必要があります。

アプリケーション内のエンティティクラスの情報 エンティティクラスとデータベーステーブルとのマッピング情報 JPAプロバイダがデータベースコネクションを取得するためのデータソースの情報 これらの情報を定義したものを永続化ユニットといいます。

  • APサーバーにJNDIを定義し、APサーバー経由で接続→こちらを推奨しますとのこと

  • 設定ファイルをアプリケーションに保持して直接接続

  • Column JavaSEでJPAを使う

    • jarファイルをクラスパスに追加して、persistence.xmlを用意すれば使えますとのこと
    • EJBコンテナがないので、EntityManagerFactory経由でEntityManagerオブジェクトを取得する

8.7 環境構築手順#

割愛

8.8 アプリケーション開発手順#

8.8.2 JPQLの開発#

IDE上で試しにSQL流せる機能

  • MEMO: 他のORMにも同様の機能あるか確認する

Chapter9 RESTful Webサービスの開発#

9.1 Webサービスの基礎#

9.1.1 Webサービスとは#

  • サーバーで行われたなんらかの処理の結果をHTMLではなく、処理結果だけで返すものをWebサービスと呼びます

  • Webサービスを実現するために使われる技術

    • SOAP: 信頼性を必要とする企業間でのWebサービスで多用されている
    • REST: 一般に公開されているWebサービスでよく使用されている
      • RESTベースのWebサービスをRESTfulWebサービスと呼ぶ
  • JavaEEでもSOAPとRESTを利用したWebサービスを作成するためのAPIを提供している

    • SOAPを使用したWebサービスを作成するAPIがJAX-WS
    • RESTful Webサービスを作成するAPIが、JAX-RS

9.1.2 RESTful Webサービスとは#

  • RESTful Webサービスとは、RESTに則ったWebサービス

  • REST原則

    • a.すべてのリソースに一意なアドレス(URI)を与える
    • b.情報の操作には予め定義された命令体型(統一インターフェイスという)を使用する
    • c.プラットフォームに応じて複数の表現(データ形式)を使用する
    • d.セッションなどの状態管理を行わず、ステートレスに通信する
    • e.アプリケーションはリンクによって、次の状態に遷移する
  • 上記のすべてを守る必要はないが、少なくとも、aとbは守っておくべき

  • 制約がゆるいので、かんたんに実装できる

  • 一方、SOAPは定義が厳密なので実装ハードルが高い

9.1.3 RESTとHTTP#

  • HTTPヘッダー
  • HTTPメソッド
    • GET
    • POST
    • PUT
    • DELETE
  • URI
    • MEMO: マトリックスパラメータは初めて聞いた
  • ステータスコード

9.2 JAX-RSの基本#

9.2.1 JAX-RSとは#

  • リクエストパラメータ

    • マーシャル:XML形式やJSON形式→Javaオブジェクト
    • アンマーシャル:Javaオブジェクト→XML形式やJSON形式
    • JAX-RS2.0仕様の参照実装はJersey
    • JerseyはGlassFishサーバーでも使用されている
  • 主に5つの機能を提供

    • 1.HTTPメソッド/URIパターンとリソースメソッドとのバインド機能
    • 2.メッセージボディのデータ形式指定機能
    • 3.リクエスト情報のインジェクション機能
    • 4.リクエスト/レスポンスのメッセージボディの変換機能
    • 5.例外のレスポンスマッピング機能

9.2.2 サンプルアプリケーションにおけるJAX-RSの機能#

9.3 RESTful Webサービス作成のための事前準備#

9.3.1 RESTful Webサービスの認証方式#

  • ナレッジバンクのRESTサービス機能ではWEBアプリケーション機能で採用しているFORM認証ではなく

  • BASIC認証で認証を行う

  • BASIC認証を行うための設定を記載

    • web.xmlに追記するみたい
  • MEMO: 他のフレームワークでBASIC認証を行う方法について整理

9.3.2 データクラス(DTO)#

  • クライアントからのリクエストをJavaオブジェクトに変換する際に受け皿クラスを作成
    • @XMLRootElementアノテーションなどを不要しないと行けないらしく、不便そう

9.3.3 Application サブクラス#

  • 作成するリソースクラスなど、JAX-RSで使用する一連のファイルをJAX-RSランタイムに通知するためにApplicationサブクラスをクラスパス上に配置
  • このファイルの存在により、作成するリソースクラスをRESTful Webサービスとして公開できる
  • ApplicationConfig.java@ApplicationPath("xxxxxx")を指定することでOK

9.4 RESTサービスクラス(サーバー側)の作成#

9.4.1 リソースクラスの構成要素#

  • RESTful Webサービスで提供する処理を定義するRESTサービスクラスを作成します。
  • RESTではすべてをリソースとして扱うため、リソースクラスとも呼ばれる
    • MEMO: Springの場合、Controller

9.4.2 エンドポイントURIの設定#

  • @Path("{id}")
  • などと指定

9.4.3 HTTPメソッドとリソースメソッドのバインド#

  • @GET,@POSTなどを指定

9.4.4 メッセージボディのデータ形式指定#

  • @Consumes({}): クライアントから受け取るデータ形式

  • @Produces({}): クライアントに返却するデータ形式

  • MINEタイプの抽象化:javax.ws.rs.core.MediaType

    • APPLICATION_XML = "application/xml";
    • などの定義がある
  • Column コンテンツネゴシエーション

    • クライアントがサーバーにリクエストする際に、返してもらいたいメッセージボディのデータ形式やエンコード方式などをリクエストヘッダーで要求できる
    • これを「HTTPコンテンツネゴシエーション」といいます。
    • コンテンツネゴシエーションはAcceptヘッダーに要求するデータ形式を指定して行う
    • 要求されたデータ形式をサーバーが提供できない場合、「406 Not Acceptable」のステータスコードをクライアントに返す
      • Accept-Charsetヘッダー、Accept-Languageヘッダー、Accept-Encodingヘッダーなど
  • MEMO: 見たことはあったが用語として抑えれてなかったので覚えておく

  • メッセージボディとJavaオブジェクトとのマッピング

    • アンマーシャル:javax.ws.rs.ext.MessageBodyReader
    • マーシャル:javax.ws.rs.ext.MessageBodyWriter

9.4.5 リクエスト情報のインジェクション#

  • @javax.ws.rs.PathParamアノテーション:{id}などのパスパラメータを取得
  • @javax.ws.rs.QueryParamアノテーション:クエリパラメータを取得
  • @javax.ws.rs.MatrixParamアノテーション:URIのマトリクスパラメータを取得する
  • @javax.ws.rs.FormParamアノテーション:HTMLのフォームから送信された情報を取得する
  • @javax.ws.rs.HeaderParamアノテーション:リクエストヘッダーから値を取得する
  • @javax.ws.rs.CookieParamアノテーション:リクエストのCookieヘッダーから値を取得する
  • @javax.ws.rs.core.Contextアノテーション:リクエストURIやリクエストヘッダー、セキュリティ情報などのコンテキスト情報を取得する汎用的なアノテーション
  • @javax.ws.rs.BeanParamアノテーション:リクエストのパラメータ一式をビーンとして取得する
  • @javax.ws.rs.DefaultValueアノテーション:対象に値が入らなかった場合、デフォルト値を指定するアノテーション

9.4.6 リクエストのメッセージボディの受取#

  • リクエストの引数にアノテーションを付与しなければ、メッセージボディを受け取れる

9.4.7 入力チェック#

  • リクエストのメッセージボディにマッピングしているJavaオブジェクトをバリデーションするには@Validアノテーションを使用する

9.4.8 レスポンスの定義#

  • return する時に javax.ws.rs.core.Responseクラスを用意している

  • Response.created(URI.create("/knowledge" + knowledge.getId())).build()

    • みたいな感じで生成して返却する
  • レスポンスメッセージボディのみを指定するときは、Response型以外のオブジェクトを戻り値にするとよい

  • エンティティプロバイダ(MessageBodyWriterインターフェース実装クラス)がリクエストのAcceptヘッダーに指定されているデータ形式に変換し、レスポンスのメッセージボディに書き出します

  • 成功時のレスポンスにメッセージボディが含まれている場合、「200 OK」

  • メッセージボディが含まれていない場合、「204 No Content」

    • MEMO: レスポンスの 204 No Contentは覚えておく

9.5 HTTPメソッドに応じた処理#

9.5.1 ナレッジの検索(GETメソッドによる操作)#

9.5.2 ナレッジの登録(POSTメソッドによる操作)#

9.5.3 ナレッジの更新(PUTメソッドによる操作)#

9.5.4 ナレッジの削除(DELETEメソッドによる操作)#

9.5.5 例外クラス#

  • JAX-RSの例外クラスを使用する

  • JAX-RS2.0の例外体系

    • 非チェック例外である、WebApplicationExceptionを用意している
      • コンストラクタにステータスコードを指定すると、アプリケーションからスローされた際にステータスコードを含んだResponseインスタンスをクライントに返す
      • 何も指定しなかったら 500 Internal Server Error
    • JAX-RS2.0ではこのクラスを継承した例外クラスが追加された
  • ClientErrorExceptionを継承した例外クラス

    • BadRequestException(400)
    • NotAuthorizedException(401)
  • ServerErrorExceptionを継承した例外クラス

    • InternalServerErrorException(500)
    • ServiceUnavailableException(503)
  • MEMO: 他のフレームワークでもこの標準エラーを使用しているような気がする。あとで確認しておく

  • 独自例外の作成方法

    • RuntimeExceptionを継承して例外クラスを作成
    • マッパークラスを作成し、JAX-RSに認識させる
  • MEMO: 独自例外を作成することは必ず必要になってくるので、ここ後で見返しておく

    • Responseが持っているステータスについても覚えておく
  • MEMO: 標準提供の例外をマッピングすることも可能!

    • 標準のExceptionはステータスコードしかクライアントに返却しないため、ここでマッピングして再定義しておくと、メッセージも合わせて返却できるということ

9.6 RESTクライアントクラス(クライアント側)の作成#

9.6.1 データクラス(DTO)#

9.6.2 RESTクライアントクラス#

  • MEMO: Javaクライアント側でJAX-RSのWebサービスを利用したい場合の実装方法
    • BASIC認証にサードパーティのクラスを使う

9.7 メッセージフィルタクラス#

9.7.1 メッセージフィルタとエンティティインターセプタ#

  • JAX-RS2.0では新たに、
    • メッセージフィルタ:リクエスト/レスポンスヘッダーの編集などに使用
    • エンティティボディインターセプター:エンティティボディの編集などに使用

割愛

  • MEMO: Logging用のフィルタの実装について考える ベストプラクティスは?

9.8 まとめ#

  • JAX-RS
    • アノテーションでRESTful-Webサービスを作成できる

Chapter10 バッチアプリケーションの開発#

JavaEE7では、Javaにおけるバッチ処理の標準化仕様が盛り込まれました。

この仕様はJSR352(Batch Applications for the Java Platform)で規定されている

通称「jBatch」と呼ばれている

10.1 jBatchの基本#

10.1.1 バッチ処理とその特徴#

  • バッチ処理とは

    • 複数のデータや複数の処理を一括して実行する方式のこと
    • 一方、Webブラウザなどの画面を介して入力と応答が繰り返される処理をリアルタイム処理、オンライン処理と呼ぶ
  • 特徴

    • 一度に多くのデータが処理される
    • 実行時間が長い
    • 非対話型(人間による画面での入出力操作を伴わない)
    • リクエストに従って起動されることよりも、実行する時刻を指定して起動されることが多い

10.1.2 jBatchとは#

  • jBatchとは

    • 前項で述べたような特徴を持つバッチ処理をJava言語で実装するためのフレームワーク
    • 業務システムにおけるバッチ処理は、全体的な処理の流れや設計時に注意すべきポイントなど、
    • 時代や言語を伴わない共通点が多く見られる
    • jBatchはこうした業務システムのバッチ処理似求められる要素を盛り込んだ「以前から培われている雛形」を標準として提供
    • jBatchを使わなくてもバッチ処理を実現できるが、活用することで、理解が容易で考慮漏れの少ないバッチ処理を効率よく提供刷ることができる
  • jBatchの機能と構成要素

    • 大まかに言うと
      • ジョブ
      • ステップ
        • で構成される
    • ジョブ:全体の流れを記述
    • ステップ:ここの処理を実装する
    • ジョブとステップの分離により、業務の変更に対して柔軟に対応できる仕組みになっている
  • jBatchのアーキテクチャはオープンソースのSpringBatchから多くを受け継いでいるが

  • ジョブとステップの分離は、メインフレーム時代から受け継がれているもの

  • メインフレームでは、全体の流れはジョブとしてJCLによって記述され、

  • 業務ロジックはステップとして、COBOLやPL/Iなどの言語で記述されたプログラムを用いて実装される

  • jBatchの機能と構成要素

  • jBatchにはジョブとステップ以外にいくつか保s所的な機能がある

    • リスナ:ジョブやステップの開始直前または終了直後に処理を差し込む
    • ジョブリポジトリ:ジョブやステップの状態を永続的に保持する
    • コンテキスト:一時的に保持する
    • メトリック:統計的な情報を確認刷る

10.1.3 ジョブ#

  • ジョブはステップの入れ物

    • 1つのジョブの中には1つ以上のステップが必要
    • XMLで記述する
      • 各ステップの呼び出し先クラス
      • 実行順序
      • ジョブ全体や各ステップに対する設定、エラー発生時の挙動なども記述
      • 記述のルールを示した仕様は、JSL(Job Specification Language)と呼ばれる
      • ジョブを記述したXMLファイルはJob XMLファイルと呼ばれる
    • JSLには処理の実行順序を制御するために、以下のXML要素が用意されている
      • フロー(flow)
      • スプリット(split)
      • デシジョン(decision)
      • 遷移要素(Transition Elements)
  • 全体図が記載されている(書籍を見たほうが良い)

  • フロー:複数のステップをまとめる要素

  • スプリット:複数のフローを同時実行させることができる

  • デシジョン:ジョブ内部で次の遷移先を細かくカスタマイズするための機能

  • 遷移要素

    • next: 遷移先には、ステップ、フロー、スプリット、デシジョンが指定できる
    • end: 正常終了
    • stop: 中断
    • fail: 異常終了
  • リトライとスキップ

    • リトライ:チャンク型ステップの処理中に特定の例外が発生した場合に、再度そのデータの処理を試みる
    • スキップ:チャンク型ステップの処理中に特定の例外が発生した場合に、データを飛ばして次に進む
    • リトライもしくはスキップ対象の例外クラスをJob XMLの中に定義
  • ジョブオペレータ

    • ジョブ自体の開始や停止の全体的な制御を行う
  • ジョブオペレータの呼び出し方法

    • バッチ処理の特徴として、「実行する時刻を指定して起動されることが多い」という点をあげたが、
    • jBatchの仕様にはバッチを決まった時間に起動する方式に関する規定や、それを実現するAPIも含まれていない
    • この部分に関しては、ジョブスケジューラを連携させる方式が一般的に
      • Linuxなどであればcron
      • Windowsであればタスクスケジューラ
      • その他市販のジョブスケジューラを使用する…など
    • ジョブを臨時で実行したい場合や、何らかの異常が発生し、人間が介入して原因を取り除いたあとに再実行する場合は、リクエストに従って起動することになります。(これを「アドホックな実行」と呼びます)
      • そういった場合、画面などのユーザーインターフェースがあると便利だが、この点に関してもjBatchは規定ない
    • 実装する際には、オペレータの運用も考える必要がある
  • MEMO: 手動実行されたジョブか、スケジュールで実行されたジョブかを識別する方法を仕込んでおいた方が良いと思った

10.1.4 ステップ#

  • バッチ内部の個々の処理を実装する部分
    • ステップの実態は、jBatchのAPIの中で定義されているJavaインターフェースであり、実装テンプレートを提供している
  • ステップには2種類ある
    • チャンク型:複数のデータを逐次的に処理するために使われる
      • ItemReader,ItemProcessor,ItemWriterの3つで構成される
      • ItemReaderとItemProcessorを繰り返したあと、ItemWriterが呼ばれる(デフォルトで10回)
      • この塊(10回などの処理の塊)をチャンクと呼ぶ
    • バッチレット型:単体で完結する処理で使われます
      • データの加工や計算を1件ずつ繰り返すような処理ではなく、データに依存しない処理やコマンド実行などの処理を担います。
      • 例えば、ディレクトリ作成やファイル圧縮、送受信処理などの処理
      • 「タスク志向のステップ」と呼ばれる場合もある
      • MEMO: このような単純な処理であれば、スクリプトで完結しそうな気もする..

10.1.5 補助機能#

  • リスナ

    • リスナを用いることで、バッチ処理の進行に応じた特定のタイミングで任意の処理を実行することができる
    • 「特定のタイミング」には、ジョブやステップの開始及び終了、リトライやスキップの発生などがある
  • 各処理のタイミングごとにリスナが用意されている

  • リスナの設置は任意で、設置したい場合、リスナのクラス名をJob XMLの中で記述

  • ジョブリポジトリ:開発者が意識して操作したりしない部分みたい

    • 実行中のジョブの情報や、実行が終わったジョブに関する情報が保存される
    • 情報の更新はコンテナによって自動的に行われ、情報の取得は、前述のジョブオペレータや、後述するコンテキスト、メトリックAPIを利用する
  • コンテキスト

    • 種類
      • ジョブコンテキスト
      • ステップコンテキスト
    • それぞれ、実行中のジョブやステップに関する情報を提供する役割を担う
      • 名前やID、ステータスなどがある
      • コンテキストへのアクセスは、jBatchAPIのJobContext、StepContextインターフェースを経由して行います
  • メトリック

    • チャンク型のステップに対して、実行時の統計情報を提供するのがメトリック
    • 情報
      • 読み取りレコード数
      • 書き込みレコード数
      • スキップが発生した数
      • など、処理量に関するもの
    • メトリックへのアクセスには、jBatchAPI似あるMetricインターフェースを経由して行う

10.2 jBatchの利用――基本編#

  • 実際に実装してみる
    • JobXMLの実装
    • チャンク型ステップの実装
    • バッチレット型ステップの実装
    • ジョブ実行部分の実装
    • 実行結果の確認

10.2.1 JobXMLの実装#

  • バッチの全体を表すJobXMLを作成刷る

  • ファイル名から拡張子を取り除いた部分がそのままジョブの名前となります。

  • ジョブの名前は実行時にJobOperatorクラスのメソッドにわたす形で利用される

  • それぞれの要素説明

    • job
    • step
    • chunk
    • batchlet

10.2.2 チャンク型ステップの実装#

10.2.5 バッチレット型ステップの実装#

  • Batchletを実装
    • prosess,stopを実装して処理を書くだけ
    • 保守性を高い状態に保つためにも、1機能の実装にとどめておくべき

10.2.6 ジョブ実行部分の実装#

  • JobInstanceとJobExecution

    • 最初にジョブを実行すると、コンテナ内部ではこの2つのインスタンスが生成される
      • JobInstanceはジョブの1回分を表現
      • JobExecutionはジョブの実行そのものを表現している
  • パッケージング

    • jBatchでもWebアプリケーションと同様に、構成するファイル群をwarファイル形式にまとめてコンテナにデプロイ刷る
    • ここで注意が必要なのは、JobXMLファイルの配置場所
      • JobXMLは、warファイル内部のWEB-INF/classes/META-INF/batch-jobsディレクトリの配下に「ジョブ名.xml」という名前で配置しなければ行けない
  • MEMO: パッケージングする際には一般的にどのようにしているか確認、Gradleとかの前処理で調整している?

10.2.7 実行結果の確認#

バッチログを掲載

10.3 jBatchの利用――応用編#

10.3.1 サンプル概要#

  • ナレッジ件数ランキング集計バッチ

  • コメント件数ランキング集計バッチ

  • Column キーブレイク処理について

    • マスタ表から1件読み込み、トランザクション表を操作して処理するという一連の流れ
    • 業務におけるバッチ処理では大変多く見られるパターンの1つ
    • jBatchのチャンク形式のステップは、このようなキーブレイク処理を念頭においたものと言えるので、本書でも取り上げた
    • MEMO: チャンク形式が業務で応用されている例を確認しておくべき
      • SQL一本で済ませる場合が多いのでは?

10.4 ジョブの作成#

10.4.1 Job XMLの実装#

  • property要素を利用する方法を記載
    • 感覚的にはmavenみたいな感じ

10.4.2 チャンクの実装#

※実際に実装刷る際に必要なった時に見返す

10.5 ジョブのフロー制御#

※実際に実装刷る際に必要なった時に見返す

10.6 まとめ#

  • 終了!
Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築
https://tutttuwi.github.io/posts/2020-04_javaee7徹底入門/
Author
Tomoaki Tsutsui
Published at
2020-04-12
License
CC BY-NC-SA 4.0