Stateful components
 
    
       
    
       The hotel search page is backed by the a stateful session bean named
       hotelSearch and implemented by the class 
       HotelSearchingAction.
    
<h:inputText value="#{hotelSearch.searchString}" />
<h:commandButton value="Find Hotels" 
    action="#{hotelBooking.find}" 
    styleClass="button" />
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
<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.
    
@Stateful
@Name("hotelSearch")
@Scope(ScopeType.SESSION)
@LoggedIn
public class HotelSearchingAction implements HotelSearching
{
   
   @PersistenceContext
   private EntityManager em;
   
   private String searchString;
   private int pageSize = 10;
   
   @DataModel
   private List<Hotel> hotels;
   @DataModelSelection
   private Hotel selectedHotel;
   
   public String find()
   {
      String searchPattern = searchString==null ? "%" : '%' + searchString.toLowerCase().replace('*', '%') + '%';
      hotels = em.createQuery("from Hotel where lower(name) like :search or lower(city) like :search or lower(zip) like :search or lower(address) like :search")
            .setParameter("search", searchPattern)
            .setMaxResults(pageSize)
            .getResultList();
      
      return "main";
   }
   
   public Hotel getSelectedHotel()
   {
      return selectedHotel;
   }
   
   public int getPageSize() {
      return pageSize;
   }
   public void setPageSize(int pageSize) {
      this.pageSize = pageSize;
   }
   public String getSearchString()
   {
      return searchString;
   }
   public void setSearchString(String searchString)
   {
      this.searchString = searchString;
   }
   
   @Destroy @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). When the user
       clicks on the button / link, the Hotel represented by that
       row is injected into the hotel field annotated by the
       @DataModelSelection annotation. Other application components
       can then access the selected hotel via the
       HotelSearching.selectedHotel property.
    
<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}"/>
	</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. It gets the selected
       hotel from the HotelSearching.selectedHotel property,
       merges it to 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 String selectHotel()
   {
      hotel = em.merge( hotelSearch.getSelectedHotel() );
      return "hotel";
   }
}