[jboss-cvs] jboss-seam/examples/jee5/view/exp ...

Peter Muir peter at bleepbleep.org.uk
Sat Jun 23 14:34:01 EDT 2007


  User: pmuir   
  Date: 07/06/23 14:34:01

  Added:       examples/jee5/view/exp        loginExp.html
                        workspaceExp.html mainExp.html confirmExp.html
                        registerExp.html introExp.html bookingExp.html
  Log:
  JBSEAM-1449 - rename glassfish to jee5 and add support for OC4J (thanks to Richard Hoffman for this!)
  
  Revision  Changes    Path
  1.1      date: 2007/06/23 18:34:01;  author: pmuir;  state: Exp;jboss-seam/examples/jee5/view/exp/loginExp.html
  
  Index: loginExp.html
  ===================================================================
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
  	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  	<title>In-depth Explanation</title>
  	<link href="../css/trailblazer_main.css" rel="stylesheet" type="text/css" />
  </head>
  
  <body>
  
  <div id="main">
    <div class="trail">
      <div class="numbox">2</div>
      <h2>What happens when you login?</h2>
      <img src="../img/header_line.gif" />
      
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
      
      <p>
         The login page is defined using pure XHTML with JSF controls. 
         The form uses JSF EL value binding and method binding 
         expressions to refer to Seam components. For example, 
         <code>#{user.username}</code> refers to a property of the
         <code>User</code> entity bean and <code>#{login.login}</code> 
         refers to a method of the <code>LoginAction</code> stateless 
         session bean. Both beans are EJB 3.0 POJOs managed by Seam.
      </p>
  
  <code class="block">
  &lt;div&gt;
      &lt;h:outputLabel for="username">Login Name&lt;/h:outputLabel>
      &lt;h:inputText id="username" value="#{user.username}" />
  &lt;/div&gt;
  &lt;div&gt;
      &lt;h:outputLabel for="password">Password&lt;/h:outputLabel>
      &lt;h:inputSecret id="password" value="#{user.password}" />
  &lt;/div&gt;
  
  ... ...
  
  &lt;div class="buttonBox"&gt;
      &lt;h:commandButton action="#{login.login}" 
                       value="Account Login" class="button" /&gt;
  &lt;/div&gt;
  </code>
  
      <p>
         The <code>User</code> enity bean is mapped to the Seam  
         context variable named <code>user</code> bean via the 
         <code>@Name</code> annotation. <code>User</code> is
         a session scoped bean, meaning that the <code>user</code>
         component value is retained for the entire session for
         each user. You might also notice there are validation annotation
         on the data properties. We will discuss those annotations in the
         <a href="registerExp.html">next step</a>.
      </p>
  
  <code class="block">
  @Entity
  @Name("user")
  @Scope(SESSION)
  public class User implements Serializable {
     private String username;
     private String password;
     private String name;
  
     @NotNull
     @Length(min=5, max=15)
     public String getPassword() {
        return password;
     }
     public void setPassword(String password) {
        this.password = password;
     }
     
     @Id
     @Length(min=5, max=15)
     public String getUsername () {
        return username;
     }
     public void setUsername (String username) {
        this.username = username;
     }
  
      // ... ...
  }
  </code>
  
      <p>
         <code>LoginAction</code> is an EJB 3.0 session bean mapped 
         to the Seam context variable named <code>login</code>. When 
         the login button is clicked, the JSF method binding 
         <code>#{login.login}</code> is evaluated, and the 
         <code>login()</code> method is invoked upon <code>LoginAction</code>.
      </p>
  
  <code class="block">
  @Stateless
  @Name("login")
  public class LoginAction implements Login
  {
     
     @In @Out
     private User user;
     
     @PersistenceContext
     private EntityManager em;
  
     public String login()
     {
        List&lt;User&gt; results = em.createQuery("from User where username=:username and password=:password")
              .setParameter("username", user.getUsername())
              .setParameter("password", user.getPassword())
              .getResultList();
        
        if ( results.size()==0 )
        {
           FacesMessages.instance().add("Invalid login");
           return "login";
        }
        else
        {
           user = results.get(0);
           Contexts.getSessionContext().set("loggedIn", true);         
           return "main";
        }
        
     }
  
  }
  </code>
  
      <p>
         The <code>@In</code> annotation tells Seam to inject a <code>User</code> 
         when any method of <code>LoginAction</code> is invoked. The <code>@Out</code> 
         annotation indicates the <code>LoginAction</code> bean can change the
         value of the <code>user</code> context variable and make the new instance 
         available to other session beans and JSF pages.
      </p>
  
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
    </div>
  </div>
  
  </body>
  </html>
  
  
  
  1.1      date: 2007/06/23 18:34:01;  author: pmuir;  state: Exp;jboss-seam/examples/jee5/view/exp/workspaceExp.html
  
  Index: workspaceExp.html
  ===================================================================
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
  	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  	<title>In-depth Explanation</title>
  	<link href="../css/trailblazer_main.css" rel="stylesheet" type="text/css" />
  </head>
  
  <body>
  
  <div id="main">
    <div class="trail">
      <div class="numbox">6</div>
      <h2>The Workspace List</h2>
      <img src="../img/header_line.gif" />
      
      <p>
         <center>
         <form>
            <INPUT type="button" value="Close Window" onclick="window.close()">
         </form>
         </center>
      </p>
  
      <p>
         The workspace list allows the user to switch between multiple
         conversations from the same browser tab. There is no Java code
         to write, just the following JSF code to include:
      </p>
  
  <code class="block">
  &lt;h:dataTable value="#{conversationList}" var="entry"&gt;
    &lt;h:column&gt;
      &lt;h:commandLink action="#{entry.select}" value="#{entry.description}"/&gt;
      &nbsp;
      &lt;h:outputText value="[current]" rendered="#{entry.current}"/&gt;
    &lt;/h:column&gt;
    &lt;h:column&gt;
      &lt;h:outputText value="#{entry.startDatetime}"&gt;
        &lt;f:convertDateTime type="time" pattern="hh:mm"/&gt;
      &lt;/h:outputText&gt;
      -
      &lt;h:outputText value="#{entry.lastDatetime}"&gt;
        &lt;f:convertDateTime type="time" pattern="hh:mm"/&gt;
      &lt;/h:outputText&gt;
    &lt;/h:column&gt;
  &lt;/h:dataTable&gt;
  </code>
  
      <p>
         We do need to specify what text will be displayed by <code>#{entry.description}</code>. 
         We do this by creating a <code>pages.xml</code> file in our <code>WEB-INF</code> 
         directory.
      </p>
  
  <code class="block">
  &lt;pages&gt;
    &lt;page view-id="/hotel.xhtml"&gt;View hotel: #{hotel.name}&lt;/page&gt;
    &lt;page view-id="/book.xhtml"&gt;Book hotel: #{hotel.name}&lt;/page&gt;
    &lt;page view-id="/confirm.xhtml"&gt;Confirm: #{booking.description}&lt;/page&gt;
  &lt;/pages&gt;
  </code>
  
      <p>
         Note that you don't need the <code>pages.xml</code> file if you don't want the
         workspace list in your application.
      </p>
  
      <p>
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
      </p>
  
    </div>
  </div>
  
  </body>
  </html>
  
  
  
  1.1      date: 2007/06/23 18:34:01;  author: pmuir;  state: Exp;jboss-seam/examples/jee5/view/exp/mainExp.html
  
  Index: mainExp.html
  ===================================================================
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
  	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  	<title>In-depth Explanation</title>
  	<link href="../css/trailblazer_main.css" rel="stylesheet" type="text/css" />
  </head>
  
  <body>
  
  <div id="main">
    <div class="trail">
      <div class="numbox">4</div>
      <h2>Stateful components</h2>
      <img src="../img/header_line.gif" />
      
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
      <p>
         The hotel search page is backed by the a stateful session bean named
         <code>hotelSearch</code> and implemented by the class 
         <code>HotelSearchingAction</code>.
      </p>
  
  <code class="block">
  &lt;h:inputText value="#{hotelSearch.searchString}" /&gt;
  &lt;h:commandButton value="Find Hotels" 
      action="#{hotelBooking.find}" 
      styleClass="button" /&gt;
  &lt;h:outputLabel for="pageSize"&gt;Maximum results:&lt;/h:outputLabel&gt;
  &lt;h:selectOneMenu value="#{hotelSearch.pageSize}" id="pageSize"&gt;
      &lt;f:selectItem itemLabel="5" itemValue="5"/&gt;
      &lt;f:selectItem itemLabel="10" itemValue="10"/&gt;
      &lt;f:selectItem itemLabel="20" itemValue="20"/&gt;
  &lt;/h:selectOneMenu&gt;
  </code>
  
      <p>
         When the button is clicked, the form is submitted and JSF sets the value 
         of the text box and drop down menu onto the <code>searchString</code> and
         <code>pageSize</code> attributes of <code>HotelSearchingAction</code> 
         before calling the <code>find()</code> 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.
      </p>
  
  <code class="block">
  @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&lt;Hotel&gt; 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() {}
  
  }</code>
  
      <p>
         The <code>find()</code> method retrieves a list of hotels from the database and
         initializes the <code>hotels</code> field. The <code>hotels</code> field is marked 
         with the <code>@DataModel</code> annotation, so when the <code>find()</code> method
         returns, Seam outjects an instance of <code>ListDataModel</code> to a context
         variable named <code>hotels</code>. So, when the search page is re-rendered, the
         result list is available to the JSF <code>dataTable</code>. 
         Each row of the data table has an associated command button or link 
         (see below). When the user
         clicks on the button / link, the <code>Hotel</code> represented by that
         row is injected into the <code>hotel</code> field annotated by the
         <code>@DataModelSelection</code> annotation. Other application components
         can then access the selected hotel via the
         <code>HotelSearching.selectedHotel</code> property.
      </p>
  
  <code class="block">
  &lt;h:outputText value="No Hotels Found" rendered="#{hotels != null and hotels.rowCount==0}"/&gt;
  &lt;h:dataTable value="#{hotels}" var="hot" rendered="#{hotels.rowCount>0}"&gt;
  	&lt;h:column&gt;
  		&lt;f:facet name="header"&gt;Name&lt;/f:facet&gt;
  		#{hot.name}
  	&lt;/h:column&gt;
  	&lt;h:column&gt;
  		&lt;f:facet name="header"&gt;Address&lt;/f:facet&gt;
  		#{hot.address}
  	&lt;/h:column&gt;
  	&lt;h:column&gt;
  		&lt;f:facet name="header"&gt;City, State&lt;/f:facet&gt;
  		#{hot.city}, #{hot.state}
  	&lt;/h:column&gt;
  	&lt;h:column&gt;
  		&lt;f:facet name="header"&gt;Zip&lt;/f:facet&gt;
  		#{hot.zip}
  	&lt;/h:column&gt;
  	&lt;h:column&gt;
  		&lt;f:facet name="header"&gt;Action&lt;/f:facet&gt;
  		&lt;s:link value="View Hotel" action="#{hotelBooking.selectHotel}"/&gt;
  	&lt;/h:column&gt;
  &lt;/h:dataTable&gt;
  </code>
  
      <p>
         The "View Hotel" link is the above mentioned command link associated
         with each row of the data table. It is implemented 
         using a Seam <code>&lt;s:Link&gt;</code>, 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 <code>&lt;s:link&gt;</code> is that, 
         unlike a standard JSF <code>&lt;h:commandLink&gt;</code>, there is no JavaScript 
         used, so "open link in new tab" works seamlessly.
      </p>
      <p>
         When this link is clicked, the <code>selectHotel()</code> method of the
         <code>HotelBookingAction</code> bean is called. It gets the selected
         hotel from the <code>HotelSearching.selectedHotel</code> 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.
      </p>
      
  <code class="block">
  @Stateful
  @Name("hotelBooking")
  @LoggedIn
  public class HotelBookingAction implements HotelBooking
  {
  
     ... ...
     
     @Begin
     public String selectHotel()
     {
        hotel = em.merge( hotelSearch.getSelectedHotel() );
        return "hotel";
     }
  }
  </code>
  
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
    </div>
  </div>
  
  </body>
  </html>
  
  
  
  1.1      date: 2007/06/23 18:34:01;  author: pmuir;  state: Exp;jboss-seam/examples/jee5/view/exp/confirmExp.html
  
  Index: confirmExp.html
  ===================================================================
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
  	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  	<title>In-depth Explanation</title>
  	<link href="../css/trailblazer_main.css" rel="stylesheet" type="text/css" />
  </head>
  
  <body>
  
  <div id="main">
    <div class="trail">
      <div class="numbox">7</div>
      <h2>Ending Conversations</h2>
      <img src="../img/header_line.gif" />
      
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
      <p>
         The "Confirm" button is bound to the action method <code>confirm()</code>
         of <code>HotelBookingAction</code>.
      </p>
  
  <code class="block">
  &lt;h:commandButton value="Confirm" 
                   action="#{hotelBooking.confirm}" 
                   class="button"/&gt;
  </code>
  
      <p>
         The <code>confirm()</code> method is tagged with the <code>@End</code> annotation, 
         which ends the long-running conversation and results in all state associated with
         the conversation being destroyed at the end of the request. Actually, since the
         <code>confirmed</code> outcome triggers a redirect, the state will not be destroyed
         until <em>after the redirect completes</em>. Note that even the success message
         that we create using the built-in <code>facesMessages</code> component is transparently
         propagated across the redirect!
      </p>
  
  <code class="block">
     @End
     public String confirm()
     {
        if (booking==null || hotel==null) return "main";
        em.persist(booking);
        facesMessages.add("Thank you, #{user.name}, your confimation number for #{hotel.name} is #{booking.id}");
        log.info("New booking: #{booking.id} for #{user.username}");
        events.raiseEvent("bookingConfirmed");
        return "confirmed";
     }
     
     @End
     public String cancel()
     {
        return "main";
     }
     
     @Destroy @Remove
     public void destroy() {}
  }
  </code>
  
     <p>
        When the conversation state is finally destroyed, Seam calls the <code>@Destroy</code> method,
        which results in removal of the SFSB.
     </p>
     
     <p>
        Notice that the <code>HotelBookingAction.confirm()</code> method
        raises a <code>bookingConfirmed</code> event before it finishes. The
        event mechanism allows Seam components to communicate with each other
        without direct coupling. In this case, the <code>BookingListAction</code>
        component captures the <code>bookingConfirmed</code> event and refreshes
        the existing booking list for the current user.
     </p>
     
  <code class="block">
  public class BookingListAction implements BookingList, Serializable
  {
  
     ... ...
     
     @Factory
     @Observer("bookingConfirmed")
     public void getBookings()
     {
        bookings = em.createQuery("from Booking b where b.user.username = :username order by b.checkinDate")
              .setParameter("username", user.getUsername())
              .getResultList();
     }
  }
  </code>
     
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
    </div>
  </div>
  
  </body>
  </html>
  
  
  1.1      date: 2007/06/23 18:34:01;  author: pmuir;  state: Exp;jboss-seam/examples/jee5/view/exp/registerExp.html
  
  Index: registerExp.html
  ===================================================================
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
  	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  	<title>In-depth Explanation</title>
  	<link href="../css/trailblazer_main.css" rel="stylesheet" type="text/css" />
  </head>
  
  <body>
  
  <div id="main">
    <div class="trail">
      <div class="numbox">3</div>
      <h2>What happens in the registration process?</h2>
      <img src="img/header_line.gif" />
      
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
      <p>
         The register.xhtml JSF form captures the user input for new account
         registration. It validates the user input, binds the data to a 
         Seam data component, and invokes a Seam UI event handler method
         when the form is submitted.
      </p>
      
  <code class="block">
  &lt;s:validateAll&gt;
  &lt;div class="entry"&gt;
      &lt;div class="label"&gt;
          &lt;h:outputLabel for="username">Username:&lt;/h:outputLabel&gt;
      &lt;/div&gt;
      &lt;div class="input"&gt;
          &lt;h:inputText id="username" value="#{user.username}"/&gt;&lt;br/&gt;
          &lt;span class="errors"&gt;&lt;h:message for="username" /&gt;&lt;/span&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="entry"&gt;
      &lt;div class="label"&gt;
          &lt;h:outputLabel for="name">Real Name:&lt;/h:outputLabel&gt;
      &lt;/div&gt;
      &lt;div class="input"&gt;
          &lt;h:inputText id="name" value="#{user.name}" /&gt;&lt;br/&gt;
          &lt;span class="errors">&lt;h:message for="name" /&gt;&lt;/span&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  &lt;/s:validateAll&gt;
  
  ... ...
  
      &lt;div class="input"&gt;
          &lt;h:commandButton value="Register" 
                           action="#{register.register}" 
                           class="button"/&gt;
          &lt;h:commandButton value="Cancel" action="login" class="button"/&gt;
      &lt;/div&gt;
  </code>
  
     <p>
        The form fields are bound to properties of a Seam component named
        <code>user</code> via JSF EL value binding expressions such as
        <code>#{user.username}</code>. The form submit button is bound
        to the <code>register()</code> method of the Seam component named
        <code>register</code> using the JSF method binding expression 
        <code>#{register.register}</code>.
     </p>
  
     <p>
         Notice that the input fields are enclosed by a <code>&lt;s:validateAll</code>
         tag. This tag is part of Seam's extension to JSF. It tells the Seam
         runtime to validate those input fields when the form is submitted.
         The validation conditions are specified on the entity bean classes
         those input fields map to (e.g., here the validation condition is
         on the <code>User</code> class, see later).
         This JSF form also includes <code>&lt;h:message&gt;</code> tags that
         will display the results of any JSF validation failures.
      </p>
  
     <p>
        The <code>User</code> class is an EJB 3.0 entity bean with a 
        <code>@Name</code> annotation that binds the bean instance to a
        context variable named <code>user</code>. In addition to the standard 
        EJB 3.0 O/R mapping metadata, this bean features several Hibernate 
        Validator annotations such as 
        <code>@NotNull</code>, <code>@Length</code>. Due to the 
        <code>&lt;s:validateAll</code> tag in the form, these constraints are 
        automatically validated by Seam when the form is submitted. If the user 
        enters invalid data in the JSF form, the form will be redisplayed with 
        error messages.
     </p>
  
  <code class="block">
  @Entity
  @Name("user")
  @Scope(SESSION)
  public class User implements Serializable
  {
     private String username;
     private String password;
     private String name;
     
     public User(String name, String password, String username)
     {
        this.name = name;
        this.password = password;
        this.username = username;
     }
     
     public User() {}
  
     @NotNull
     @Length(max=100)
     public String getName()
     {
        return name;
     }
     public void setName(String name)
     {
        this.name = name;
     }
     
     @NotNull
     @Length(min=5, max=15)
     public String getPassword()
     {
        return password;
     }
     public void setPassword(String password)
     {
        this.password = password;
     }
     
     @Id
     @Length(min=5, max=15)
     public String getUsername()
     {
        return username;
     }
     public void setUsername(String username)
     {
        this.username = username;
     }
     
  }</code>
  
      <p>
         <code>RegisterAction</code> is an EJB 3.0 stateful session bean 
         bound to the Seam context variable named <code>register</code>. 
         The <code>register()</code> method is invoked  when the form is 
         submitted.
      </p>
  
  <code class="block">
  @Stateful
  @Scope(EVENT)
  @Name("register")
  public class RegisterAction implements Register
  {
  
     @In
     private User user;
     
     @PersistenceContext
     private EntityManager em;
     
     @In(create=true)
     private transient FacesMessages facesMessages;
     
     private String verify;
     
     public String register()
     {
        if ( user.getPassword().equals(verify) )
        {
           List existing = em.createQuery("select username from User where username=:username")
              .setParameter("username", user.getUsername())
              .getResultList();
           if (existing.size()==0)
           {
              em.persist(user);
              return "login";
           }
           else
           {
              facesMessages.add("username #{user.username} already exists");
              return null;
           }
        }
        else 
        {
           facesMessages.add("re-enter your password");
           verify=null;
           return null;
        }
     }
  
     public String getVerify()
     {
        return verify;
     }
  
     public void setVerify(String verify)
     {
        this.verify = verify;
     }
     
     @Destroy @Remove
     public void destroy() {}
  }</code>
  
      <p>
         The <code>@In</code> annotations inject Seam components into the <code>RegisterAction</code>
         bean. The <code>user</code> component is our entity bean, of course. The <code>facesMessages</code> 
         component is a built-in Seam component that makes it very easy to display templated and localized
         messages to the user, even when redirect after post is used.
      </p>
  
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
    </div>
  </div>
  
  </body>
  </html>
  
  
  
  1.1      date: 2007/06/23 18:34:01;  author: pmuir;  state: Exp;jboss-seam/examples/jee5/view/exp/introExp.html
  
  Index: introExp.html
  ===================================================================
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
  	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  	<title>In-depth Explanation</title>
  	<link href="../css/trailblazer_main.css" rel="stylesheet" type="text/css" />
  </head>
  
  <body>
  
  <div id="main">
    <div class="trail">
      <div class="numbox">1</div>
      <h2>What is JBoss Seam</h2>
      <img src="../img/header_line.gif" />
      
      <p>
         <center>
         <form>
            <INPUT type="button" value="Close Window" onclick="window.close()">
         </form>
         </center>
      </p>
      
      <p>
         EJB 3.0 and JSF are perhaps the most exciting new developments in the Java EE 5 platform. 
         Seam is an innovative new application framework that integrates the EJB 3.0 component model 
         with JSF as a presentation tier. Seam builds upon the standard extension points provided by 
         both specifications and provides a set of Java annotations that extends the standard 
         annotations defined by the EJB specification. In addition, Seam introduces several innovative 
         new ideas: managed conversations, declarative and contextual application state management, 
         bijection and integrated business process management. 
      </p>
  
      <p>
         Traditional web applications are incredibly vulnerable to bugs and performance problems 
         relating to state management. Developers are forced to handle issues like back button 
         navigation, multi-window browsing, session size management in an utterly ad-hoc fashion. 
         Access to transactional components from the web tier has also been problematic. J2EE 
         provided no way to have simultaneous access to state held in contexts associated with 
         the web request, and state held in transactional resources accessed via EJB. Finally, 
         J2EE had no first-class construct for representing state associated with a long-running 
         business process. Seam tackles all these problems, and provides a uniform model for 
         stateful components in Java EE 5.
      </p>
  				
      <p>
         Like all JBoss software, this entire software stack is free. The full source code of this 
         sample application is available in the <code>examples/booking</code> directory of the 
         <a href="http://www.jboss.com/products/list/downloads#seam">Seam distribution</a>. 
         <!--
         There is even a  
         <a target="_blank" href="http://docs.jboss.com/TrailBlazer/seam-booking/Seam.htm">
            10-minute flash demo 
         </a>
         showing how to build a Seam web application from ground up.
         -->
      </p>
  
      <p>
         <center>
         <form>
            <INPUT type="button" value="Close Window" onclick="window.close()">
         </form>
         </center>
      </p>
  
    </div>
  </div>
  
  </body>
  </html>
  
  
  
  1.1      date: 2007/06/23 18:34:01;  author: pmuir;  state: Exp;jboss-seam/examples/jee5/view/exp/bookingExp.html
  
  Index: bookingExp.html
  ===================================================================
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
  	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  	<title>In-depth Explanation</title>
  	<link href="../css/trailblazer_main.css" rel="stylesheet" type="text/css" />
  </head>
  
  <body>
  
  <div id="main">
    <div class="trail">
      <div class="numbox">5</div>
      <h2>Conversations</h2>
      <img src="../img/header_line.gif" />
      
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
      <p>
         The hotel booking "wizard" is implemented by a conversation-scoped
         stateful session bean. All Seam components are in the 
         conversation scope by default. 
         The <code>HotelBookingAction</code> maintains
         state associated with the booking process in the Seam conversation
         scope. This ensures that if the user is working in multiple brower
         tabs or multiple brower windows, the various conversations are
         completely isolated from each other.
      </p>
      <p>
         To see this working in practice, right click on the "View Hotel" button 
         in the search screen and select "open in new tab" or "open in new window",
         and try working on multiple hotel bookings simultaneously. 
         In the <a href="workspaceExp.html">next step</a>, we will discuss
         Seam's built-in components to manage multiple concurrent conversations.
      </p>
      
  <code class="block">
  @Stateful
  @Name("hotelBooking")
  @LoggedIn
  public class HotelBookingAction implements HotelBooking
  {
     
     @PersistenceContext(type=EXTENDED)
     private EntityManager em;
     
     @In
     private User user;
     
     @In(required=false) @Out
     private Hotel hotel;
     
     @In(required=false) 
     @Out(required=false)
     private Booking booking;
     
     @In(create=true)
     private FacesMessages facesMessages;
        
     @In(create=true)
     private Events events;
        
     @In 
     private HotelSearching hotelSearch;
     
     @Logger 
     private Log log;
     
     @Begin
     public String selectHotel()
     {
        hotel = em.merge( hotelSearch.getSelectedHotel() );
        return "hotel";
     }
     
     public String bookHotel()
     {      
        booking = new Booking(hotel, user);
        Calendar calendar = Calendar.getInstance();
        booking.setCheckinDate( calendar.getTime() );
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        booking.setCheckoutDate( calendar.getTime() );
        
        return "book";
     }
  
     public String setBookingDetails()
     {
        if (booking==null || hotel==null) return "main";
        if ( !booking.getCheckinDate().before( booking.getCheckoutDate() ) )
        {
           facesMessages.add("Check out date must be later than check in date");
           return null;
        }
        else
        {
           return "confirm";
        }
     }
  
     @End
     public String confirm()
     {
        if (booking==null || hotel==null) return "main";
        em.persist(booking);
        facesMessages.add("Thank you, #{user.name}, your confimation number for #{hotel.name} is #{booking.id}");
        log.info("New booking: #{booking.id} for #{user.username}");
        events.raiseEvent("bookingConfirmed");
        return "confirmed";
     }
     
     @End
     public String cancel()
     {
        return "main";
     }
     
     @Destroy @Remove
     public void destroy() {}
  
  }</code>
  
      <p>
         The conversation begins when the <code>@Begin</code> annotated
         <code>selectHotel()</code> is called, and ends when 
         the <code>@End</code> annotated 
         <code>confirm()</code> or <code>cancel()</code> is called. Between the
         <code>@Begin</code> and <code>@End</code> methods, the user can do
         any number of things with the application (i.e., invoke any 
         event handler method or use the BACK button etc.) and the 
         <code>hotelBooking</code> maintains its state throughout the process.
         When the <code>@End</code> method is called, Seam destroys this
         component and avoids any memory leak.
      </p>
      
      <p>
        However, none of the <code>HotelBookingAction</code> bean methods 
        may be called outside of a long-running conversation. 
        So if we try to use the 
        back button after the end of the conversation, Seam will redirect to the main page, with an 
        error message.
     </p>
  
  
         <form>
            <input type="button" value="Close Window" onclick="window.close()"/>
         </form>
  
    </div>
  </div>
  
  </body>
  </html>
  
  
  



More information about the jboss-cvs-commits mailing list