Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

2.3. Clickable lists in Seam: the messages example

Clickable lists of database search results are such an important part of any online application that Seam provides special functionality on top of JSF to make it easier to query data using EJB-QL or HQL and display it as a clickable list using a JSF <h:dataTable>. The messages example demonstrates this functionality.

2.3.1. Understanding the code

The message list example has one entity bean, Message, one session bean, MessageListBean and one JSP.

2.3.1.1. The entity bean: Message.java

The Message entity defines the title, text, date and time of a message, and a flag indicating whether the message has been read:
@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;
   }
   
}
Example 2.10. 

2.3.1.2. The stateful session bean: MessageManagerBean.java

Just like in the previous example, we have a session bean, MessageManagerBean, which defines the action listener methods for the two buttons on our form. One of the buttons selects a message from the list, and displays that message. The other button deletes a message. So far, this is not so different to the previous example.
But MessageManagerBean is also responsible for fetching the list of messages the first time we navigate to the message list page. There are various ways the user could navigate to the page, and not all of them are preceded by a JSF action—the user might have bookmarked the page, for example. So the job of fetching the message list takes place in a Seam factory method , instead of in an action listener method.
We want to cache the list of messages in memory between server requests, so we will make this a stateful session bean.
@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("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 @Destroy
   public void destroy() {}

}
  1. The @DataModel annotation exposes an attibute of type java.util.List to the JSF page as an instance of javax.faces.model.DataModel. This allows us to use the list in a JSF <h:dataTable> with clickable links for each row. In this case, the DataModel is made available in a session context variable named messageList.
  2. The @DataModelSelection annotation tells Seam to inject the List element that corresponded to the clicked link.
  3. The @Out annotation then exposes the selected value directly to the page. So every time a row of the clickable list is selected, the Message is injected to the attribute of the stateful bean, and the subsequently outjected to the event context variable named message.
  4. This stateful bean has an EJB3 extended persistence context . The messages retrieved in the query remain in the managed state as long as the bean exists, so any subsequent method calls to the stateful bean can update them without needing to make any explicit call to the EntityManager.
  5. The first time we navigate to the JSP page, there will be no value in the messageList context variable. The @Factory annotation tells Seam to create an instance of MessageManagerBean and invoke the findMessages() method to initialize the value. We call findMessages() a factory method for messages.
  6. The select() action listener method marks the selected Message as read, and updates it in the database.
  7. The delete() action listener method removes the selected Message from the database.
  8. All stateful session bean Seam components must have a method marked @Remove @Destroy to ensure that Seam will remove the stateful bean when the Seam context ends, and clean up any server-side state.
Example 2.11. 

Note that this is a session-scoped Seam component. It is associated with the user login session, and all requests from a login session share the same instance of the component. (In Seam applications, we usually use session-scoped components sparingly.)

2.3.1.3. The session bean local interface: MessageManager.java

All session beans have a business interface, of course.
@Local
public interface MessageManager
{
   public void findMessages();
   public void select();
   public void delete();
   public void destroy();
}
From now on, we won't show local interfaces in our code examples.
Let's skip over components.xml, persistence.xml, web.xml, ejb-jar.xml, faces-config.xml and application.xml since they are much the same as the previous example, and go straight to the JSP.

2.3.1.4. The view: messages.jsp

The JSP page is a straightforward use of the JSF <h:dataTable> component. Again, nothing specific to Seam.
<%@ taglib uri="https://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="https://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>
Example 2.12. 


 
 
  Published under the terms of the Open Publication License Design by Interspire