Stateful components
    
       
    
       The hotel search page is backed by the a stateful session bean named
       hotelSearch and implemented by the class 
       HotelSearchingAction.
    
<h:inputText id="searchString" value="#{hotelSearch.searchString}" >
    <a:support event="onkeyup" actionListener="#{hotelSearch.find}" 
               reRender="searchResults"/>
</h:inputText>
<h:selectOneMenu value="#{hotelSearch.pageSize}" id="pageSize">
    <f:selectItem itemLabel="5" itemValue="5"/>
    <f:selectItem itemLabel="10" itemValue="10"/>
    <f::selectItem itemLabel="20" itemValue="20"/>
</h:selectOneMenu>
    
       When the button is clicked, the form is submitted and JSF sets the value 
       of the text box and drop down menu onto the searchString and
       pageSize attributes of HotelSearchingAction 
       before calling the find() action listener method. We've used a 
       session-scope stateful bean because we want it's state (the search results) to 
       be held in the session between requests to the server.  The <a:support>
       tax specfies that after a keypress, the contents of the <a:outputPanel> whose
       id is searchResults should be rerendererd.  This is done through an AJAX-style
       call back to the server with no additional code required of the application.
    
@Stateful
@Name("hotelSearch")
@Scope(ScopeType.SESSION)
@LoggedIn
public class HotelSearchingAction implements HotelSearching
{
   @PersistenceContext
   private EntityManager em;
   
   private String searchString;
   private int pageSize = 10;
   private int page;
   
   @DataModel
   private List<Hotel> hotels;
   
   public void find()
   {
      page = 0;
      queryHotels();
   }
   public void nextPage()
   {
      page++;
      queryHotels();
   }
      
   private void queryHotels()
   {
      hotels = em.createQuery("select h from Hotel h where lower(h.name) " + 
                              "like #{pattern} or lower(h.city) like #{pattern} " + 
                              "or lower(h.zip) like #{pattern} or " + 
                              "lower(h.address) like #{pattern}")
            .setMaxResults(pageSize)
            .setFirstResult( page * pageSize )
            .getResultList();
   }
   
   public boolean isNextPageAvailable()
   {
      return hotels!=null && hotels.size()==pageSize;
   }
   
   public int getPageSize() {
      return pageSize;
   }
   
   public void setPageSize(int pageSize) {
      this.pageSize = pageSize;
   }
   
   @Factory(value="pattern", scope=ScopeType.EVENT)
   public String getSearchPattern()
   {
      return searchString==null ? 
            "%" : '%' + searchString.toLowerCase().replace('*', '%') + '%';
   }
   
   public String getSearchString()
   {
      return searchString;
   }
   
   public void setSearchString(String searchString)
   {
      this.searchString = searchString;
   }
   
   @Remove
   public void destroy() {}
}
    
       The find() method retrieves a list of hotels from the database and
       initializes the hotels field. The hotels field is marked 
       with the @DataModel annotation, so when the find() method
       returns, Seam outjects an instance of ListDataModel to a context
       variable named hotels. So, when the search page is re-rendered, the
       result list is available to the JSF dataTable. 
       Each row of the data table has an associated command button or link 
       (see below). 
    
<h:outputText value="No Hotels Found" 
              rendered="#{hotels != null and hotels.rowCount==0}"/>
<h:dataTable value="#{hotels}" var="hot" rendered="#{hotels.rowCount>0}">
	<h:column>
		<f:facet name="header">Name</f:facet>
		#{hot.name}
	</h:column>
	<h:column>
		<f:facet name="header">Address</f:facet>
		#{hot.address}
	</h:column>
	<h:column>
		<f:facet name="header">City, State</f:facet>
		#{hot.city}, #{hot.state}
	</h:column>
	<h:column>
		<f:facet name="header">Zip</f:facet>
		#{hot.zip}
	</h:column>
	<h:column>
		<f:facet name="header">Action</f:facet>
		<s:link value="View Hotel" 
                        action="#{hotelBooking.selectHotel(hot)}"/>
	</h:column>
</h:dataTable>
    
       The "View Hotel" link is the above mentioned command link associated
       with each row of the data table. It is implemented 
       using a Seam <s:link>, which is part of Seam's 
       extension of JSF controls.
       This JSF control let's us call an action, and pass a request parameter, without 
       submitting any JSF form. The advantage of <s:link> is that, 
       unlike a standard JSF <h:commandLink>, there is no JavaScript 
       used, so "open link in new tab" works seamlessly.
    
       When this link is clicked, the selectHotel() method of the
       HotelBookingAction bean is called with the hot
       parameter that is specified in the query.  The parameter values are evaluated
       at invocation time, not when the link is generated, so the <s:link>
       tag adds a dataModelSelection parameter that indicates the value of the 
       hot loop variable for the given row.
  The selectHotel() method merges the selected hotel into 
       the current persistence context (in case the same
       hotel has been accessed before in the same session),
       and starts a Seam conversation. We will discuss Seam conversations
       in the next step.
    
@Stateful
@Name("hotelBooking")
@LoggedIn
public class HotelBookingAction implements HotelBooking
{
   ... ...
   
   @Begin
   public void selectHotel(Hotel selectedHotel)
   {
      hotel = em.merge(selectedHotel);
   }
}