1.3. Seam のクリック可能な一覧 : メッセージサンプル
クリックするとデータベースの検索結果を一覧表示できる機能は、あらゆるオンラインアプリケーションの非常に重要な部分です。 Seam は JSF に加えて特殊な機能を提供することで EJB-QL や HQL でのデータ問い合わせを容易にし、 JSF
<h:dataTable> を使ってクリック可能な一覧としてそれを表示します。メッセージサンプルがこの機能を示しています。
1.3.1. コードの理解 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
このメッセージサンプルは 1 つのエンティティ Bean (
Message)、1 つのセッション Bean (MessageListBean)、1 つの JSP から構成されています。
1.3.1.1. エンティティ Bean : Message.java リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Message エンティティ Bean は、タイトル、テキスト、メッセージの日付と時刻、そしてメッセージが既読か否かを示すフラグを定義します。
例1.12 Message.java
@Entity
@Name("message")
@Scope(EVENT)
public class Message implements Serializable {
private Long id;
private String title;
private String text;
private boolean read;
private Date datetime;
@Id @GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@NotNull @Length(max=100)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@NotNull @Lob
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@NotNull
public boolean isRead() {
return read;
}
public void setRead(boolean read) {
this.read = read;
}
@NotNull
@Basic @Temporal(TemporalType.TIMESTAMP)
public Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}
}
1.3.1.2. ステートフルセッション Bean : MessageManagerBean.java リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
前述のサンプル同様、 このサンプルは 1 つのセッション Bean (
MessageManagerBean) から構成され、 フォームにある両方のボタンに対応するアクションリスナーメソッドを定義します。 前述のサンプルと同様、 ボタンの 1 つは一覧からメッセージを選択してそのメッセージを表示します。 もう 1 つのボタンはメッセージを削除します。
ただし、 はじめてメッセージ一覧のページに移動したときのメッセージの一覧取得も
MessageManagerBean の役割となります。 ユーザーがこのページに到達するにはいろいろな経路があり、 必ずしも JSF アクションがすべての経路で先行するわけではありません。 (たとえば、 お気に入りからそのページに行く場合、 必ずしも JSF アクションを呼び出す必要はありません。) したがって、 メッセージ一覧の取得作業はアクションリスナーメソッドではなく Seam の ファクトリメソッド で行われなければなりません。
メッセージの一覧をサーバー要求にまたがってメモリにキャッシュしたいので、 ステートフルセッション Bean でこれを行います。
例1.13 MessageManagerBean.java
@Stateful
@Scope(SESSION)
@Name("messageManager")
public class MessageManagerBean
implements Serializable, MessageManager
{
@DataModel
private List<Message> messageList;
@DataModelSelection
@Out(required=false)
private Message message;
@PersistenceContext(type=EXTENDED)
private EntityManager em;
@Factory("messageList")
public void findMessages()
{
messageList = em.createQuery("select msg " +
"from Message msg" +
"order by msg.datetime desc")
.getResultList();
}
public void select()
{
message.setRead(true);
}
public void delete()
{
messageList.remove(message);
em.remove(message);
message=null;
}
@Remove
public void destroy() {}
}
| @DataModel アノテーションは、 java.util.List タイプの属性を、 javax.faces.model.DataModel インスタンスとして JSF ページに公開します。これにより、各行に対してクリック可能なリンクを持つ JSF <h:dataTable> 中の一覧を使用可能とします。 このサンプルでは、 DataModel は、 messageList という名前のセッションコンテキスト変数で利用可能です。
|
| @DataModelSelection アノテーションは Seam にクリックされたリンクに該当する List エレメントをインジェクトするよう指示します。
|
|
次に @Out アノテーションは選択された値を直接ページに公開します。クリック可能な一覧の行が選択されるたびに Message がステートフル Bean の属性にインジェクトされ、続いて message というイベントコンテキスト変数に アウトジェクト されます。
|
|
このステートフル Bean は EJB3 拡張永続コンテキスト を持っています。この Bean が存在する限り、クエリで取得されたメッセージは管理状態に留まります。そのため、ステートフル Bean への後続のメッセージ呼び出しは、 EntityManager へ明示的な呼び出しを行わずにそのメッセージを更新することができます。
|
|
初めて JSP ページに移動するとき、 messageList コンテキスト変数には値がありません。@Factory アノテーションは Seam に MessageManagerBean インスタンスを作成し、findMessages() メソッドを呼び出し、値を初期化するよう指示します。findMessages() を messages の ファクトリメソッド と呼びます。
|
| select() アクションリスナーメソッドは、 選択された Message に既読マークを付け、 データベース中のそれを更新します。
|
| delete() アクションリスナーメソッドは、 選択された Message をデータベースから削除します。
|
|
ステートフルセッション Bean の Seam コンポーネントは @Remove とマークされたパラメータを持たないメソッドを定義する 必要があります。Seam コンテキストが終了すると、Seam はステートフル Bean を削除しサーバー側の状態を消去します。
|
注記
これはセッションスコープの Seam コンポーネントです。 ユーザーログインのセッションと関連付けられ、 ログインセッションからの要求はすべて同じコンポーネントのインスタンスを共有します。 Seam アプリケーションではセッションスコープのコンポーネントは通常、控えめに使用されます。
1.3.1.3. セッション Bean ローカルインタフェース : MessageManager.java リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
すべてのセッション Bean にビジネスインターフェースがあります。
例1.14 MessageManager.java
@Local
public interface MessageManager {
public void findMessages();
public void select();
public void delete();
public void destroy();
}
この時点から、ローカルインターフェースはこれらのコードサンプルには表示されなくなります。
Components.xml、 persistence.xml、 web.xml、 ejb-jar.xml、 faces-config.xml、 application.xml については前述までのサンプルとほぼ同じなので、 JSP に進みます。
1.3.1.4. ビュー: messages.jsp リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
この JSP ページは JSF
<h:dataTable> コンポーネントを使用した簡単なものです。繰り返しになりますが、この機能も Seam 固有ではありません。
例1.15 messages.jsp
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<title>Messages</title>
</head>
<body>
<f:view>
<h:form>
<h2>Message List</h2>
<h:outputText value="No messages to display"
rendered="#{messageList.rowCount==0}"/>
<h:dataTable var="msg" value="#{messageList}"
rendered="#{messageList.rowCount>0}">
<h:column>
<f:facet name="header">
<h:outputText value="Read"/>
</f:facet>
<h:selectBooleanCheckbox value="#{msg.read}" disabled="true"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Title"/>
</f:facet>
<h:commandLink value="#{msg.title}"
action="#{messageManager.select}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Date/Time"/>
</f:facet>
<h:outputText value="#{msg.datetime}">
<f:convertDateTime type="both" dateStyle="medium"
timeStyle="short"/>
</h:outputText>
</h:column>
<h:column>
<h:commandButton value="Delete"
action="#{messageManager.delete}"/>
</h:column>
</h:dataTable>
<h3><h:outputText value="#{message.title}"/></h3>
<div><h:outputText value="#{message.text}"/></div>
</h:form>
</f:view>
</body>
</html>







