实体bean:message
//$Id: Message.java 902 2006-01-13 14:19:20Z theute $ package org.jboss.seam.example.messages; import static org.jboss.seam.ScopeType.EVENT; import java.io.Serializable; import java.util.Date; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Lob; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.hibernate.validator.Length; import org.hibernate.validator.NotNull; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; @Entity 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; } }
-------------------------------------------------------------------------------------------------------------------------
session 接口:
//$Id: MessageManager.java 1584 2006-05-23 05:30:24Z gavin $ package org.jboss.seam.example.messages; import javax.ejb.Local; @Local public interface MessageManager { public void findMessages(); public void select(); public void delete(); public void destroy(); }
---------------------------------------------------------------------------------------------------------------------------------
session bean:
//$Id: MessageManagerBean.java 2711 2006-11-19 21:01:33Z gavin $ package org.jboss.seam.example.messages; import static javax.persistence.PersistenceContextType.EXTENDED; import static org.jboss.seam.ScopeType.SESSION; import java.io.Serializable; import java.util.List; import javax.ejb.Remove; import javax.ejb.Stateful; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.jboss.seam.annotations.Destroy; import org.jboss.seam.annotations.Factory; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.datamodel.DataModel; import org.jboss.seam.annotations.datamodel.DataModelSelection; @Stateful
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")
MessageManagerBean 的实例并调用 findMessages() 方法来初始化上下文变量。
我们把 findMessages() 当作 messages 的 工厂方法。
public void findMessages() { messageList = em.createQuery("select msg from Message msg order by msg.datetime desc").getResultList(); } public void select() { if (message!=null) message.setRead(true);
} public void delete() { if (message!=null) { messageList.remove(message); em.remove(message); message=null; }
} @Remove @Destroy public void destroy() {}
}
------------------------------------------------------------------------------------------------------------------
页面:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %> <html> <head> <title>Messages</title> </head> <body> <f:view> <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> <s:link 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}"> <s:convertDateTime type="both" dateStyle="medium" timeStyle="short"/> </h:outputText> </h:column> <h:column> <s:button value="Delete" action="#{messageManager.delete}"/> </h:column> </h:dataTable> <h3><h:outputText value="#{message.title}"/></h3> <div><h:outputText value="#{message.text}"/></div> </f:view> </body> </html>
-----------------------------------------------------------------------------------------------------------------------
工作原理
当我们首次浏览 messages.jsp 页面时,无论是否由回传(postback)的JSF(页面请求)或浏览器直接的GET请求(非页面请求),此JSP页面将设法解析
messagelist 上下文变量。 由于上下文变量尚未被初始化,因此Seam将调用工厂方法 findmessages(),该方法执行了一次数据库查询并导致 DataModel 被向外注入。 DataModel 提供了渲染 <h:dataTable> 所需的行数据。
当用户点击 <h:commandLink> 时,JSF就调用 Select() 动作监听器。 Seam拦截此调用并将所选行的数据注入给 messageManager 组件的 message 属性。 而动作监听器将所选定的 Message 标为已读。在此调用结束时,Seam向外注入所选定的 Message 给名为 message 的变量。 接着,EJB容器提交事务,将 Message 的已读标记写入数据库。 最后,该网页重新渲染,再次显示消息列表,并在列表下方显示所选消息的内容。
如果用户点击了 <h:commandButton>,JSF就调用 delete() 动作监听器。 Seam拦截此调用并将所选行的数据注入给 messageManager 组件的 message 属性。 触发动作监听器,将选定的 Message 从列表中删除并同时在 EntityManager 中调用 remove() 方法。在此调用的最后,Seam刷新 messageList 上下文变量并清除名为 message 的上下文变量。 接着,EJB容器提交事务,将 Message 从数据库中删除。最后,该网页重新渲染,再次显示消息列表。