JSF 2.0 : ブックマーク可能な URL (GET リクエスト) のサポートと動的パラメータ設定
今回紹介する機能は恐らく多くの JSF の開発者が求めてきた機能の一つかと想定しますが、JSF 1.2 までは画面遷移を行う際 h:commandLink, h:commandButton を使用して POST による遷移しかできませんでした。しかし JSF 2.0 からは GET による画面遷移も可能になりました。GET による画面遷移を行うためには、h:link, h:button を利用します。また、これらのタグは JSF のナビゲーションルールに従い画面遷移ができるようになっています。
例えば、JSF 1.2 では下記のように直接遷移先の URL をコード中に埋め込んでいました。
<h:link value="next.xhtml" value="リンク"/>
しかし、JSF 2.0 からは h:link, h:button の2つのコンポーネントに対して outcome の属性を指定し遷移先の view ID を指定しナビゲーションルールを設定できるようになりました。例えば、下記のように記載します。
<h:link outcome="viewEntry" value="リンク"/>

この際、上記の「リンク」をクリックすると下記のコンテンツが表示されます。
http://localhost:8080/JSF-Bookmark/faces/viewEntry.xhtml

これは faces-config.xml にナビゲーションルールを記載していないため、デフォルトの遷移先である vewEntry.xhtml に遷移しています。また、EL 式で CDI/Managed Bean のメソッドを指定する事で動的に遷移先を変更する事も可能です。下記の例では、SomeBean#entry() メソッドが呼び出されるため、entry() メソッドでは遷移先の view ID を文字列で返す必要があります。ちなみに outcome の属性はページ内にリンクを記載するため、必ず画面がレンダリングされる前に評価されます。
<h:link outcome="#{someBean.entry}" value="リンク"/>
URL パラメータの指定
次に、HTTP リクエストに対してパラメータを指定する方法を紹介します。GET メソッドにパラメータを付加するためには下記の何れかの方法で行います。
- outcome 属性に直接記載(画面遷移時に使用)
- View Parameters の使用(アクセス時に使用)
- f:param タグの使用(画面遷移時に使用)
まず、画面遷移時に利用可能な outcome 属性に直接記載する方法ですが、下記のように記載します。複数のパラメータを指定する際は、&amp; を記載します。
<h:link outcome="viewEntry?query=10&result=5" value="リンク"/>
また、下記のように outcome 属性中に EL 式を記載する事も可能です。
<h:link outcome="viewEntry?query=#{someBean.query}" value="リンク"/>
次にアクセス時に利用可能な View Parameter を紹介します。JSF 2.0 では View のパラメータを扱うために特別な UIInput コンポーネント UIViewParameter を追加しました。UIViewParameter は UIInput を継承しているため、他の通常のコンポーネントと同様にコンバータやバリデータを扱う事ができます。また EL 式を記載する事ができ動的な値を扱う事もできます。UIViewParameter を使うためには f:metadata 中で <f:viewParam/> を追加して使用してください。f:viewParam の使用例を下記に示します。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:metadata>
<f:viewParam id="data" name="data" value="#{someBean.data}" />
</f:metadata>
<h:head>
<title>Sample</title>
</h:head>
<h:body>
<h:link outcome="viewEntry" value="リンク"/> #{' '}
<br/>
<h:outputLabel value="#{someBean.data}"/>
</h:body>
</html>
f:viewParam で指定した Managed Bean を下記に示します。
package managed;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class SomeBean {
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
このページにアクセスする際は、URL の引数に ?data=foobar を付加してアクセスします。
http://localhost:8080/pathToWebapp/view.xhtml?data=foobar

すると、myBean の setData() が呼び出され data に対して foobar が セットされます。そして画面をレンダリングする際、myBean#getData() が呼び出され、data にセットした foobar という文字列が表示されるようになります。URL の引数指定 (?data=foobar) を必須にしたい場合は、required=”true” を付加します。これを指定すると引数が指定されていない場合は例外が出力されます。
<f:metadata>
<f:viewParam id="data" name="data" value="#{someBean.data}" required="true"/>
</f:metadata>

さらに、前述したようにバリデーションを記載する事も可能なため、下記のように View Parameter に指定する文字列の長さも検証する事が可能になります。
<f:metadata>
<f:viewParam id="fname" name="data" value="#{someBean.data}" required="true">
<f:validateLength minimum="5" />
</f:viewParam>
</f:metadata>

※ デフォルトで表示される翻訳されたエラーメッセージはひどいのですが、エラーメッセージは独自の内容に変更する事が可能です。
最後に画面遷移をする際に利用する f:param タグの使用方法を紹介します。
f:param は他の画面に遷移する際 URL に付加するパラメータを組み込んで画面遷移ができるようになります。例えば、下記のコードを記載した場合を想定してください。
<h:link outcome="viewEntry" value="リンク">
<f:param name="getParam" value="getValue"/>
</h:link>
実行して「リンク」を押下すると、下記の URL に遷移し URL にパラメータが指定できている事がわかります。
http://localhost:8080/JSF-Bookmark/faces/viewEntry.xhtml?getParam=getValue

また、ナビゲーションルールを faces-config.xml の設定ファイルに記載したい場合は下記のように設定ファイルを記載する事でナビゲーションルールを記載する事もできます。
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>viewEntry</from-outcome>
<to-view-id>/page2.xhtml</to-view-id>
<redirect>
<view-param>
<name>getParam</name>
<value>#{someBean.value}</value>
</view-param>
</redirect>
</navigation-case>
</navigation-rule>
上記のように、f:param は別の画面に遷移する際にパラメータを指定できる事がわかります。
最後に、JSF 2.0 は JAX-RS で提供する全メソッドには対応しておりませんが、GET アクセスで Bookmark 可能なサイトを構築するために最低限必要な機能を兼ね備えています。またここに記載した内容を使って、GET/POST のリクエスト間でデータ交換等もできるようになります、JSF 1.2 の頃に比べるとかなり簡単になったリクエスト処理を是非お試しください。
統計情報にみる人気記事
http://blogs.sun.com/yosshi から http://yoshio3.com に移動したのは昨年の2月なのですが、1 年が経過し統計情報をまとめて見たいと思います。
http://yoshio3.com へは1年間のトータルで 60,908 のアクセスがありました。単純に割ると 170 view/日 なのですが、週末のアクセスは激減するので週末を除くと平均 200-300 view/日位になります。ブログエントリをご参照頂いた皆様誠にありがとうございました。この1年間もブログ記事をいくつか書きましたが人気コンテンツを上から順にまとめてみます。仮にこの中で見落としているコンテンツ等があれば是非一度確認してみてください。
人気コンテンツ Top 20:
- ホームページ [23,024 hit]
- ここから始める Java EE 6 [2,982 hit]
- GlassFish 関連 [2,776 hit]
- Servlet 3.0 の新機能概要 [1,787 hit]
- 自己紹介 [1,636 hit]
- EJB 3.1 の新機能概要 [1,526 hit]
- GlassFish データベースの設定 [1,395 hit]
- Servlet 3.0 File Upload 機能 [1,368 hit]
- GlassFish ドメイン管理(作成、削除、起動、停止) [1,076 hit]
- EJB 3.1 の組み込み可能コンテナ [877 hit]
- GlassFish v2.1.1 と GlassFish v3.0.1 の機能比較 [863 hit]
- Java EE の向かう先 [845 hit]
- GlassFish v3.1 の新機能概要 [736 hit]
- GlassFish ドメイン管理の基本 [711 hit]
- Java Hot Topic セミナー緊急開催決定 [687 hit]
- Servlet 3.0 web-fragment.xml による設定 [662 hit]
- GlassFish SSLの設定 (サーバ証明書の設定) [657 hit]
- JavaOne 2010 キーノート概要紹介 [650 hit]
- GlassFish v3.1 の各種仕様公開 [618 hit]
- Web Server関連 [598 hit]
人気検索キーワード Top 20:
- servlet 3.0 [966 hit]
- java ee 6 [445 hit]
- ejb 3.1 [204 hit]
- javaone 2010 [164 hit]
- javaee6 [160 hit]
- java ee6 [133 hit]
- glassfish 3.1 [128 hit]
- 寺田佳央 [124 hit]
- glassfish ssl [121 hit]
- glassfish [112 hit]
- glassfish v3.1 [106 hit]
- glassfish tomcat 比較 [98 hit]
- ejb [98 hit]
- javaone [97 hit]
- glassfish v3 [81 hit]
- glassfish ssl 設定 [66 hit]
- glassfish クラスタ[63 hit]
- glassfish tomcat [63 hit]
- glassfish domain [62 hit]
- glassfish ドメイン [58 hit]
今まで GlassFish/Java EE を担当してきたので、Java EE に関連する情報、 GlassFish に関する情報が多くあります。まぁ、それ関連のネタしか書いていなかったのですが。(^_^;) 一点、統計情報を確認し、予期してなくて驚いたのが Servlet 3.0 についての情報を参照されていらっしゃる方が思ったよりも多かったという事でした。
今後は、Java SE に関する情報ももっと増やしていきたいと思っています。Java SE に関する情報は4月頃から増やして行きたいと考えておりますので、今暫くお待ちください。
今後もご支援の程宜しくお願いします。
Java 開発者向け情報サイト OTN
日本オラクルでは、Oracle Technology Network (通称 OTN) で Java 開発者の皆様向けの情報を提供しています。現在は英語コンテンツが多いですが、今後日本語に翻訳されたコンテンツ等を提供していく予定です。
現在、OTN では Java の開発者向けのサイトを構築するにあたり、Java の開発者の皆様からこのようなサイトにして欲しい等のご要望、アンケートを承っています。またアンケートにお答え頂いた先着200名の皆様に卓上カレンダーを贈呈致しますので是非開発者の皆様のご要望、ご意見を頂ければと思っております。
仮に、アンケートが終了した場合、もしくはアンケートに記載できなかった場合は、本ブログへご要望、ご意見等をください。OTN サイト構築の際に参考にさせて頂きますので、いずれの方法でも結構ですので開発者の皆様の声を是非日本オラクルまでお届けください。
どうぞ宜しくお願いします。
JSF 2.0 で Facelets タグをコメントする方法
今日は、JSF 2.0 の Facelets でコンポーネントタグをコメントする方法をご紹介します。テスト用のコードを記載する際、デバッグ用のコード、もしくはダミーのコードを埋め込んだりする事があるかと思いますが、本番環境での表示には必要ないコンポーネントをコメントする方法を下記に紹介します。
まず、始めに、下記のようなサンプルページを作成してください。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:commandButton action="#{user.login_dummy}" value="Submit-Dummy"/><br/>
<h:commandButton action="#{user.login}" value="Submit"/>
</h:body>
</html>
CDI の UserBean.java
package jp.co.oracle.cdi;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.inject.Named;
@Named("user")
@SessionScoped
public class UserBean implements Serializable{
public void login(){
;
}
public void login_dummy(){
;
}
}
今回は上記コード中の「Submit-Dummy」ボタンをコメントします。何も考えず、通常通り HTML/XML のコメント(<!– –>)を使って下記のようにコメントをして実行してください。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<!-- <h:commandButton action="#{user.login_dummy}" value="Submit-Dummy"/><br/> -->
<h:commandButton action="#{user.login}" value="Submit"/>
</h:body>
</html>
すると、下記のようなエラーが表示されます。

致命的: Error Rendering View[/comentSample.xhtml]
javax.el.PropertyNotFoundException: The class ‘jp.co.oracle.cdi.org$jboss$weld$bean-$Users$yt133043$NetBeansProjects$JSFSampleApplication$build$web$-ManagedBean-class_jp$co$oracle$cdi$UserBean_$$_WeldClientProxy’ does not have the property ‘login_dummy’.
警告: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
これは、通常の XML/HTML のコメントのように、<!– –> でコメントしても JSF 2.0 の実行環境では完全にコメントできていない事を表しています。内部的には、 #{user.login_dummy}の EL式が評価・処理されています。
そこで、JSF のコンポーネントタグをコメントする方法(EL式も含め)を2通り紹介します。
1. <ui:remove> </ui:remove> タグを使用する方法
2. facelets.SKIP_COMMENTS を web.xml に記載する方法
まず、始めの方法は
<ui:remove> タグを使用する方法です。下記の 10 行目〜12 行目のように、コメントしたいコンポーネントを <ui:remove> </ui:remove> でくくってください。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<ui:remove>
<h:commandButton action="#{user.login_dummy}" value="Submit-Dummy"/><br/>
</ui:remove>
<h:commandButton action="#{user.login}" value="Submit"/>
</h:body>
</html>
コメントした後、画面を再描画すると「Submit-Dummy」のコマンドが非表示になっている事を確認できます。

この時の描画されたページの HTML ソースコードは下記のようになります。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="/JSFSampleApplication/primefaces_resource/2.1/skins/sam/skin.css" />
<title>Facelet Title</title>
</head>
<body>
<input type="submit" name="j_idt7" value="Submit" />
</body>
</html>
次にもう一つの方法は、
web.xml 設定ファイルに facelets.SKIP_COMMENTS を記述する方法です。下記の7 行目〜10 行目のように web.xml に facelets.SKIP_COMMENTS を追加してください。すると<!– –> でくくられた箇所が EL 式も評価されずコメントされる事が確認できます。
web.xml 設定ファイルの編集:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>facelets.SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
...

この時の HTML の出力結果は下記のようになります。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="/JSFSampleApplication/primefaces_resource/2.1/skins/sam/skin.css" />
<title>Facelet Title</title>
</head>
<body>
<input type="submit" name="j_idt7" value="Submit" />
</body>
</html>
どちらの方法を使用してもコメントができるようになりますので、開発者の皆様の使い勝手の良い方法を選択してください。
JSF 2.0 の Ajax 対応はとてもかんたん
JSF 2.0 の新機能の一つに Ajax 対応があります。今日は JSF 2.0 に追加された Ajax と 画面遷移が無いページ(同一描画内)で利用可能な @ViewScope について紹介します。
JSF 2.0 で追加された Ajax の機能を使うと、JavaScript の知識が殆どなくても Ajax のページを作成する事ができます。またその際、自身で XMLHttpRequest, XMLHttpResponse の通信処理も記載する必要がないため開発効率が向上します。
もっと誇張していうなら、通常の JSF ページに対してほんの数行追加するだけで、簡単に Ajax 対応させる事ができます。下記に示す例ではほんの1〜2行追加するだけで Ajax 対応ページを実現しています。
JSF 2.0 のページを Ajax 対応させるための開発の手順としては、通常の JSF のページを記載して頂き、最後に Ajax 対応用のタグを追加するという手順で行って頂く事ができます、そのため、Ajax 対応を意識をせずに記載できるようになっています。
それでは、JSF 2.0 における Ajax 対応について詳細に説明していきます。JSF では 「実行」と「描画」に分けて処理を行います。
実行フェーズでは下記を行います
● コンポーネントデータのコンバートやバリデート
● 入力データをモデル(サーバ側の CDI/Managed Bean)に送信
● アクション、アクションリスナーの実行
描画フェーズでは下記を行います。
● 処理結果の描画
必要な描画部分だけを更新できるため、サーバ、クライアント(ブラウザ)共に負荷(データ転送容量や全データの描画処理等)を軽減する事ができるようになります。

サンプルアプリケーションの作成
それでは、サンプルのアプリケーションを作成してみます。ユーザ名、パスワードを入力し、ボタンを押下するアプリケーションを作成します。

このアプリケーションの描画部分である Facelets は下記のように記載します。
ログイン Facelets のソースコード (Ajax 未対応):
<h:form>
<h:inputText id="name" value="#{user.name}" validator="#{user.validateName}">
</h:inputText> #{' '}
<h:message for="name" id="nameError" style="color: red"/>
<br/>
<h:inputSecret id="password" value="#{user.password}">
</h:inputSecret>
<br/>
<h:commandButton value="Submit" action="#{user.login}">
</h:commandButton>
</h:form>
CDI の UserBean.java は下記のように書きます。下記のコードは Submit ボタンが押下された際 (UserBean#logic が実行される)、画面遷移は行わず入力されたデータのバリデーションのみ行います。@Named(“user”) の代わりに @ManagedBean(name=”user”) を指定すると、本クラスは CDI ではなく JSF の Managed Bean として扱われます。
(※ データの入力値チェックは通常 JavaScript で記載する事が多いと思いますが、今回は説明をかんたんにするためサーバ側でチェックを行っています。)
UserBean.java のソースコード:
package jp.co.oracle.cdi;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.inject.Named;
@Named("user") //@ManagedBean(name="user")
@SessionScoped
public class UserBean implements Serializable{
private String name="";
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void validateName(FacesContext fc, UIComponent uic, Object value){
String inputData = (String)value;
if(inputData.length() > 25){
throw new ValidatorException(new FacesMessage("25 文字以上は入力できません。"));
} else if(inputData.contains("_")){
throw new ValidatorException(new FacesMessage("アンダースコアは入力できません。"));
} else if (! inputData.matches("^[\\u0020-\\u007E]+$")){
throw new ValidatorException(new FacesMessage("入力文字は ASCII 文字でなければなりません。"));
} else{
;
}
}
public void login(){
;
}
}
コードを記述した後、アプリケーションを実行してください。「Submit」ボタンを押下すると Validation が実行されます。この際、画面の一部ではなく全画面が再読み込みされている事を確認してください。

次に、上記のコードに対して下記のコードを追加してください。
3 行目:<f:ajax execute=”name” render=”nameError” event=”blur” />
12 行目:<f:ajax/>
追記したログイン Facelets のソースコード(Ajax 対応):
<h:form>
<h:inputText id="name" value="#{user.name}" validator="#{user.validateName}">
<f:ajax execute="name" render="nameError" event="blur" />
</h:inputText> #{' '}
<h:message for="name" id="nameError" style="color: red"/>
<br/>
<h:inputSecret id="password" value="#{user.password}">
</h:inputSecret>
<br/>
<h:commandButton value="Submit" action="#{user.login}">
<f:ajax/>
</h:commandButton>
</h:form>
コードを追記後、アプリケーションを再実行してください。実行すると、画面をリフレッシュせず Validation を実行する事が確認できます。

上記で追加した <f:ajax execute=”name” render=”nameError” event=”blur” /> は execute, render, event の 3 つの属性を持っています。
execute=”name” で指定した “name” は Ajax のリクエストを送信した際、サーバ側で実行される JSF コンポーネント名を指定します(複数のコンポーネントを実行する場合、スペースで区切ります。また、直接コンポーネント名を指定する他、@this, @form, @all, @none 等の予約語を指定する事もできます。)。上記の例では <h:inputText id=”name” のコンポーネントが実行されます。
次に、render=”nameError” ですが、Ajax の実行結果を描画する JSF コンポーネントを指定します(複数のコンポーネントを実行する場合、スペースで区切ります)。上記の例では <h:message for=”name” id=”nameError” style=”color: red”/> の部分が再描画されます。
次に event=”blur” ですが、どのタイミングでこの Ajax が実行されるかを指定します。blur は onblur の事を指し、コンポーネントのフォーカスが失われた際に実行する事を意味しています。
つまり、上記のコードを追加すると、テキストフィールドに対するフォーカスを失った際、id=”name” で指定したコンポーネントを実行し、id=”nameError” で指定した箇所にエラーコードを出力するという動きになります。
最後に、上記の例では<h:commandButton/> のタグ内に <f:ajax> タグを記載しています。これは input 内にフォーカスがあたっている際に、ボタンが押下された場合、Ajax イベントと ボタン押下のイベントが競合して同時実行されてしまう可能性があるため、このような意図しない振る舞いを防ぐために記載しています。なぜなら、JSF では Ajax のリクエストをキューイングしますので、最初の Ajax のリクエストが終了した後に、次の commandButton 内に記載した Ajax リクエストが実行されるようになります。
<f:ajax> タグはその他、disabled, event, execute, immediate, onerror, onevent, listener, render の属性を指定する事ができます。
例えば、下記のようにしてエラーハンドリングを行う事ができます。
<f:ajax onerror=”handleAjaxError”/>
如何でしょうか? たった1、2行の追加で、
かんたんに Ajax 対応ができる事ができました。
それでは、
上記よりちょっとだけ複雑な Ajax のページを作成してみます。

このページはテキストフィールド内に入力したデータをテーブル内に追加していく(カートのような)ページです。この例では直接製品名を入力していますが、製品の写真を表示したりボタン等を設けてよりリッチなページも作成する事ができるかと思います。
(※ 今回は説明かんたんにするためテキスト入力にさせて頂きます。)
まず、このページの描画用 Facelets を下記のように記載します。
簡易カート Facelets のソースコード (Ajax 未対応)
<h:form prependId="false">
<h:inputText id="productname" value="#{cart.product.productname}">
</h:inputText> #{' '}
<h:commandButton action="#{cart.addItem}" value="カートに追加">
</h:commandButton>
<br/>
<br/>
<h:dataTable border="1" id="tables" value="#{cart.selectedItems}" var="item">
<f:facet name="header">
<h:outputText value="追加された製品一覧" />
</f:facet>
<h:column>
<h:outputText value="#{item.productname}" />
</h:column>
</h:dataTable>
</h:form>
次に、製品名を持つ 製品 Bean を作成します。
製品 Bean のソースコード:
package jp.co.oracle.cdi;
import java.io.Serializable;
public class Product implements Serializable{
private String productname;
public String getProductname() {
return productname;
}
public void setProductname(String productname) {
this.productname = productname;
}
}
最後に、入力された製品名を格納する Cart Bean を作成します。
カート Bean のソースコード:
package jp.co.oracle.cdi;
import java.io.Serializable;
import java.util.ArrayList;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Named;
import javax.validation.constraints.NotNull;
@Named("cart")
@SessionScoped
public class Cart implements Serializable{
@NotNull
private Product product = new Product();
private ArrayList<Product> selectedItems = new ArrayList();
public ArrayList<Product> getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(ArrayList<Product> selectedItems) {
this.selectedItems = selectedItems;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public void addItem(){
String inputProductName = product.getProductname();
Product item = new Product();
item.setProductname(inputProductName);
selectedItems.add(item);
}
}
補足:
| このページの振る舞いについて若干補足します。 1. <h:inputText id=”productname” value=”#{cart.product.productname}”> の描画領域にデータを入力します。 2. 入力された値は、下記の呼び出しによって Product のインスタンスが生成されます。 3. ボタンが押下された際、Cart#addItem が実行されます。 4. Cart#addItem は、内部で持つ ArrayList に対して入力された値を追加します。 5. Cart 中の ArrayList に含まれる一覧をリスト表示します。 6. 配列の各要素は、var=”item” となるため、#{item.productname}で製品名を表示します。 |
ソースコードを記述後、アプリケーションを実行してください。すると画面がリフレッシュされ、入力した文字列が画面下部に表示されます。

次に Ajax 対応させます。Ajax 対応させるために記載するコードは下記の1行だけです。
5 行目:<f:ajax execute=”productname” render=”tables”/>
上記 Ajax 対応のコードはテキストフィールドの値で Ajax の Request を送信し、dataTable の描画部分を更新しています。
追記した簡易カート Facelets のソースコード(Ajax 対応):
<h:form prependId="false">
<h:inputText id="productname" value="#{cart.product.productname}">
</h:inputText> #{' '}
<h:commandButton action="#{cart.addItem}" value="カートに追加">
<f:ajax execute="productname" render="tables"/>
</h:commandButton>
<br/>
<br/>
<h:dataTable border="1" id="tables" value="#{cart.selectedItems}" var="item">
<f:facet name="header">
<h:outputText value="追加された製品一覧" />
</f:facet>
<h:column>
<h:outputText value="#{item.productname}" />
</h:column>
</h:dataTable>
</h:form>
追記したコードでアプリケーションを再度実行してください。画面がリフレッシュされず、ボタン押下時に画面下部に文字列が追加されている事を確認できるかと思います。

ViewScoped について
最後に、JSF 2.0 で追加された @ViewScoped を紹介します。上記 CDI の Cart Bean は @SessionScoped を宣言しています。つまり上記 Cart Bean はセッションの有効期限内はずっと保持されます。
JSF 2.0 では画面遷移の無い同一画面のみ有効なスコープ ViewScoped が新たに追加されました。ViewScoped は CDI(Weld) では実装されておらず、JSF の Managed Bean で実装されています。
そこで、ViewScope を扱うためには、CDI から Managed Bean に変更する必要があります(もしくは独自拡張を実施)。
Cart Bean を CDI から Managed Bean に変更するため下記のように書き直してください。
変更箇所(11〜14 行目):
// @Named(“cart”)
// @SessionScoped
@ManagedBean(name=”cart”)
@ViewScoped
Managed Bean に修正したコード:
package jp.co.oracle.cdi;
import java.io.Serializable;
import java.util.ArrayList;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Named;
import javax.validation.constraints.NotNull;
// @Named("cart")
// @SessionScoped
@ManagedBean(name="cart")
@ViewScoped
public class Cart implements Serializable{
@NotNull
private Product product = new Product();
private ArrayList<Product> selectedItems = new ArrayList();
public ArrayList<Product> getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(ArrayList<Product> selectedItems) {
this.selectedItems = selectedItems;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public void addItem(){
String name = product.getProductname();
System.out.println("Product Name: " + name);
Product product = new Product();
product.setProductname(name);
selectedItems.add(product);
}
}
変更後、再度アプリケーションを実行してください。
SessionScoped の場合は、画面をリロード(再読み込み)しても、過去に入力したデータが表示されていました。
一方 ViewScoped に変更すると画面をリロードすると(ビューが変わるため)、データが破棄されている事が確認できます。
この ViewScope は同一画面内で処理する Ajax 等に便利なので是非ご使用ください。
最後に、上記では <f:ajax/> タグを使って Ajax を実現しましたが、細かなカスタマイズを行いたい場合は、別途カスタマイズできるように JavaScript ライブラリを提供しています。
そういったニーズがある場合、JavaScript ライブラリを利用するために下記のコードを追加して実装してください。
<h:outputScript library=”javax.faces” name=”jsf.js”/>
また、jsf.ajax には addOnError(), addOnEvent(), isAutoExec(), request(), response() 等の関数が用意されていますので、これらを使って処理を柔軟に記載する事ができるようになります。
是非、JSF 2.0 の Ajax 対応を試してみてください。
WebLogic 10.3.4 が正式リリース
WebLogic 10.3.4 が正式リリースされました。WebLogic 10.3.4 は ExaLogic 対応等数多くの機能追加があります。例えば、JSF 2.0 や JPA 2.0 が利用できるようになっています。下記では昨年開催された Oracle DBA Developer Days 2010 のイベントで発表した WebLogic Server 10.3.4 の新機能概要をプレゼンでまとめていますので、どうぞご参照ください。
また、下記のデモは 10.3.4 に追加されたクラスローダ解析ツールを JSF 2.0 のアプリケーションを作成してデモしています。ClassLoader Analysis Tool はクラス名の衝突を Web の画面から確認できるようになっていますので、非常に便利です。
(画面を大きくし 720p に変更してご覧ください。)
また、下記のデモは 10.3.4 から Maven Plugin を提供しますが、WebLogic の Maven Plugin の利用方法について紹介しています。
JSF 2.0 の新機能概要とFacelets テンプレートのご紹介
![]()
JavaServer Faces 2.0(JSF) は Java EE 6 含まれる標準 Web ユーザインタフェース技術です。これから数回に渡り、JSF 2.0 の新機能を紹介して行きたいと思います。
JSF 2.0 の新機能
- Facelets/VDL による実装
- Ajax 対応
- カスタム複合コンポーネント
- Behavior
- Partial State
- ページナビゲーションの改良
- Resource Loading
- ブックマーク可能なページ
- New Event API
- 例外ハンドリング
- JSR-303 Bean Validation のサポート
- faces-config.xml のオプション化
JSF 2.0 では JSF 1.2 に比べ上記のような新機能が含まれますが、今日は JSF 2.0 から標準仕様に含まれた Facelets について紹介します。
Facelets は JSF 1.2 まで View を記載する方法として使用されていた JavaServer Pages(JSP) で の代替え方法として開発されました。JSF 1.2 の頃は Facelets は標準仕様内に組み込まれていなかったため、別途利用するための設定等が必要でしたが、JSF 2.0 からは JSF の標準仕様内に組み込まれたため、今後は JSP の変わりに Facelets(XHTML) を記載して開発するようになります。
また、JSF 1.2 は Servlet 2.5 と組み合わせて動作させる必要がありましたが、JSF 2.0 では Servlet 3.0 との組み合わせは必須ではなく、Servlet 2.5 との組み合わせでも動作させる事ができるようになっています。つまり JSF 2.0 の実行環境(参照実装は Mojjara(モハラ)) は Java EE 6 の環境下だけでなく Java EE 5 の環境でも動作させる事ができるようになっています。WebLogic 10.3.3 等 Java EE 5 のアプリケーションサーバ上でも JSF 2.0 を動作させる事ができるようになっています。
● Facelets による開発の利点
JSF 1.2 までは JSP で JSF を開発していました。しかし JSP で開発する際には、コンパイル時にオーバヘッドが掛かっていました。例えば、JSP のコードを編集したり、保存、ページの再読み込みのような処理を行うたびに、JSP コンパイラは Java の Servlet コードを生成し、コンパイルをを行っていました。これは JSP の Translation プロセスと呼ばれ、約1~2秒程のオーバヘッドが掛かっていました(サーバの処理能力に依存)。
一方、JSP と異なり、Facelets ページは Servlet にコンパイルされず、XML として処理を行います。そして Facelets は表示を行うために高速な SAX ベースのコンパイラを使用しています。また Facelets はページの変更等を即座に検知する事ができるため、JSF における開発効率が向上します。
■テンプレート機能
多くの Web サイトではページ間のデザインを統一するため、共通の表示部分を持たせる事が多いかと思います
例えば、共通のヘッダやフッダ、サイドバー等はページ間で統一したいかと思います。上記の Web ページでは下記のように共通部分を5つ(ヘッダ、左ペイン、右ペイン、フッダ、自由記載のコンテンツ領域)に分割する事ができます。
この内、「自由記載のコンテンツ領域」以外は全ページで同一コンテンツを表示したいと考えます。このような場合、作成するページ毎に共通部分(ヘッダ、フッダ等)を記載すると、開発効率やメンテナンス性が非常に悪くなります。このような重複コンテンツを効率よく扱うために、Facelets では「テンプレート機能」を持ち共通部分をテンプレート内に記載し、必要な部分だけを編集する事ができるようになっています。
PrimeFaces について
上記の画面は全て NetBeans 7.0 Beta に含まれる PrimeFaces を使用して作成しています。Oracle のホームページの画面に似せて作成してみましたが、PrimeFaces は非常にリッチな JSF のコンポーネントを提供していますので、簡単にこのようなリッチな JSF Web アプリケーションを作成する事ができます。PrimeFaces が提供している各種 JSF コンポーネントの詳細は下記をご参照ください。
ご参考:PrimeFaces ShowCase (提供されるコンポーネント一覧)
NetBeans 7.0 Beta で PrimeFaces を利用するためには、新規プロジェクトを作成する際、フレームワークの選択時に、「JavaServer Faces 」をチェックし「コンポーネント」より「PrimeFaces 2.1」を選択してください。

● プロジェクトの進め方とディレクトリ構成
今回、NetBeans 7.0 のプロジェクトを作成しますが、下記のような手順で画面を作成していきます。

1. ヘッダの作成
2. 左ペインの作成
3. 右ペインの作成
4. フッダの作成
5. テンプレートの作成
6. 各種ページの作成
ちなみに、プロジェクトのディレクトリ構成は下記のように作成しています。
「Web ページ」配下に「templates」ディレクトリを作成し、JSF のテンプレートファイル (1〜5) はすべてこのディレクトリ配下に作成します。

1. ヘッダ部分の作成
![]()
まず、ヘッダ部分を作成します。ヘッダ部分は PrimeFaces で提供されている MenuBar を利用します。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form id="menue">
<h:graphicImage url="/resources/images/Oracle_ja.gif"/>
<p:menubar>
<p:submenu label="製品">
<p:menuitem value="Oracle DataBase" url="http://www.oracle.com/jp/products/database/index.html">
</p:menuitem>
<p:menuitem value="Oracle Fusion Middleware" url="http://www.oracle.com/jp/products/middleware/index.html">
</p:menuitem>
</p:submenu>
<p:submenu label="ダウンロード">
<p:menuitem value="DataBase"></p:menuitem>
<p:menuitem value="DataBase 11g" url="http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html">
</p:menuitem>
</p:submenu>
<p:submenu label="価格/ライセンス">
<p:menuitem value="価格表" url="http://www.oracle.com/jp/corporate/pricing/pricing-pricelists-079522-ja.html">
</p:menuitem>
</p:submenu>
<p:submenu label="サポート">
<p:menuitem value="価格表" url="http://www.oracle.com/jp/corporate/pricing/pricing-pricelists-079522-ja.html">
</p:menuitem>
</p:submenu>
<p:submenu label="研修/資格">
<p:menuitem value="価格表" url="http://www.oracle.com/jp/corporate/pricing/pricing-pricelists-079522-ja.html">
</p:menuitem>
</p:submenu>
<p:submenu label="パートナー">
<p:menuitem value="価格表" url="http://www.oracle.com/jp/corporate/pricing/pricing-pricelists-079522-ja.html">
</p:menuitem>
</p:submenu>
<p:submenu label="日本オラクルについて">
<p:menuitem value="価格表" url="http://www.oracle.com/jp/corporate/pricing/pricing-pricelists-079522-ja.html">
</p:menuitem>
</p:submenu>
</p:menubar>
</h:form>
</h:body>
</html>
2. 左ペイン部分の作成
次に左ペインの部分を作成します。

左ペインの部分は PrimeFaces で提供されている Menu を利用します。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<div class="leftString">
<p:menu>
<p:submenu label="Oracle Fusion Middleware">
<p:menuitem value="アプリケーション・グリッド"/>
<p:menuitem value="アプリケーション統合アーキテクチャ"/>
<p:menuitem value="WebLogic Server"/>
<p:menuitem value="ビジネス・インテリジェンス"/>
<p:menuitem value="ビジネスプロセス管理"/>
<p:menuitem value="コラボレーション"/>
<p:menuitem value="コンテンツ管理"/>
<p:menuitem value="データ統合"/>
<p:menuitem value="開発ツール"/>
<p:menuitem value="イベント駆動アーキテクチャ"/>
<p:menuitem value="Exalogic"/>
<p:menuitem value="ID管理"/>
<p:menuitem value="インメモリ・データグリッド"/>
</p:submenu>
</p:menu>
</div>
</h:form>
</h:body>
</html>
3. 右ペイン部分の作成
次に右ペインの部分を作成します。

右ペインの部分は PrimeFaces で提供されている Accordion Panel を利用します。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<div class="leftString">
<p:accordionPanel autoHeight="false">
<p:tab title="ダウンロード">
<h:panelGrid columns="2" cellpadding="10">
<h:outputText value="Oracle Universal Content Management"/>
</h:panelGrid>
</p:tab>
<p:tab title="サポート">
<h:panelGrid columns="2" cellpadding="10">
<h:outputText value="Oracle Support"/>
<h:outputText value="Advanced Customer Services"/>
</h:panelGrid>
</p:tab>
<p:tab title="技術情報">
<h:panelGrid columns="2" cellpadding="10">
<h:outputText value="Oracle Content Management"/>
</h:panelGrid>
</p:tab>
<p:tab title="パートナー">
<h:panelGrid columns="2" cellpadding="10">
<h:outputText value="Find Specialized partner"/>
</h:panelGrid>
</p:tab>
<p:tab title="カタログ/データシート">
<h:panelGrid columns="2" cellpadding="10">
<h:outputText value="Brochure: Oracle Content Management (PDF)"/>
<h:outputText value="Data Sheet: Unversal Content Management (PDF)"/>
</h:panelGrid>
</p:tab>
<p:tab title="ホワイトペーパー">
<h:panelGrid columns="2" cellpadding="10">
<h:outputText value="Information Workplace Platform: Oracle vs Microsoft(PDF)"/>
<h:outputText value="Get More from Microsoft SharePoint with Oracle Fusion Middleware (PDF)"/>
</h:panelGrid>
</p:tab>
</p:accordionPanel>
</div>
</h:form>
</h:body>
</html>
4.フッダ部分の作成
次にフッダ部を作成します。
![]()
フッダ部分はちょっと手抜きですが、下記のように記述します。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<div class="greyBarBottom"><!--footer--></div>
<h:graphicImage url="/resources/images/oracle-footer-tagline.gif"/>
<div class="footerString">
会社情報 | オラクルとサン | Oracle RSS Feeds | Subscribe | 採用情報 | お問い合わせ | サイトマップ | ウェブサイトのご使用条件 | 個人情報保護基本方針 | 情報保護基本方針
</div>
</h:body>
</html>
5. JSF テンプレートの作成
次に、上記で作成した各共通部分を含むテンプレートを作成します。NetBeans のプロジェクトから「新規」→「その他…」を選択してください。

すると下記の画面が表示されます。ここで「Facelets テンプレート」を選択します。

選択すると下記の画面が表示されますので、レイアウトのスタイルを選択して「完了(F)」ボタンを押下します。
ボタンを押下するとテンプレートの雛形が生成されますので、これを編集して Facelets テンプレートを完成させます。ここでは、 <ui:include src=”./top.xhtml”/>、<ui:include src=”./left.xhtml”/>、<ui:include src=”./right.xhtml”/>、<ui:include src=”./bottom.xhtml”/> のタグを使ってそれぞれをテンプレートの適切な箇所に記載します。
「レイアウトスタイル:」で「表」をチェックした際のテンプレートの記載内容を下記に示します。(画面構成は自由にカスタマイズができます。)
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./../resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./../resources/css/tableLayout.css" rel="stylesheet" type="text/css" />
<title>Facelets Template</title>
</h:head>
<h:body>
<table cellspacing="10px">
<tr>
<td id="top" colspan="3">
<ui:insert name="top">
<ui:include src="./top.xhtml"/>
</ui:insert>
</td>
</tr>
<tr>
<td id="left">
<ui:insert name="left">
<ui:include src="./left.xhtml"/>
</ui:insert>
</td>
<td id="content">
<ui:insert name="content">Content</ui:insert>
</td>
<td id="right">
<ui:insert name="right">
<ui:include src="./right.xhtml"/>
</ui:insert>
</td>
</tr>
<tr>
<td id="bottom" colspan="3">
<ui:insert name="bottom">
<ui:include src="./bottom.xhtml"/>
</ui:insert>
</td>
</tr>
</table>
</h:body>
</html>
6. JSF テンプレートクライアント(表示用のページ)の作成
次に、テンプレートを利用した表示用のページを作成します。NetBeans のプロジェクトから「新規」→「その他…」を選択してください。

すると下記の画面が表示されます。ここで「Facelets テンプレートクライアント」を選択します。

ここで「テンプレート:」の「参照…」ボタンを押下してください。すると下記のように、テンプレートを選択するウィンドウが表示されます。
作成したテンプレート(tableTemplate2.xhtml)を選択し「ファイルを選択」ボタンを押下します。最後に「完了(F)」ボタンを押下します。
すると下記の雛形が自動生成されます。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="./templates/tableTemplate2.xhtml">
<ui:define name="top">
top
</ui:define>
<ui:define name="left">
left
</ui:define>
<ui:define name="content">
content
</ui:define>
<ui:define name="right">
right
</ui:define>
<ui:define name="bottom">
bottom
</ui:define>
</ui:composition>
</body>
</html>
ここで「Facelets テンプレート」と「テンプレートクライアント」の関係を説明します。「Facelets テンプレート」の中身を確認すると下記のタグが記載されている事が確認できます。(それぞれ、17行目, 24行目, 29行目, 32行目, 39行目)
<ui:insert name="top">
<ui:insert name="left">
<ui:insert name="right">
<ui:insert name="content">Content</ui:insert>
<ui:insert name="bottom">
一方で、「テンプレートクライアント」の中身を確認すると下記のタグが記載されている事が確認できます。(それぞれ10行目, 14行目, 18行目, 22行目, 26行目)
<ui:composition template="./templates/tableTemplate2.xhtml">
<ui:define name="top">
<ui:define name="left">
<ui:define name="content">
<ui:define name="right">
<ui:define name="bottom">
</ui:composition>
Facelets ではテンプレート中に記載されている <ui:insert name=”NAME”> の箇所をテンプレートクライアントの <ui:define name=”NAME”> で更新する事ができます。テンプレートの全てを変更したい場合は全て上書きする事ができますが(NetBeans で自動的に作成される上記の雛形は全てを上書きします)、自由記載のコンテンツ領域だけを編集したい場合は、下記のように必要な部分のみ(<ui:define name=”content”> のタグの部分だけを残してその部分のみ)を編集します。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="./templates/tableTemplate2.xhtml">
<ui:define name="content">
ここに「自由記載 コンテンツ領域」の内容を書きます。
</ui:define>
</ui:composition>
</body>
</html>
テンプレートを使用して作成したコンテンツへアクセスすると下記の画面が表示されます。

JSF 2.0 の Facelets のテンプレート機能を効果的に利用すると Web ページの開発が効率化され、本当に必要な部分の開発にのみ集中できるようになります。また、NetBeans 7.0 Beta に含まれる PrimeFaces も非常にリッチな JSF コンポーネントが用意されていますので、見栄えのよい Web ページをかんたんに作成する事ができるようになります。
是非、お試しください。
本ページで使用した NetBeans 7.0 Beta のプロジェクトは下記より入手可能です。JSFSampleApplication.jar (NB7 プロジェクトファイルのアーカイブ)の入手はコチラ
余談:
上記、プロジェクトですが、web.xml の設定を Development にすると画面中に下記のワーニングが表示されます。(すいません、原因がつかめていません。)
The button/link/text component needs to have a Form in its ancestry. Please add <h:form>.
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
下記のように、Production に変更するとワーニングは表示されません。
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
原因がわかったら追記します。
今年1年を振り返って
今年1年、皆様の周りでは如何だったでしょうか?
今日が仕事納めの日ですので、今年1年を振り返ってみたいと思います。私にとって今年1年を一言で表すならば「激動の1年だった」と言えます。
忘れもしない、1月21日「 EU の Oracle による Sun 買収承認 」が無事 ?! あり、約 9年程勤めてきた Sun という会社が事実上無くなってしまった日でした。

こんな1年の始まりでしたが、オラクルの統合後、自分がどのようになるか全く想像もつかなかったため、日本の統合まで、できるだけ自分の持っている GlassFish の関連情報をブログに残しておこうと、粛々とブログを書いていたのがこの頃でした。また自分の将来について真剣に悩み始めたのもこの頃でした。
ただ、悩んでばかりはいられない、日本 Sun が無くなるのはもうすぐなんだ、Sun が無くなる前に、Sun として最後の「 Java Hot Topic セミナー」を開催したいと思い立ち企画し、ご賛同頂いた多くの皆様のご協力のおかげで「 Sun 最後の Java Hot Topic セミナー 」を開催する事ができました。ご協力頂きました、櫻庭さんを始めとし Sun の Java エバンジェリストの皆様本当にありがとうございました。
(この文章を書いていて、たった半年なのに、もう随分前の事のように思えて悲しくなりました。(T_T))
そして、ついに 5/31 ついに日本 Sun がなくなる日がやって来ました。Sun に憧れ Java が好きで入ってきたこの会社がまさか本当に無くなるとは夢にも思ってなかったです。あの時、今は無き用賀オフィスのSun ロゴの写真も撮っておいて良かったです。さよなら Sun のエントリ


そして、6/1 より日本オラクルの一員として活動を開始したのですが、半年のプリセールスグループの経験後、12/1 より現在のポジションで活動させて頂く事になりました。
入社から半年間、対外的にブログ等はあまり書いてませんでしたが、私個人的には、とても収穫のあった半年でした。WebLogic や周辺製品を触ったのもそうなのですが、何より WebLogic, JRockit, Coherence にとても詳しい優秀な方々と同グループで親しくさせて頂いたので、とても良い時間を過ごしたと思っています。人間関係はグループが変わっても変わる物ではないのでかけがえのない宝だと思っております。
12/1 からこの1ヶ月間も色々とありましたが、Java/UNIX が好きで入った Sun 、Sun が Oracle に変わっても Java は無くならないので、”Sun 魂” の心に持ったまま、Oracle のエンジニアとして、今後も Java に対する不安を払拭できるように頑張って行きたいと思います。
皆様、本年は誠にありがとうございました。
来年もどうぞ宜しくお願いします。
Java EE の向かう先
このエントリはJava Advent Calendar -ja 2010 の一環です。
Yamashiro0217さんに引き続き 12/24 の担当をさせて頂きます。

先日勉強会で GlassFish v3.1 の新機能をご紹介したばかりなので何を書こうかいろいろ悩んでいたのですが、やっぱり私は Java EE 関連のイメージが強いと思いますので、Java EE の最新情報についてお届けしようと思います。
ただし、「本日ご紹介する内容はまだ計画段階の内容を多く含みますので、今後大きく方針等が変更される可能性があります」のでその点だけご理解ください。Java EE 6 がリリースされて1年、本エントリではこれからの Java EE がどのような方向に進むのか概要を捉えて頂ければと思います。
さて、Java EE 6 は 以前のバージョン(Java EE 5)のリリースに比べて世界ではとても早いスピードで浸透してきています。我々は既に Java EE 6 対応のアプリケーションサーバ GlassFish v3 を提供していますし、また、多くのベンダーが Java EE 6 に対応したアプリケーションサーバの開発を進めておりリリース間近の製品もあります。

本日は Java EE 6 の後にリリースされる予定の 「Java EE 7」 について紹介します。
ずばり、Java EE 7 のメインテーマは「クラウド」対応です(PaaS)。
恐らく、この Java EE 7 の「クラウド」対応という言葉は、今年の JavaOne の報告等で目にされていらっしゃる方もいらっしゃるかと思います。それではどのあたりがクラウド対応なのか?という事について本エントリではすこし掘り下げて説明したいと思います。
まず、今まで提供してきた Java EE (Web コンテナ/EJB コンテナ) コンテナは、既存のエンタープライズ要件を十分に満たしてきたわけですが、今後 Java EE はクラウドに対応する必要があると考えています。

Java EE 6 までに提供してきたものは下記が上げられます、そしてこれらの内今すぐクラウド環境に適用できる物もあります。
- コンテナ(Web/EJB)
- サービス、インジェクト可能なサービス
- リソース管理
- 大規模クラスタ対応(Java EE インスタンスのスケール)
- セキュリティモデル
- 境界や規制が必要な環境への適用を可能とする。
しかし、クラウド環境に対応するためには上記では不十分で、追加で考慮しなければならない点があります。例えば下記のような点がクラウド対応に必要だと考えています。
- リソースと状態管理の厳密化
今までは、アプリケーションサーバのインスタンス毎に状態を管理でき、アプリケーション毎に状態管理を行う事はできませんでしたが、アプリケーション中で使用するスレッドの使用ポリシーの定義ができるようになる他、アクセスするリソースに対する定義がアプリケーション単位でできるようになります。またアプリケーションサーバは定義された内容について監視ができるようになります。
- アプリケーション間の独立性
特定のアプリケーションを起動する事によりスレッドやメモリが消費されますが、それが他のアプリケーションに対して影響を与えてしまうのは問題です。そこで、アプリケー ション間の独立性を確保し他への影響を及ぼさないようにする必要があります。このようにアプリケーションが他のサービスに影響しないように独立して稼働できるような定義ができる他、サービスの共有等も定義もできるようにしたいと考えています。
- NRDBMS,キャッシュアクセスに関する標準APIの提供
クラウドを考える際 Amazone の S3 といったストレージサービスのように、ストレージやキャッシュに対してデータを保存する仕組みが必要です。現在は、Java EE でこのようなクラウド環境のストレージサービスに対してデータを保存する共通 API が提供されておらず、個別の実装が必要です。そこで Java EE の API でこれらのストレージサービスに対してアクセスできる API を提供する必要があると考えています。
- 共通の管理、監視インタフェース
今までアプリケーションサーバのインスタンスの管理、監視用のAPI は提供されていましたが、クラウドのような環境ではアプリケーションレベルでの管理、監視用の API が必要と考えています。アプリケーションが起動された際に、その管理、監視用 API をコールする事で動的にアプリケーションの制御ができるようになります。
- アプリケーションのバージョニング
アプリケーションのバージョニングにおいては、同一アプリケーションの複数バージョンを扱えるようにし、柔軟にアプリケーションのバージョンアップができるようにする必要があると考えています。(GlassFish v3.1は既に一部対応)アプリケーションの更新に伴い、RDBMS のスキーマ等が変わった場合に、その定義ファイル等をマイグレーションするのはとても困難でした。同一アプリケーションで複数のバージョンを持たせる事で、よりかんたんにアプリケーションのバージョンアップ/ロールバックが可能になります。
現在上記のような点を改善しクラウド環境で利用できるように考えています。「現在 Java EE 7 は仕様を検討し始めた段階で、上記が全てではありません」。Java EE 7 のクラウド対応に関するコメント等を JCP/GlassFish コミュニティ等で受け付けています。ご意見、ご要望がある方は是非これらのコミュニティへフィードバックをお送りください。

また、クラウド対応以外の各種仕様に関するアップデートの一部も下記に記載します。この中で最も大きく変わりそうなのは JMS だと思われます、今までよりもかんたんに JMS の開発ができるような方向で改良が加えられる予定です。
- JavaServer Faces 2.1 (マイナーアップグレードで JavaEE 7 前に利用可能予定)
- UIData の瞬間的な状態保存
- XML ビューのクリーンアップ
- Facelet からのキャッシュAPI
- JavaServer Faces 2.2
- HTML 5 対応
- HTML 5 タグへの対応
- ブラウザ機能の検出
- HTML 5 用コンポーネント
- 音声/動画のサポート
- 頻繁に利用される API の標準化
- Apache MyFaces Trinidad PageRsolver
- Oracle ADF ApplicationContextManager
- JSR 276: Design-Time Metadata for JavaServerTM Faces Components サポート
- 既存機能の拡張
- モバイルレンダーキット
- コンポジットコンポーネント
- パフォーマンスの改善
- JMS 2.0
- API における曖昧さと、不確実性を解決
- 既存 API の複雑性を解決
- 不完全かつオプションの仕様のJava EEへの統合
- 共通のベンダ拡張/新機能の標準化
- 他言語や他の仕様の統合
- WebTier
- WebSocket プロトコルのサポート
- JSON API のサポート
- HTML 5 のサポート
- NIO.2 ベースの Web コンテナ
- JPA 2.1
- ※ コミュニティからの改善要望を受付中 ※
- JPA 2.0 に対する機能追加を予定
- モジュール化
Java EE におけるモジュラリティについてですが、Java EE のモジュール対応は Java EE 8 で対応する予定です。ご存知の通り、Java SE の Project Jigsaw のモジュール機能が、Java SE 8 で実装されるため、Java EE 7 のリリース時点では対応が (Java EE 7 の方が Java SE 8 より早くリリースする可能性が高いため) 困難でJava EE 8 での対応を予定しています。
- ロードマップ
- JAX-RS 2.0 と JPA 2.1 は近々登録予定
- JSF 2.2, Servlet 3.1, EJB 3.2, JMS 2.0は今後登録予定。
- 2012 年にリリース予定
最後に、
今まで (Java EE 6 まで) は企業環境で十分耐えられる技術や API を提供してきました。これらは現時点でもすぐクラウド環境に適応する事が可能な物もあります。一方、Java EE 7 は一から新しく仕様を再作成するのではなく、既存の技術に対してクラウド環境へ適用しやすい機能を追加で提供していく予定です。
また、今後の Java について若干触れておきたいとおもいます。
Java SE/EE に関して明確なロードマップを示されており継続して Java SE/EE を提供していく予定です。Java SE 7 は来年リリース予定ですし、Java EE も上記で記載したように提供に向けて今まさに議論が始まった所です。
Java に対する不安の声等もありますが、現時点で Oracle は Java をなくそうとか、コミュニティをおろそかにするという考えは一切なく、開発者の皆様の声を聞き、コミュニティを大事にしていきたいと考えています。例えば実際に、US Oracle では、GlassFish コミュニティも大事にしコミュニティ活動をおろそかにしてはいけない、それどころか逆にコミュニティを拡大するようにというメッセージもでているくらいです。また OpenJDK の開発に IBM 殿が参加された事も、OpenJDK のコミュニティ活動、成果物である JavaVM に対してとても良いニュースでした。
Oracle になった後、Oracle は Java を囲い込むのではないか?金儲けをしようとしているのではないか?という声も聞こえますが、Oracle の Java に対する開発・提供方針は Sun の頃から変えずにやっていこうと動いています。これだけ広く浸透した Java を Oracle が独占したりする事はありません(少なくとも現時点でそのようなメッセージは一切ないですし、例えば、OpenJDK を GPL v2 のライセンスでフォークして頂いてもいいです) ので今後も Java を安心してお使いください。
明日は、Java Advent Calendar -ja 2010 で Seacolor さんです。
GlassFish v3.1 の新機能概要
先日の JavaFX & GlassFish 合同勉強会で発表した資料とデモを公開します。
また、デモを行った際の手順も下記に記載します。
GlassFish v3.1の入手はコチラから
WebSocket サンプルアプリケーションの入手はコチラから

zip 版 GlassFish をインストールする為、unzip してください。
| # unzip latest-web.zip |

次にドメインを起動します。下記のコマンドを実行してください。
| # asadmin start-domain |

次にクラスタを作成します。下記のコマンドを実行してください。
| # asadmin create-cluster cluster1 |

次に、SSH で操作ができるようログインパスワード(相手ノードのパスワード)
を “AS_ADMIN_SSHPASSWORD”に設定し、setup-ssh サブコマンドを実行してください。
※ setup-ssh サブコマンドは後に出てくるパスワードエイリアスが使用できないため、この時点では相手システムのパスワードを生のテキストファイルに記載し、設定完了後削除してください。
④ ノードへのログインパスワード設定
| # echo “AS_ADMIN_SSHPASSWORD=password” > /tmp/password |
⑤ SSH 公開鍵・秘密鍵の作成(ローカル)、authroized_keys の作成(リモート)
下記のコマンドを実行するとホームディレクトリの.sshディレクトリ配下にid_rsa、id_rsa.pubの2ファイルを作成します。また相手システムのホームディレクトリ .sshディレクトリ配下にauthroized_keysを無ければ作成し、公開鍵を追加します。これにより、SSH 経由で処理ができるようになります。
| # asadmin –passwordfile=/tmp/password –interactive=false setup-ssh –sshuser root –generatekey=true glassfish-node1 |

下記のコマンドを実行すると、ドメイン管理サーバから相手システムに GlassFish のバイナリをインストールします。
| # asadmin install-node –installdir /usr/local/glassfish3 –sshuser root –sshkeyfile ~/.ssh/id_rsa glassfish-node1 |
⑦ パスワード・エイリアスの作成
GlassFish v3.1 からパスワードのエイリアスを使用できるようになりました。管理パスワードの他、DB 設定においても生テキストのパスワードを入力する必要がなくパスワード・エイリアスを使用してセキュアな管理ができるようになります。
| # asadmin create-password-alias ssh-password |
⑧ パスワードファイルの作成 (bash の場合)
| # echo “AS_ADMIN_SSHPASSWORD=${ALIAS=ssh-password}” > /tmp/p |

パスワードエイリアスを設定後、パスワードエイリアスを指定したパスワードファイルを使用して GlassFish のノードを作成します。
| # asadmin –passwordfile /tmp/p create-node-ssh –nodehost glassfish-node1 –sshuser root –sshkeyfile ~/.ssh/id_rsa –installdir /usr/local/glassfish3 node1 |

ノード作成後、クラスタ(cluster1)に含まれるインスタンスを作成します。
| # asadmin create-instance –node node1 –cluster cluster1 instance1 |
⑩’ JDK のインストールパスを設定
システムに応じては JDK のインストールパスが異なるため 必要な場合 JDK のインストールパスを設定します。
| # asadmin set “configs.config.cluster1-config.java-config.java-home=/usr/jdk/jdk1.6.0_23” |

インスタンスを作成しましたので、インスタンスを起動します。
| # asadmin start-instance instance1 |
⑫ GlassFish インスタンスの一覧表示
list-instances サブコマンドでインスタンスの一覧を表示する事ができます。
| # asadmin list-instances |
⑬ Cluster に対する WebSocket の有効化
GlassFish v3.1 から WebSocket を利用できるようになりました。GlassFish v3.1 で WebSocket を有効化するためには下記のコマンドを実行してください。
| # asadmin set configs.config.cluster1-config.network-config.protocols.protocol.http-listener-1.http.websockets-support-enabled=true |
⑭ WebSocket サンプルアプリケーションの配備
冒頭で示した URL よりサンプルアプリケーションを入手しデプロイしてください。
| # asadmin deploy –target cluster1 grizzly-websockets-chat-1.9.26.war |





