1 1 GlassFish v3 で実感!! エンタープライズ Java の進化 Yoshio Terada GlassFish エバンジェリスト Sun Microsystems K.K. http://yoshio3.com
11
GlassFish v3 で実感!!エンタープライズ Java の進化
Yoshio TeradaGlassFish エバンジェリストSun Microsystems K.K.http://yoshio3.com
2
Agenda
• はじめに• Java EE 6 のご紹介• GlassFish v3 のご紹介• GlassFish の今後• 参考情報
3
はじめに
もう一度 Java EE を見直してみませんか?
4
今日のポイント
• Java EE 6 でかんたん開発がさらに進化しました
• 開発効率が大幅に向上しました
• GlassFish v3 はとてもかんたん・軽量です
• GlassFish v3.1 は本番環境向けの機能を提供します
• Java EE は XML 設定が困難、設定が膨大になる
• パッケージも面倒 (ear,war,jar...)
• すぐに動作確認ができず開発効率が悪い
• アプリケーションサーバも重く起動時間もかかる> 再起動を待つのが耐えられない
5
Demo
6
Java EE 6 概要
2009 年 12 月 10 日正式リリース
7
Java EE 6 のテーマWhat's New?• 拡張性
• プロファイル> Web プロファイル> Enterprise Platform ( フル Java EE )
• Pruning> 仕様の削減
• かんたん開発> 新技術の追加
● DI, CDI, JAX-RS, Bean Validation
> 更新された技術● JPA2.0, EJB 3.1, JSF 2.0 等
8
拡張性
• Servlet 3.0> アノテーション> マルチパート対応> 非同期サーブレット
• プラガビリティの向上> web-fragments.xml> Struts, Spring 等
• 管理 / 設定が容易> 設定ファイルの複雑さが軽減
Web アプリ開発における拡張性
9
• Java EE の技術を用途毎に分割提供
• 独自プロファイルの開発が可能> 例:電話会社向けプロファイル
• Java EE 6 で提供されるプロファイル> Web プロファイル (Web の開発に特化 )> Enterprise Platform( フル Java EE)
Java EE のサブセットを提供
プロファイル
10
Java EE 6 リリース時に提供される最初の プロファイル
Web 開発に特化した軽量プロファイル
Web プロファイル
• Servlet
• JSP / EL
• JSTL
• JSF
• Bean Validation
• EJB Lite
• JPA
• JTA
• DI/CDI
• Managed Beans
• Interceptors
• Common Annotations
11
仕様の削減 - 2 段階プロセス
• 古く使われなくなった API の整理
• コンポーネントのオプション化
• 次期バージョン (Java EE 7) で オプション化> JAX-RPC(->JAX-WS)> EJB Entity Beans(->JPA)> JAXR> JSR-88
Pruning
12
EJB 3.1
13
EJB 3.1 の主な特徴
• JSR 318• 特徴
> パッケージの簡略化> EJB 3.1 “Lite” の提供> ローカルビジネスインタフェースのオプション化> 移植可能な Global JNDI 名> Java SE に組み込み可能な EJB コンテナ> その他の新機能
EJB 3.1
14
foo.ear
WEB-INF/web.xmlWEB-INF/classes/ com/acme/FooServlet.classWEB-INF/classes
foo_web.war
com/acme/FooBean.classcom/acme/Foo.class
foo_ejb.jar
foo.earlib/foo_common.jarcom/acme/Foo.class
WEB-INF/web.xmlWEB-INF/classes/ com/acme/FooServlet.class
foo_web.war
com/acme/FooBean.class
foo_ejb.jar
OR
パッケージの簡略化
Java EE 5 までのパッケージ構成
適切なアーカイブファイル (ear,war,jar) へのパッケージ化が必要面倒なパッケージング / 作業負担が大
15
Java EE 6 からのパッケージ構成
WEB-INF/classes/com/acme/ FooServlet.class FooBean.class (EJB)
パッケージの簡略化
foo.war
• かんたんなパッケージング• EJB を war ファイルへ含める事が可能
> WEB-INF/classes: ファイルとして> WEB-INF/lib: 分割 jar ファイルとして
• 今まで同様のパッケージ化も可能> ejb-jar ファイル
• 配備記述子はオプション化> 記載する必要がある場合別途 WEB-INF/ejb-jar.xml へ記述可能
16
EJB 3.1 “Lite” の提供
フル Java EE 機能のサブセットを提供
コンポーネント EJB 3.1 Lite Full EJB 3.1
Session Beans(stateful,stateless,singleton) ● ●Message-Driven Bean × ●2.x/1.x CMP/BMP Entity Bean × ●
(pruning)
Java Persistence 2.0 ● ●
17
EJB 3.1 “Lite” の提供
フル Java EE 機能のサブセットを提供
Session Bean クライアントビュー EJB 3.1 Lite Full EJB 3.1Local/No-Intafece ● ●3.0 Remote × ●2.x Remote Home/Component × ●JAX-WS Web Service Endpoint × ●JAX-RPC Web Service Endpoint × ●
(pruning)
18
EJB 3.1 “Lite” の提供
フル Java EE 機能のサブセットを提供
Services EJB 3.1 Lite Full EJB 3.1EJB Timer Service × ●Asynchronous Session Bean Invocation × ●Interceptors ● ●RMI-IIOP Interoperability × ●Container-Managed Transactions / Bean-Managed Transactions ● ●Declarative and Programmatic Security ● ●Embeddable API ● ●
19
EJB 3.0 の実装
クライアントの実装
Local Business Interface のオプション化
public interface Hello { public String sayHello();}
@Statelesspublic class HelloBean implements Hello { public String sayHello() { return “hello”; }}
@EJB private Hello h;
...
h.sayHello();
EJB の定義と実装
インタフェース定義が必須だった
20
EJB 3.1 の実装
クライアントの実装
Local Business Interface のオプション化
@Statelesspublic class HelloBean { public String sayHello() { return “hello”; }}
@EJB private HelloBean h;
...
h.sayHello();
EJB の定義と実装
• EJB の実装がよりかんたんに• Local Business Interface の実装が不必要
21
移植可能な Global JNDI 名Java EE 5 : ベンダー実装依存の Global JNDI 名
• Global JNDI 名はアプリケーションサーバ提供 ベンダー独自に設定していた
• Global JNDI 名を直接記載したコードは移植性が損なわれていた> 他製品へ移行する際 JNDI 名の変更が必要
22
移植可能な Global JNDI 名Java EE 6 :標準化された Global JNDI 名
• Global で唯一の JNDI 名> java:global[/<app-name>]/<module-name>/<ejb-name>
• 同一アプリケーション内で唯一の JNDI 名> java:app/<module-name>/<ejb-name>
• モジュール定義内で唯一の JNDI 名> java:module/<ejb-name>
全ての Session Bean で下記の JNDI 名を持つ
23
移植可能な Global JNDI 名Java EE 6 : サンプル
@Statelesspublic class HelloBean implements Hello {
public String sayHello(String msg) { return “Hello “ + msg; }}
JNDI NAME:java:global/hello/HelloBeanjava:app/hello/HelloBeanjava:module/HelloBean
24
EJB 3.1 で単体テストが容易に
• EJB 3.0 まで> EJB コンポーネントの単体テストは困難> Remote Facade/Web Tier で強制実行> サーバ/クライアントで別プロセスの稼働
• EJB 3.1 から> Java SE に EJB コンテナを組み込むことが可能> JUnit 等で同一 Java プロセス内でテストが可能
Java SE に組み込み可能な EJB コンテナ
25
EJB 3.1 例: Stateless Session Bean クラス
package test;import javax.ejb.Stateless;@Statelesspublic class Hello { public String sayHello(){ return "Hello Embedded TEST"; }}
Java SE に組み込み可能な EJB コンテナ
26
EJB 3.1 例: JUnit単体テスト用コード
@Testpublic void testSayHello() { Map p = new HashMap(); p.put("org.glassfish.ejb.embedded.glassfish.instance.root", "/Applications/GlassFish/glassfishv3-webprofile/glassfish/ domains/domain1"); EJBContainer container = EJBContainer.createEJBContainer(p); try{ Hello hello = (Hello)container.getContext().lookup ("java:global/classes/Hello"); System.out.println(hello.sayHello()); }catch(Exception e){ e.printStackTrace(); }}
Java SE に組み込み可能な EJB コンテナ
27
JUnit : EJB の単体テスト実行
Java SE に組み込み可能な EJB コンテナ
DB 連携の EJB もテスト可能
28
Java SE 単体で稼働させるために必要なライブラリ
Java SE に組み込み可能な EJB コンテナ
• javax.ejb.jar> EJBContainer クラスを含むライブラリ
• glassfish-embedded-static-shell.jar> 組み込み可能な GlassFish ライブラリ
29
新機能
その他の新機能
• Singleton Session Beans の追加> 並列アクセス処理対応> Startup / Shutdown コールバック機能の追加
• タイマーサービス> 自動タイマー生成 / カレンダーベースタイマー
• 非同期処理
30
特徴
• アプリケーションで唯一のインスタンス> 異なる JVM( クラスタ環境 ) でも 1 インスタンスを保障
● GlassFish v3.1 よりクラスタ対応> コンテナの停止時にインスタンスは破棄> 並列アクセスをサポート
• Singleton Session Beans の初期化> 複数の Singleton コンポーネントが存在する場合、コンポーネントの初期化順を規定したい場合、 @DependsOn を使用
Singleton Session Beans
31
Singleton Beans の実装例
@Singletonpublic class SharedBean { private SharedData shared; @PostConstruct private void init() { shared = ...; } public int getXYZ() { return shared.xyz; }
@Stateless public class FooBean { @EJB private SharedBean shared;
public void foo() { int xyz = shared.getXYZ(); … }}
Singleton Bean の実装例 Singleton Bean の利用例
Singleton Session Beans
32
並列アクセス処理用オプション
• コンテナ管理(デフォルト)> @ConcurrencyManagement(CONTAINER)> メソッドにメタデータを記述しアクセス制御 ( ロック ) の指定が可能
● @Lock(READ): 複数アクセスからの読み込みが可能● @Lock(WRITE): 書き込みは単一アクセス
• ビーン管理> @ConcurrencyManagement(BEAN)> 開発者による状態の同期処理、インスタンスのアクセス処理制御が可能
● synchronized,volatile の利用が可能
Singleton Session Beans
※ 両方を使用する事はできない
33
Startup/Shutdown コールバック
@Singleton@Startuppublic class StartupBean {
@PostConstruct private void onStartup() { … }
@PreDestroy private void onShutdown() { … } }
@Startup: コンテナ起動時に初期化無い場合最初のアクセス時に初期化
@PostConstruct:起動時にメソッドを実行
@PreDestroy: 停止時にメソッドを実行
Singleton Session Beans
34
EJB コンテナ管理のタイマーサービス
タイマーサービス
• EJB コンテナが提供するサービス• アノテーションでスケジュールを定義
> @Schedule:単一メッソッドに対するタイマースケジュールを定義> @Schedules:単一メソッドに対して複数の @Schedule を定義する場合に使用
• カレンダー表記でタイマー定義可能> 毎日、毎時、毎分に実行
● (minute="*", hour="*", timezone="Asia/Tokyo")
> 午前9時~午後5時、 30 分毎● (minute="0,30", hour="9-17")
35
サンプルコード
タイマーサービス
@Stateless public class BankBean { @PersistenceContext EntityManager accountDB; @Resource javax.mail.Session mailSession; //毎月最終日午前8時に sendMonthlyBankStatements() を実行 @Schedule(hour=”8”, dayOfMonth=”Last”) void sendMonthlyBankStatements() { ... }}
※@Schedule は void型のメソッドに適用可能@Timeout or @Schedule method must return void and be a no-arg method or take a single javax.ejb.Timer param
36
特徴
非同期処理
• アノテーションでかんたんに非同期処理を定義可能> @Asynchronous:非同期処理の定義> クラスレベル:クラスに含まれる全メソッドの非同期を定義> メソッドレベル:特定のメソッド単位で非同期を定義
• 非同期メソッド定義における返り値の設定> void型:非同期処理で値を返さなくてもよい場合> Future<V>:非同期処理結果を返す必要がある場合
● <V>: 結果の型
37
サンプルコード
非同期処理
@Stateless public class DocBean { @PersistenceContext EntityManager resultsDB; @EJB DocBean myself; public void processDocument(Document document) { myself.doAnalysisA(document); myself.doAnalysisB(document); } @Asynchronous public void doAnalysisA(Document d) {...} @Asynchronous public void doAnalysisB(Document d) {...}
38
EJB 3.1
EJB 3.1 のまとめ
• JSR 318• 特徴
> パッケージの簡略化> EJB 3.1 “Lite” の提供> ローカルビジネスインタフェースのオプション化> 移植可能な Global JNDI 名> Java SE に組み込み可能な EJB コンテナ> その他の新機能
39
http://yoshio3.com/glassfish-関連情報/ より抜粋
Java EE 6 に関する参考情報
• ここから始める Java EE 6> http://tinyurl.com/yhs3mvn
• Servlet 3.0 の新機能概要> http://tinyurl.com/yhft4b6
• Servlet 3.0 File Upload 機能> http://tinyurl.com/28nbdvg
• Servlet 3.0 web-fragment.xml による設定> http://tinyurl.com/yzmtela
• EJB 3.1 の新機能概要> http://tinyurl.com/yerek65
• EJB 3.1 の組み込み可能コンテナ> http://tinyurl.com/y8lvhzn
• GlassFish v3 の OSGi 対応> http://tinyurl.com/2963uly
40
GlassFish v3
41
進化したアプリケーションサーバ
• かんたん開発
• より進化した管理機能
• 次世代アプリケーション
GlassFish v3 のテーマ
42
進化したアプリケーションサーバ
• Java EE 6 のリファレンス実装> 軽量、高速、モジュール化> プロファイルに対応
• マルチ言語対応> Java 、スクリプト言語 (JRuby 等 )
• かんたんな操作> インストール
● unzip,専用インストーラ> 管理、拡張、設定変更、開発
GlassFish v3 の特徴
43
その他の管理機能のアップデート
• 数秒 (10 秒以下 ) で起動MacBook: 2.4GHz Core2Duo/4GB の起動時間約 4.5秒
• 使われない機能の未初期化
• 開発効率の大幅な向上> 再起動による待ち時間の減少
起動時間の劇的な短縮
44
GlassFish v3.0 管理画面
Ajax を使用したユーザフレンドリーな管理画面
GlassFish v3 の管理画面
アップデートツールの統合
45
asadmin redeploy keepSessions=true
再配備時のセッションの保持
• 再配備時にセッションを保存> 開発環境で有効
• コマンドオプション> keepSessions=true
• 統合開発環境と連携> Eclipse> NetBeans
再デプロイ時に毎回再ログインが不必要
46
独自の OSGi バンドル(モジュール)を作成し 管理機能を拡張することも可能
GlassFish (Apache Felix) OSGi コンソール
GlassFish v3 の OSGi 対応
% telnet localhost 6666Trying 127.0.0.1…Connected to localhost.Escape character is ‘^]’.Felix Remote Shell Console:============================-> ps (GlassFish v3で導入されているバンドル一覧 )START LEVEL 1ID State Level Name[ 0] [Active ] [ 0] System Bundle (2.0.2)….. (中略 )[ 245] [Installed ] [ 1] MyBundle (1.0.0)-> start 245-> stop 245-> exitGood Bye!
※独自に実装したバンドルを組み込み動的に アプリケーションサーバの機能を拡張可能 参考: http://tinyurl.com/2963uly
47
GlassFish をライブラリとして利用
• GlassFish Embedded Server API> プログラム内から GlassFish を起動
• Maven Plug-in> Apache Maven との連携> 容易なテストを実現可能
• EJB 3.1 Embeddable API> 容易なテストを実現可能
GlassFish組み込み可能コンテナ
参考 URL:http://tinyurl.com/29vvcxj
48
GlassFish の今後
49
スケジュール案
• GlassFish v3.1 ‒ 2010> クラスタ、中央集中管理機能> DAS の高可用性/リプリケーション> Coherence Support 等
• GlassFish v3.2 ‒ 2011> クラスタ、 HA の改良> 仮想化サポート> Java EE 7 機能の EA 版を提供
• GlassFish v4> Java EE 7 対応
GlassFish の今後のリリース
50
新機能
• クラスタ機能> 大規模クラスタ (50 インスタンス以上 )> SSH Provisioning (NA の廃止 )> アプリケーションバージョニング> ローリングアップグレード
• DAS 管理サーバの高可用性
• 管理監視機能の強化> Dtrace によるモニタリング対応
• WebLogic との互換性を提供> WegLogic DD のサポート
GlassFish v3.1 の新機能
51
GlassFish v2.1 のクラスタ構成• ノードエージェント方式
• ノードエージェントの起動・停止は各マシン上で実施
• create-node-agent コマンドの提供
52
GlassFish v3.1 のクラスタ構成• SSH 方式
> DAS 内に SSH Client ライブラリを統合 (Hudson の成果より )
● Trilead-ssh2 library> 各マシン上で sshd を起動
• システム初期化と DAS への登録
• 将来的な実装予定> 各マシンへのインストールも ssh経由で可能
> Cloud 環境での Provisioning 対応> Auto Scale 対応等
• create-node-ssh コマンドの提供
sshd sshd
SSH Client
Node1 Node2
参考: http://wiki.glassfish.java.net/Wiki.jsp?page=3.1SSHProvisioningDesign
53
同一アプリの複数バージョン
• バージョンの表現> アプリケーション名:バージョン名> 例:
● MyApp:Alpha● MyApp:Beta● MyApp:RC1● MyApp:RC2
• 同一コンテキストで単一バージョンのみ有効
アプリケーションバージョニング
54
コマンド実行例
• バージョン指定のアプリケーション配備> # asadmin deploy --name=foo:1 foo_1.war
• 無効化バージョンの配備> # asadmin deploy --enable=false
--name=foo:2 foo_2.war
• アプリケーションの有効 (無効 ) 化> # asadmin enable(disable) foo:2
• 配備済みリストの表示> # asadmin list-applications --verbose=true
アプリケーションバージョニング
55
削除機能
• ノードエージェントを廃止
• HADB を廃止> In-memory,Coherence
• JBI コンテナ
• Web Service Management
• 自己管理機能
• 呼び出しフロー
• 一部のコマンドの削除> start-appserv,stop-appserv 等
GlassFish v3.1 で削除される機能
56
スケジュール案
• M1: プランニング完了 (5/24)
• M5: 全ての機能実装完了 (9/13)
• JavaOne 開催 (9/19-9/23)
• v3.1 リリース (12/14)※スケジュール案は下記 URL に記載されている内容 に基づき記載しています。スケジュールは状況により 変更される可能性があります。
GlassFish v3.1 スケジュール:
http://tinyurl.com/27jyfgc
GlassFish v3.1 ロードマップ(ドラフト)
57
参考情報 URL 一覧
• GlassFish v3.1 プラン> http://tinyurl.com/29mjk8o
• GlassFish v3.1 機能リスト> http://tinyurl.com/y45kxqn
• GlassFish v3.1 クラスタ機能> http://tinyurl.com/ye9qsg5
• GlassFish v3.1 スケジュール> http://tinyurl.com/27jyfgc
GlassFish v3.1 の参考情報
58
まとめ
59
今日のポイント• Java EE 6 でかんたん開発がさらに進化しました
> 乱雑な XML 設定ファイルの編集は不必要
• 開発効率が大幅に向上しました> コード編集 /保存したらすぐ動作確認
● 手動の再配備やサーバの再起動は不必要
> 再配備時にセッション情報を保持 ( 再ログインは不必要 )> 待ち時間 ( 再起動等 ) が大幅に短縮
• GlassFish v3 のインストールはとてもかんたんです> zip版を利用すると unzip でインストール完了> サーバの起動は数秒以内で完了
• GlassFish v3.1 は本番環境向けの機能を提供します
6060
GlassFish v3 で実感!!エンタープライズ Java の進化
Yoshio TeradaGlassFish エバンジェリストSun Microsystems K.K.http://yoshio3.com
61
参考資料
62
Servlet 3.0
63
Servlet 3.0 の主な特徴
• JSR-315
• 特徴> かんたん開発> 拡張性> マルチパート対応
● ファイルアップロード
> 非同期サポート> セキュリティ
Servlet 3.0
64
かんたん開発
• Java SE 5の言語使用を利用> アノテーションを利用した宣言的 プログラミングモデル
> ジェネリクスを利用した型の安全性
概要
65
かんたん開発
• @WebServlet
• @WebFilter
• @WebListener
• @WebInitParam
• @ServletSecurity
• @MultipartConfig
アノテーション
‒ Servlet の定義
‒フィルタの定義‒リスナの定義
‒パラメータの定義
‒セキュリティの制約‒ファイルアップロード
web.xml はオプション化
アノテーションの設定は web.xml で上書き設定可能
66
package hello; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@WebServlet(name="Hello", urlPatterns={"/Hello"}) public class Hello extends HttpServlet {
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ....... } }
Servlet 3.0 のサンプルアノテーションを利用したプログラミング
<web-app> <servlet> <servlet-name>Hello</servlet-name> <servlet-class>hello.Hello</servlet-class> </servlet> <servlet-mapping> <servlet-name>Hello</servlet-name> <url-pattern>/Hello/* </url-pattern> </servlet-mapping>... </web-app>
(Servlet 2.5まで必要 )
67
拡張性
• 静的コンテンツ /JSP 等のリソースを 外出し可能
• WEB-INF/lib 配下の jar ファイルにMETA-INF/resources を作成> コンテキストルートでアクセス可能
モジュール型の開発
例:WEB-INF/lib/resources.jar > jar tvf resources.jar META-INF/ META-INF/MANIFEST.MF META-INF/resources/ META-INF/resources/test.html例: http://www.oracle.com/test.html
68
拡張性フレームワークの追加が容易
• 設定ファイルによる拡張> web-fragments.xml> 外部ライブラリ、フレームワークをweb.xml とは別の設定ファイルで管理
> ライブラリの呼び出し順を設定可能
• プログラムによる拡張> サーブレット、フィルタ等をサーブレット初期化時に設定可能
69
例:フラグメントアーカイブの作成 WEB-INF/lib/jsf-fragment.jar > jar tvf jsf-fragment.jar META-INF/ META-INF/MANIFEST.MF META-INF/web-fragment.xml
<web-fragment> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping></web-fragment>
設定ファイルによるコンテナの拡張
フラグメントアーカイブの作成web.xml への記載は不要web.xml の肥大化を抑制
フラグメントファイルの作成( JSF の場合)web.xml への記載内容と同様
web-fragment.xml で外部フレームワークの設定を管理
70
プログラムによるコンテナの拡張
• ServletContainerInitializer > インタフェースを実装しコンテナを拡張> 起動時に1度だけ実装クラスを検知
• @HandlesTypes > ServletContainerInitializer がハンドル可能な型を宣言
• ServletContext> 動的に servlet/filter の登録等が可能
Servlet 3.0
71
プログラムによるコンテナの拡張例
コンテナ拡張コードは META-INF/services へ配置
@HandlesTypes(WebService.class)class JAXWSServletContainerInitializer implements ServletContainerInitializer{ public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException { // 実行時の初期化やマッピング等の JAX-WS 固有の // 設定等をここで実装 ServletRegistration reg = ctx.addServlet("JAXWSServlet", "com.sun.webservice.JAXWSServlet"); reg.addServletMapping("/foo"); }}
72
マルチパート対応
サンプルプログラム
<FORM action=”/MyFileUpload” enctype=”multipart/form-data” method=”POST”>ファイル名: <INPUT type=”file” name=”content”> <INPUT type=”submit” value=”Submit”> </FORM>
@WebServlet( name = ”MyFileUpload”, urlPatterns = {“/MyFileUpload”}) @MultipartConfig( fileSizeThreshold=5000000, MaxFileSize=10000000, location=”/tmp”) public class MyFileUpload extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // <INPUT type=”file” name=”content”>より取得 Part part = request.getPart(“content”); // Content-Disposition ヘッダを解析し // ファイル名の取得 String fname = getFilename(part); // @MultipartConfig(location=”/tmp”) で設定した // ディレクトリ配下に保存 part.write(fname);
• <INPUT TYPE=”file” name=”fname”> でマルチパートフォームを記載
• HttpServletRequest#getPart(“fname”)でマルチパートデータを取得> フォーム名に一致するデータを取得
• HTTP ヘッダよりファイル名を取得
> Content-Disposition: form-data; name=”content”; filename=”FILE_NAME”
73
非同期処理の概要
• 非同期リクエスト処理用のプログラムモデル> 例: Comet, chat, push apps
• 長時間処理が必要なリクエストに有効> スレッドを別処理に再利用可能> スレッドを1クライアント毎に保持する必要無し
• Async 用アノテーションを追加> @WebServlet(asyncSupported=true)
Servlet 3.0
74
非同期処理の実装例
@WebServlet(name="CalculatorServlet", asyncSupported=true, urlPatterns={"/calc", "/getVal"})public class CalculatorServlet extends HttpServlet{ public void doGet(HttpServletRequest req, HttpServletResponse res) { ... AsyncContext aCtx = req.startAsync(req, res); } }
サンプルプログラム
75
セキュリティ
Servlet でログイン / ログアウト機能を実現
• 新しい認証方式を提供> <form action="j_security_check" method="post"> の代わりに使用
• 認証 / ログイン / ログアウト機能の提供 > HttpServletRequest.authenticate> HttpServletRequest.login> HttpServletRequest.logout
• アノテーションによる宣言> @ServletSecurity
76
JPA 2.0
77
Java Persistence API
JPA 2.0 の新機能概要
• EJB から独立 (JSR-317)• JPA 2.0 = JPA 1.0 + α
> モデリングの強化> JPQL 新しい構文の追加> Criteria API の提供
● メタモデル API の提供
> 悲観的ロックの追加> バリデーションのサポート> 設定オプションの標準化
78
モデリングの強化
JPA 2.0 の新機能概要
• コレクションのサポート> 基本型のコレクション> Embeddable のコレクション> 多段レベルの組み込み> 関連性を持った組み込み> Map サポートの強化> 順序付けリストのサポート
79
基本型のコレクションの例
@Entitypublic class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; @ElementCollection private Set<String> nickname;
デフォルト:EntityName_FIELDNAME テーブルとマップ
PERSON
PK ID Name
PERSON_NICKNAME
Person_ID NICKNAME
モデリングの強化
80
@Entitypublic class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; @ElementCollection @CollectionTable(name="NICKNAMES") @Column(name="aliases") private Set<String> nickname;
マップするテーブル名とカラム名の指定が可能
基本型のコレクションの例
PERSON
PK ID Name
NICKNAMES
Person_ID aliases
モデリングの強化
81
@Embeddablepublic class Address{ private String street; private String town; private String city; private String prefecture;}@Entitypublic class Person { @ElementCollection private Set<Address> addresses;}
組み込み可能型コレクションの例
PERSON
PK ID Name
PERSON_ADDRESS
Person_ID street town city prefecture
EntityName_FIELDNAME テーブルとマップ ( 名前は変更可能 )
モデリングの強化
82
@Embeddablepublic class ContactInfo { @Embedded Address addresses;}@Entitypublic class Person { @Id private Long id; private String name; private ContactInfo contactInfo;
多段レベルの組み込み例
PERSON
PK ID name street town city prefecture
EntityName_FIELDNAME テーブルとマップ ( 名前は変更可能 )
組み込みオブジェクト中の組み込みオブジェクト
モデリングの強化
83
関連性を持つテーブル組み込み例
@Embeddable public class ContactInfo { @Embedded Address addresses; @OneToMany Set<Phone> phone;}@Entity public class Person { @Id private Long id; private String name; private ContactInfo contactInfo;
PHONE
PK PHONENUMBER PHONETYPE
PERSON
PK ID name ...( 省略 )
PERSON_PHONE
PK PERSON_IDPK PHONE_PHONENUMBER
モデリングの強化
84
Map の Collection
• JPA1.0 の Map> 限定的に使用可能> Entityの属性を Map のキーとして利用 , 値は Entity
• JPA 2.0 の Map> 柔軟性が向上> キー、値共に Basic型 , Embeddable 型 , Entity 型の使用が可能
モデリングの強化
85
JPA 1.0 の Map
• @MapKeyのみ利用可能> Entity内の属性を Map のキーとして利用し、 value はEntityオブジェクト@Entity public class Person{ @OneToMany(mappedBy="owner") @MapKey(name="phone_type") private Map<String, PhoneNumber> phoneNumbers; …@Entitypublic class PhoneNumber{ @Basic private String phone_type; @ManyToOne private Person owner;
モデリングの強化
86
JPA 2.0 で可能な Map の種類とアノテーション
Mapping
Map<Basic,Basic> @ElementCollection @Column
Map<Basic,Embeddable> @ElementCollection
Map<Basic,Entity> @OneToMany,@ManyToMany
Map<Embeddable,Basic> @ElementCollection @Column
Map<Embeddable,Embeddable> @ElementCollection
Map<Embeddable,Entity> @OneToMany,@ManyToManyMap<Entity,Basic> @ElementCollection @MapKeyJoinColumn @Column
Map<Entity,Embeddable> @ElementCollection @MapKeyJoinColumn
Map<Entity,Entity> @OneToMany,@ManyToMany @MapKeyJoinColumn
Mapの種類 Keyのアノテーション Valueのアノテーション@MapKeyColumn@MapKeyEnumerated@MapKeyTemporal@MapKeyColumn@MapKeyEnumerated@MapKeyTemporal
Embeddableでマップ@AttrivuteOverride@AssociationOverride
@MapKey@MapKeyColumn@MapKeyEnumerated@MapKeyTemporal
Entityでマップ
Embeddableでマップ@AttrbuteOverride
Embeddableでマップ@AttrbuteOverride
Embeddableでマップ@AttrivuteOverride@AssociationOverride
Embeddableでマップ Entityでマップ
Embeddableでマップ@AttrivuteOverride@AssociationOverrideEntityでマップ
モデリングの強化
87
Map の Collection: Basic 型のキー
@Entitypublic class Customer{ @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String firstName; .... @ElementCollection @CollectionTable(name=”**”)キー :@MapKeyColumn(name=”**”) @Column(name=”**”) private Map<String,String> phoneNumber;
Customer_PHONENUBER
PK,FK1 Customer_IDPK PHONENUMBER_KEY
PHONENUMBER
デフォルトの名前を変更可能 (各色に対応)
モデリングの強化
88
Map の Collection: Enumeration のキー
@Entitypublic class Customer{ .... @ElementCollection @CollectionTable @MapKeyEnumerated(EnumType.STRING) @MapKeyColumn @Column private Map<PhoneType,String> phoneNumber; .....}public enum PhoneType{Mobile, Home, Company}
キーで扱う文字列の数が少ない場合、String の代わりに Enumerated を使用し効率化可能
モデリングの強化
89
OrderList
JPA 1.0 の Order(検索結果からオーダを生成 )
@OrderBy: 検索結果から動的にオーダを生成
@EntityPublic class Project { .... @OneToMany @OrderBy(“lastname DESC( 昇順 ),phonenumber ASC(降順) ) private List<Person> person;}@Entitypublic class Person { .... private String lastname; private String phonenumber;}
90
OrderList
JPA 2.0 の Order(永続化されるオーダ )
@Entitypublic class CreditCard {
@Id long ccNumber; @OneToMany // unidirectional @OrderColumn List<CardTransaction> transactionHistory; ...}
• @OrderColumn> インサート、アップデート、デリート時等において恒久的に
永続化> OneToMany,ManyToMany で利用可能
91
Automatic Orphan Deletion
カスケード削除 (Orphan Deletion)
• DB レコードの連鎖削除> 関連性のあるエンティティが削除された際、孤児となったエンティティを自動削除
> @OneToOne, @OneToManyに適用可能> cascade=CascadeType.REMOVE は不必要@Entity public class Order { @Id int orderId; ... @OneToMany(cascade=PERSIST, orphanRemoval=true ) Set<Item> lineItems;
92
Java Persistence Query Language
JPA 2.0 の JPQL の追加機能
• 新しく追加されたモデリングとマップ機能に対応> Select List の操作機能> CASE,COALESCE,NULLIF 表現の追加> Restricted polymorphism> IN 表現におけるコレクション -値パラメータ
93
JPA 2.0 で追加された演算子
• INDEX> ORDERED LIST で使用
• KEY, VALUE, ENTRY> MAP で使用
• CASE, COALESCE, NULLIF> CASE表現で使用
• TYPE> Restricted Polymorphism で使用
Java Persistence Query Language
94
OrderedList で使用する INDEX
Java Persistence Query Language
SELECT tFROM CreditCard c JOIN c.transactions tWHERE c.cardHolder.name = 'John Doe' AND INDEX(t) < 10
95
Map で使用する KEY,VALUE
Java Persistence Query Language
// Inventory is Map<Movie,Integer>
SELECT v.location.street, KEY(i).title, VALUE(i)FROM VideoStore v JOIN v.inventory iWHERE KEY(i).director LIKE '%Hitchcock%' AND VALUE(i) > 0
96
ANSI SQL-92 CASE Expression 対応
検索結果を変更したい場合、テーブル定義の変更ができない場合に有効
• CASE> CASE{WHEN <cond_exp> THEN <scalar_expr>} + ELSE <scalar_exp> END
• COALESCE> COALESCE(<scalar_exp> {,<scalar_expr>} + )
• NULLIF> NULLIF(<scalar_expr1>, <scalar_expr2>)
Java Persistence Query Language
97
CASE式の利用例
給料の昇級額の計算UPDATE Employee eSET e.salary = CASE e.rating WHEN 1 THEN e.salary * 1.2 WHEN 2 THEN e.salary * 1.1 ELSE e.salary * 1.02 END
社員の評価レートが1の場合基本給の 1.2倍 社員の評価レートが 2 の場合基本給の 1.1倍 それ以外は、 1.02倍
Java Persistence Query Language
98
TYPE Expression
継承した Entityの内、特定の Entityの取得が可能SELECT eFROM Employee eWHERE TYPE(e) IN (Contractor)
Employee
Regular Contractor
TYPE には Java の Entityクラスを指定
Java Persistence Query Language
99
Criteria API
JPQL の代わりにプログラミングでクエリーを記載
• クエリーの制御を Java オブジェクトで制御> JPA1.0 では JPQL/Native SQL でクエリーを記載> JPQL で可能なことはプログラム上で実現可能
• Criteria API はクエリー実行結果の型の安全性が向上> クエリー実行におけるランタイムエラーの発生率が減少> 統合開発環境の型チェックを利用し安全に実装可能
• JPQL は SQL に精通した開発者に有効> 統合開発環境が自動的に雛形を生成(開発効率の向上)
• 開発者に選択肢を提供> オブジェクトベース、文字列ベースのクエリーを提供
100
Criteria API
Criteria API の主なインタフェース
• CriteriaBuilder : > CriteriaQueryオブジェクトを生成するファクトリ> EntityManager#getCriteriaBuilder() より取得
• CriteriaQuery : > クエリーの実行結果の型を返す> <T> CriteriaQuery<T> createQuery(Class<T> resultClass)
• Root :> クエリーの範囲指定
• その他> Join, ListJoin, MapJoin, Path, Subquery など
101
Criteria API
Criteria API の実装と対応する JPQL のサンプル
EntityManager em = … ; CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Person> p = cb.createQuery(Person.class); Root<Person> person = p.from(Person.class); p.select(person).where( cb.equal(person.get(“name”),”Taro Yamada”));
SELECT p FROM Person p WHERE p.name = 'Taro Yamada'
Criteria API を使用した実装例
JPQL による記載例
102
Metamodel API
Metamodel API でさらにタイプセーフに
• 強力な型チェックを可能> ランタイムエラーの排除
● 文字列によるエンティティの属性へのアクセスを排除> コンパイル時に属性の有無、型チェックを実施
• Metamodel クラスの生成> _ を付加した正規化した Metamodel クラスを生成
● IDE で自動生成(※ NetBeans は Ver 6.9 より)> プログラム上で動的に生成
103
Metamodel API
Metamodel API でさらにタイプセーフに
• 属性の文字列操作はランタイムエラーの可能性台
EntityManager em = … ; CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Person> p = cb.createQuery(Person.class); Root<Person> person = p.from(Person.class); p.select(person).where( cb.equal(person.get(“name”),”Taro Yamada”));
問題:“ name” が存在しない場合、もしくは型が異なる (String 型でない ) 場合ランタイムエラーが発生
104
正規化された Metamodelクラス
• _ を付けた Metamodel クラスを生成@Entitypublic class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; Private Integer age;
import javax.persistence.metamodel .SingularAttribute;@javax.persistence.metamodel.StaticMetaModel(Person.class)public class Person_ { public static volatile SingularAttribute<Person,Long> id; public static volatile SingularAttribute<Person,String> name; public static volatile SingularAttribute<Person,Integer> age;
Entity クラス
Metamodel クラス
Metamodel API
105
動的に Metamodelクラスを取得することも可能
• プログラム中で動的に Metamodel クラスを生成可能
EntityManager em = ...;
Metamodel meta = em.getMetaModel();
EntityType<Person> Person_ = meta.entity(Person.class);
Metamodel API
106
Criteria API をさらにタイプセーフに
• 属性の文字列操作はランタイムエラーの可能性台
EntityManager em = … ; CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Person> p = cb.createQuery(Person.class); Root<Person> person = p.from(Person.class); p.select(person).where( cb.equal(person.get(Person_.name),”Taro Yamada”));
解決: Person_.name の有無、型チェックをコンパイル時に可能 ( IDE の強力な型チェックでランタイムエラーを抑制)
※ NetBeans は Ver 6.9 より利用可能
Metamodel API
107
悲観的ロック
JPA が提供するロック
• JPA1.0> 楽観的ロック
● 操作している情報は他が操作する可能性が少ない場合に利用
• JPA 2.0> 悲観的ロック
● 操作している情報を他が操作する可能性がある場合に利用● 用途を明確にして使用しなければパフォーマンスに悪影響
108
悲観的ロック
• 悲観的ロックの使用
em.lock(person, LockModeType.PESSIMISTIC_WRITE);
• LockModeType.PESSIMISTIC_READ> 共有ロック
• LockModeType.PESSIMISTIC_WRITE> 排他ロック
• トランザクションが存在しない場合> TransactionRequiredExceptionをスロー
109
Bean Validation
Bean Validation (JSR-303)
@Entity public class Employee { @Id Integer empId; String name; @Max(15) Integer vacationDays; @Valid Address worksite; ...}
@Embeddable public class Address { @Size(max=30) String street; @Size(max=20) String city; @Zipcode String zipcode; ...}
• Entity レベルでバリデーションを実現
@[email protected]@Min/@Max@Future/@Past@Size等の利用が可能
110
2 次(共有)キャッシュのサポート
JPA 1.0 と JPA 2.0 のキャッシュ
• JPA 1.0 (1次キャッシュ)> 単一の Persistence Context のエンティティに対するキャッシュを利用可能
> EntityManager がエンティティを管理
• JPA 2.0 (2次キャッシュ)> JPA 1.0 ではベンダが独自に提供していたがJPA 2.0 で標準化
> 複数の Persistence Context のエンティティのキャッシュを共有し利用可能
> EntityManagerFactoryから Cache API を利用可能
Level 2 Cache(共有 Cache)
Transaction
PersistenceContext
Transaction
PersistenceContext
111
2 次(共有)キャッシュのサポート
2次キャッシュの利点
• 利点> 一度読み込んだエンティティへのアクセスが高速 /DB 負荷軽減> 読み込みが多く、修正が頻繁でないエンティティへのアクセスが
多い場合に有効
• 欠点> 大量のオブジェクトを使用した場合、メモリを大量に消費> 更新されたデータに対して古いデータを参照する場合がある> 並列書き込み時に考慮が必要(ロック)> スケーラビリティが低下
112
2 次(共有)キャッシュのサポート
設定によるキャッシュ動作の違い
設定 動作
ALL
NONE 全てをキャッシュしない
ENABLE_SELECTIVE
DISABLE_SELECTIVE
全てをキャッシュ (EclipseLinkの場合デフォルトでこの設定が有効)
@Cacheable(true)が設定されたエンティティをキャッシュする
@Cacheable(false)が指定されたエンティティ以外全てをキャッシュする
persistence.xml の <shared-cache-mode> 要素の設定
113
2 次(共有)キャッシュのサポート
EclipseLink における @Cache を使用した L2 キャッシュの設定
@Entity@Cache(type=CacheType.WEAK, isolated=false, expiry=60000, alwaysRefresh=true, disableHits=true, coordinationType=INVALIDATE_CHANGE_OBJECTS)@Cacheable(true)public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;
TYPE=FULL: 削除されるまでフラッシュされないTYPE=WEAK: 参照がなくなるとガベージコレクション
isolated=true に設定した場合 L2 キャッシュを無効化
114
2 次(共有)キャッシュのサポート
クエリーにおけるキャッシュ動作の設定
• Cache Retrive (検索 ) モード> javax.persistence.cache.retrieveMode
● BYPASS :キャッシュを無視し DB より結果を取得● USE :キャッシュを利用(既にキャッシュ内に存在する場合)
• Cache Store ( 保存 ) モード> javax.persistence.cache.storeMode
● BYPASS : キャッシュを更新せず、 DB に直接保存● REFRESH : 既存キャッシュをリフレッシュ /置換● USE : キャッシュを更新しコミット時に DB に反映
115
public List<Person> findPersons(){ TypedQuery<Person> query = em.createQuery(“SELECT p ...”); query.setProperty("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS); query.setProperty("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH); return query.getResultList();}
2 次(共有)キャッシュのサポート
※ 1: REFRESHはデフォルトの設定のため記載する必要なし※ 2:全ての検索で BYPASS するとキャッシュの意味はなし (用途の検討が必要)
クエリーにおけるキャッシュ動作の実装例
116
設定オプションの標準化
Java SE で利用する際の persistence.xml 設定項目の標準化
• JPA 1.0 ではベンダー固有の設定が必要> JDBC ドライバ、 URL 、ユーザ名、パスワード等<property name="eclipselink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/><property name="eclipselink.jdbc.url" value="jdbc:derby://localhost:1527/Sample;create=true"/><property name="eclipselink.jdbc.user" value="APP"/><property name="eclipselink.jdbc.password" value="APP"/>
例: JPA1.0 で EclipseLinkを使用する際の persistence.xml の設定
117
設定オプションの標準化
Java SE で利用する際の persistence.xml 設定項目の標準化
• JPA 2.0 では設定項目が標準化> EclipseLink、 Hibernate 、 OpenJPA 等での移植性が向上 <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/Sample;create=true"/> <property name="javax.persistence.jdbc.user" value="APP"/> <property name="javax.persistence.jdbc.password" value="APP"/>
例: JPA2.0 で標準化された persistence.xml の設定項目
118118
GlassFish v3 で実感!!エンタープライズ Java の進化
Yoshio TeradaGlassFish エバンジェリストSun Microsystems K.K.http://yoshio3.com