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

Norman Richards norman.richards at jboss.com
Mon Jul 16 11:35:22 EDT 2007


  User: nrichards
  Date: 07/07/16 11:35:22

  Added:       examples/hibernate2/view/exp        bookingExp.html
                        confirmExp.html introExp.html loginExp.html
                        mainExp.html registerExp.html workspaceExp.html
  Log:
  JBSEAM-1652
  
  Revision  Changes    Path
  1.2       +156 -0    jboss-seam/examples/hibernate2/view/exp/bookingExp.html
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: bookingExp.html
  ===================================================================
  RCS file: bookingExp.html
  diff -N bookingExp.html
  --- /dev/null	1 Jan 1970 00:00:00 -0000
  +++ bookingExp.html	16 Jul 2007 15:35:22 -0000	1.2
  @@ -0,0 +1,156 @@
  +<!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">
  + at Stateful
  + at Name("hotelBooking")
  + at 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>
  
  
  
  1.2       +105 -0    jboss-seam/examples/hibernate2/view/exp/confirmExp.html
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: confirmExp.html
  ===================================================================
  RCS file: confirmExp.html
  diff -N confirmExp.html
  --- /dev/null	1 Jan 1970 00:00:00 -0000
  +++ confirmExp.html	16 Jul 2007 15:35:22 -0000	1.2
  @@ -0,0 +1,105 @@
  +<!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>
  \ No newline at end of file
  
  
  
  1.2       +73 -0     jboss-seam/examples/hibernate2/view/exp/introExp.html
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: introExp.html
  ===================================================================
  RCS file: introExp.html
  diff -N introExp.html
  --- /dev/null	1 Jan 1970 00:00:00 -0000
  +++ introExp.html	16 Jul 2007 15:35:22 -0000	1.2
  @@ -0,0 +1,73 @@
  +<!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.2       +164 -0    jboss-seam/examples/hibernate2/view/exp/loginExp.html
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: loginExp.html
  ===================================================================
  RCS file: loginExp.html
  diff -N loginExp.html
  --- /dev/null	1 Jan 1970 00:00:00 -0000
  +++ loginExp.html	16 Jul 2007 15:35:22 -0000	1.2
  @@ -0,0 +1,164 @@
  +<!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>#{identity.username}</code> refers to a property of the
  +       <code>Identity</code> component and <code>#{identity.login}</code> 
  +       refers to a method of the <code>Identity</code> component.
  +    </p>
  +
  +<code class="block">
  +&lt;div&gt;
  +    &lt;h:outputLabel for="username">Login Name&lt;/h:outputLabel>
  +    &lt;h:inputText id="username" value="#{identity.username}" />
  +&lt;/div&gt;
  +&lt;div&gt;
  +    &lt;h:outputLabel for="password">Password&lt;/h:outputLabel>
  +    &lt;h:inputSecret id="password" value="#{identity.password}" />
  +&lt;/div&gt;
  +
  +... ...
  +
  +&lt;div class="buttonBox"&gt;
  +    &lt;h:commandButton action="#{identity.login}" 
  +                     value="Account Login" class="button" /&gt;
  +&lt;/div&gt;
  +</code>
  +
  +    <p>
  +       After logging in, 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">
  + at Entity
  + at Name("user")
  + at 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>
  +       Seam comes with its own Security framework, based on JAAS.  It allows you 
  +       to perform user authentication by configuring your own authentication method
  +       in <code>components.xml</code>.
  +    </p>
  +    
  +<code class="block">
  +  &lt;security:identity authenticate-method="#{authenticator.authenticate}"/&gt;
  +</code>
  +
  +    <p>
  +       <code>AuthenticatorAction</code> is an EJB 3.0 session bean mapped 
  +       to the Seam context variable named <code>authenticator</code>. When 
  +       the login button is clicked, the JSF method binding 
  +       <code>#{identity.login}</code> is evaluated, and based upon the previous configuration, the 
  +       <code>authenticate()</code> method is invoked upon <code>AuthenticatorAction</code>.
  +    </p>
  +
  +<code class="block">
  + at Stateful
  + at Scope(EVENT)
  + at Name("authenticator")
  +public class AuthenticatorAction implements Authenticator
  +{
  +   @In Identity identity;
  +   
  +   @PersistenceContext EntityManager em;
  +   
  +   @Out(required=false, scope = SESSION)
  +   private User user;
  +   
  +   public boolean authenticate()
  +   {
  +      List results = em.createQuery(
  +            "select u from User u where u.username=:username " +
  +              "and u.password=:password")
  +            .setParameter("username", identity.getUsername())
  +            .setParameter("password", identity.getPassword())
  +            .getResultList();
  +      
  +      if ( results.size()==0 )
  +      {
  +         return false;
  +      }
  +      else
  +      {
  +         user = (User) results.get(0);
  +         return true;
  +      }
  +   }
  +   
  +   @Remove @Destroy
  +   public void destroy() {}
  +}
  +</code>
  +
  +    <p>
  +       The <code>@In</code> annotation tells Seam to inject an <code>Identity</code> 
  +       (a built-in Seam component that provides security functionality)
  +       when any method of <code>AuthenticatorAction</code> is invoked. The <code>@Out</code> 
  +       annotation indicates the <code>AuthenticatorAction</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.2       +196 -0    jboss-seam/examples/hibernate2/view/exp/mainExp.html
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: mainExp.html
  ===================================================================
  RCS file: mainExp.html
  diff -N mainExp.html
  --- /dev/null	1 Jan 1970 00:00:00 -0000
  +++ mainExp.html	16 Jul 2007 15:35:22 -0000	1.2
  @@ -0,0 +1,196 @@
  +<!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">
  + at Stateful
  + at Name("hotelSearch")
  + at Scope(ScopeType.SESSION)
  + at 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">
  + at Stateful
  + at Name("hotelBooking")
  + at 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.2       +228 -0    jboss-seam/examples/hibernate2/view/exp/registerExp.html
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: registerExp.html
  ===================================================================
  RCS file: registerExp.html
  diff -N registerExp.html
  --- /dev/null	1 Jan 1970 00:00:00 -0000
  +++ registerExp.html	16 Jul 2007 15:35:22 -0000	1.2
  @@ -0,0 +1,228 @@
  +<!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">
  + at Entity
  + at Name("user")
  + at 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">
  + at Stateful
  + at Scope(EVENT)
  + at 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.2       +80 -0     jboss-seam/examples/hibernate2/view/exp/workspaceExp.html
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: workspaceExp.html
  ===================================================================
  RCS file: workspaceExp.html
  diff -N workspaceExp.html
  --- /dev/null	1 Jan 1970 00:00:00 -0000
  +++ workspaceExp.html	16 Jul 2007 15:35:22 -0000	1.2
  @@ -0,0 +1,80 @@
  +<!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>
  
  
  



More information about the jboss-cvs-commits mailing list