JavaEEは簡単に言うとWEBアプリケーションを開発するための標準規格である。 JavaEEの「EE」はエンタープライズ・エディション(Enterprise Edition)の略であり、一応企業向けの大規模アプリケーションを開発する際の標準ということになっている(実際は個人でも普通に使えるものだが)。
今までJavaのWEBアプリケーションと言えば、サーブレット・JSPであったが、JavaEEではCDI、XHTML、JSFが標準となっている。 その他にも様々な機能が用意されており、使用感としてはSpringに非常に似ている。 JavaEEはJ2EEの後継であり、サーブレットコンテナも含んでいるため、サーブレット・JSPも使用できる。
今回はJava8、Eclipseは4.5.1、GlassFishは4.1.1を使用してJavaEE7の環境を構築する。 EclipseとGlassFishの連携は以下のページを参照。
JavaEEのプロジェクトは動的Webプロジェクトで作成する。
以下の手順で実施する。
①「ファイル」メニューから「新規」→「プロジェクト」をクリック。
②ウィザード選択画面で「Web」→「動的Webプロジェクト」を選択し、「次へ」をクリック。
③新規動的Webプロジェクト画面で以下を入力・選択し、「完了」をクリック。プロジェクトが作成される。
④「サーバ」タブでGlassFishサーバを右クリックして「追加および除去」をクリック。
⑤作成したプロジェクトを選択し、「追加」をクリック。構成済み欄に表示されたことを確認し、「完了」をクリック。
文字列を送信すると、編集して再表示するサンプルアプリケーションを作成する。
送信を押下すると文字列の最後に「world」を付加して表示する。
以下がサンプルアプリケーションのプロジェクト構成。
以下の5ファイルを作成する。
WEB-INF配下にglassfish-web.xmlを作成する。
glassfish-web.xmlにはコンテキストルート(コンテキストパスともいう)を記述する。 コンテキストルートはサーブレットのコンテキストルートと同じで、呼び出すWEBアプリケーションを区別するものとなる。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
<context-root>/eetest</context-root>
</glassfish-web-app>
WEB-INF配下にweb.xmlを作成する。記述方法は通常のWEBアプリケーションと同じ。
JSFを使用するため、FacesServletの定義を入れる。 JSFはこのFacesServletを内部的に呼び出し、JSFのタグを解釈している。
URLパターン(url-pattern)には、JSF使用対象のビューを指定する。今回は全てのXHTMLを対象とするため「*.xhtml」とする。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>eetest</display-name>
<!-- FacesServlet定義 -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
ロジッククラスを作成する。
引数で受け取った文字列の最後に「world」を付加して返却するaddWorldメソッドを1つ作成。 クラス宣言の上の「@RequestScoped」については後述。
package test;
import javax.enterprise.context.RequestScoped;
/** ロジッククラス */
@RequestScoped
public class TestLogic{
/** メソッド */
public String addWorld(String value){
return value + " world";
}
}
管理Beanを作成する。
管理BeanはCDIで管理されるクラスのこと。そういう意味では先ほどのテストロジックも管理Beanの1つとなる。 英語ではManagedBeanやBackingBeanとも言われるが、呼び方の区別は不明。
CDIは「Contexts and Dependency Injection」の略で、オブジェクトのライフサイクルを管理する機能と依存性注入(インジェクション)の機能を括ったものと思ってよい。
ビューと直接やり取りする管理Beanは、主に以下2つの機能を持つ。
package test;
import java.io.Serializable;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
// ①クラス宣言
/** 管理Beanクラス */
@Named
@ViewScoped
public class JavaeeTestBean implements Serializable{
/** シリアルバージョンUID */
private static final long serialVersionUID = 1L;
/** ②ロジッククラス */
@Inject
private TestLogic logic;
/** ③画面入力値 */
private String value;
/** 画面入力値の設定 */
public void setValue(String value){
this.value = value;
}
/** 画面入力値の取得 */
public String getValue(){
return value;
}
/** ④イベントメソッド */
public void send(){
value = logic.addWorld(value);
}
}
[説明]
①クラス宣言
@Named
@ViewScoped
public class JavaeeTestBean implements Serializable{
ビューから使用されるBeanには「@Named」アノテーションを付与する。これを付与しないとビューからアクセスできない。
「@ViewScoped」はBeanのライフサイクル(スコープ)を意味する。スコープには以下の定義が指定可能。
このアノテーションによって開発者はオブジェクトの生成や破棄の実装をする必要がなくなる。
アノテーション | ライフサイクル | パッケージ |
---|---|---|
@ApplicationScoped | アプリケーション起動から終了まで (ノーマルスコープ) | javax.enterprise.context |
@SessionScoped | セッションの範囲 (ノーマルスコープ) | javax.enterprise.context |
@RequestScoped | リクエストの範囲 (ノーマルスコープ) | javax.enterprise.context |
@ConversationScoped | 任意の範囲 (ノーマルスコープ) | javax.enterprise.context |
@ViewScoped | ページが同じである間 (ノーマルスコープ) | javax.faces.view |
@FlowScoped | 任意の範囲 (ノーマルスコープ) | javax.faces.flow |
@Singleton | アプリケーション起動から終了まで (疑似スコープ) | javax.enterprise.context |
@Dependent | インジェクトするクラスに依存 (疑似スコープ) | javax.enterprise.context |
なお@SessionScopedなど、ライフサイクルがリクエストを跨ぐ場合、シリアライザブル(Serializable)をインプリメントする。
②ロジッククラス
@Inject
private TestLogic logic;
CDI管理のオブジェクトを使用する場合、「@Inject」アノテーションを定義する。 これによりインジェクトされるため、自分でオブジェクトを生成する必要はない。
③画面入力値
private String value;
public void setValue(String value){
this.value = value;
}
public String getValue(){
return value;
}
画面から送信される値(要はリクエストパラメータ)を格納する変数およびセッター、ゲッターを定義する。 変数名とリクエストパラメータの紐づけはビューのJSFによって行われる(後述)。
④イベントメソッド
public void send(){
value = logic.addWorld(value);
}
リクエストをハンドリングするメソッドを定義する。 画面のイベントと呼び出されるメソッドの紐づけはビューのJSFによって行われる(後述)。
なおイベントメソッドの戻り値がvoidの場合、直前に表示していた画面へ遷移する。別の画面へ遷移したい場合は、戻り値をString型とし、表示したいxhtml名を返却する。 nullを返却するとvoidと同じ動作となる。
public String send(){
value = logic.addWorld(value);
return "test2.xhtml";
}
ビューをXHTMLで作成する。XHTMLのコンポーネントは、JSFのタグライブラリなどを使用する。
<?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:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:jsf="http://xmlns.jcp.org/jsf">
<h:head>
<title>Javaee Test</title>
</h:head>
<h:body>
<h:form id="frm">
<!-- テキストフィールド -->
<input type="text" jsf:value="#{javaeeTestBean.value}" />
<!-- 送信ボタン -->
<h:commandButton value="送信" action="#{javaeeTestBean.send()}" />
<!-- 画面入力値を表示 -->
<h:outputText value="#{javaeeTestBean.value}" />
</h:form>
</h:body>
</html>
[説明]
①JSFのタグについて
HTML互換タグについては、以下3つの記述方法がある。
記述方法 | 導入バージョン | 説明 |
---|---|---|
<h:XXX> | JSF2.0以前 | JSFオリジナルのタグ |
jsfc="h:XXX" | JSF2.1 | HTMLとの互換性をより意識。 jsfc属性の値に以前のJSFタグ名を指定。 |
jsf:XXX="xxx" | JSF2.2 | 「jsf:」をHTML属性の前に付加。 JSFタグ名は覚える必要がなくなった。 |
なお、どれか1つの記述方法に統一しなくてはいけないルールはなく、混在も可能。 <h:XXX>タグだけでは実現できない場合に「jsf:」を使ったり、逆に「jsf:」では実現できない場合に<h:XXX>を使ったりしてもよい。サンプルのtest.xhtmlはあえて混在させてみた。
JSF2.1の「jsfc="XXX"」形式は、JSF2.2の「jsf:」形式の出現により使わないことも多い。
3通りの記述例を以下に示す。
■JSF2.0以前の記述
<h:inputText value="#{javaeeTestBean.value}" />
<h:inputText>タグを使用。なおタグの種類については数が多いため、ここでは説明しない。
■JSF2.1の記述
<input type="text" jsfc="h:inputText" value="#{javaeeTestBean.value}" />
jsfc属性を定義して、その値にJSFタグ名である「h:inputText」を指定する。これで<h:inputText>タグを使用してるのと同じこととなる。 この形式のメリットは、inputタグを使用しているので、JavaEE上でなくても、ブラウザでそのまま確認できることである。
■JSF2.2の記述
<input type="text" jsf:value="#{javaeeTestBean.value}" />
通常のHTMLタグの属性に「jsf:」を付与するだけ。JSF2.1より記述が簡単になった(JSFタグ名を覚えなくてよい)。 「jsf:」は属性のどれか1つに付加されていればよく、id属性、value属性、action属性などに付けることが多い。
②ビューコンポーネントと管理Beanの紐づけについて
入力値や出力値の紐づけはvalue属性で行う。サンプルのtest.xhtmlのコードから抜粋すると以下のようになる。
<input type="text" jsf:value="#{javaeeTestBean.value}" />
<h:outputText value="#{javaeeTestBean.value}" />
次にイベントと管理Beanクラスのメソッドの紐づけについて説明する。
これはaction属性で紐づける。 先ほどと同様にEL式で「CDI上の管理Bean名.メソッド名」を記述する。なおメソッドの「()」は無くても動作するようである。
<h:commandButton value="送信" action="#{javaeeTestBean.send()}" />
上記の<h:commandButton>は「input type="submit"」相当のタグである。inputタグで記述すると以下のようになる。 「jsf:」でマークアップし、JSF化するのを忘れないように注意。
<input type="submit" value="送信" jsf:action="#{javaeeTestBean.send()}" />