[seam-commits] Seam SVN: r10729 - in examples/trunk/booking: ejb-jar and 7 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Apr 30 03:48:46 EDT 2009


Author: dan.j.allen
Date: 2009-04-30 03:48:46 -0400 (Thu, 30 Apr 2009)
New Revision: 10729

Added:
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducer.java
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducerBean.java
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManager.java
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManagerBean.java
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/Registrar.java
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/RegistrarBean.java
   examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/account.xhtml
   examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/user.xhtml
   examples/trunk/booking/war/src/main/webapp/account.xhtml
   examples/trunk/booking/war/src/main/webapp/password.xhtml
   examples/trunk/booking/war/src/main/webapp/register.xhtml
Modified:
   examples/trunk/booking/ejb-jar/pom.xml
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/model/User.java
   examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/BookingAgentBean.java
   examples/trunk/booking/pom.xml
   examples/trunk/booking/war/src/main/webapp/WEB-INF/faces-config.xml
   examples/trunk/booking/war/src/main/webapp/WEB-INF/layout/template.xhtml
   examples/trunk/booking/war/src/main/webapp/book.xhtml
   examples/trunk/booking/war/src/main/webapp/confirm.xhtml
   examples/trunk/booking/war/src/main/webapp/css/screen.css
   examples/trunk/booking/war/src/main/webapp/home.xhtml
Log:
add registration, account page, and change password
clean up some styles


Modified: examples/trunk/booking/ejb-jar/pom.xml
===================================================================
--- examples/trunk/booking/ejb-jar/pom.xml	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/ejb-jar/pom.xml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -77,6 +77,12 @@
       </dependency>
 
       <dependency>
+         <groupId>javax.faces</groupId>
+         <artifactId>jsf-api</artifactId>
+         <scope>provided</scope>
+      </dependency>
+
+      <dependency>
          <groupId>javax.persistence</groupId>
          <artifactId>persistence-api</artifactId>
          <scope>provided</scope>

Modified: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/model/User.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/model/User.java	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/model/User.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -85,7 +85,8 @@
    }
 
    @Id
-   @Size(min = 4, max = 15)
+   @NotNull
+   @Size(min = 3, max = 15)
    @Pattern(regexp = "^\\w*$", message = "not a valid username")
    public String getUsername()
    {

Added: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducer.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducer.java	                        (rev 0)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducer.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,17 @@
+package org.jboss.seam.examples.booking.session;
+
+import javax.ejb.Local;
+import org.jboss.seam.examples.booking.model.User;
+
+/**
+ * The <strong>AccountProducer</strong> produces the object that
+ * represents the current user's account information. The account
+ * information is represented by the {@link User} entity.
+ *
+ * @author Dan Allen
+ */
+public
+ at Local
+interface AccountProducer {
+   User getCurrentAccount();
+}

Added: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducerBean.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducerBean.java	                        (rev 0)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/AccountProducerBean.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,31 @@
+package org.jboss.seam.examples.booking.session;
+
+import javax.annotation.Named;
+import javax.context.SessionScoped;
+import javax.ejb.Stateless;
+import javax.inject.Produces;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import org.jboss.seam.examples.booking.Registered;
+import org.jboss.seam.examples.booking.model.User;
+
+/**
+ * @author Dan Allen
+ */
+public
+ at Stateless
+class AccountProducerBean implements AccountProducer
+{
+   private @PersistenceContext EntityManager em;
+
+   public
+   @Produces
+//   @Registered // FIXME not resolving"user" variable if binding type is present
+   @Named("user")
+   @SessionScoped
+   User getCurrentAccount()
+   {
+      // FIXME provide a real implementation
+      return em.find(User.class, "dan");
+   }
+}

Modified: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/BookingAgentBean.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/BookingAgentBean.java	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/BookingAgentBean.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -41,6 +41,7 @@
 import org.jboss.seam.international.StatusMessages;
 import org.jboss.webbeans.log.Log;
 import org.jboss.webbeans.log.Logger;
+import ui.BookingFormControls;
 
 public
 @Named("bookingAgent")
@@ -56,6 +57,8 @@
 
    @Current StatusMessages statusMessages;
 
+   @Current BookingFormControls formControls;
+
    private Hotel hotelSelection;
 
    private Booking booking;
@@ -89,12 +92,12 @@
       calendar.add(Calendar.DAY_OF_MONTH, -1);
       if (booking.getCheckinDate().before(calendar.getTime()))
       {
-         statusMessages.addToControl("booking:checkinDate:input", "Check in date must be a future date");
+         statusMessages.addToControl(formControls.getCheckinDateControlId(), "Check in date must be a future date");
          bookingValid = false;
       }
       else if (!booking.getCheckinDate().before(booking.getCheckoutDate()))
       {
-         statusMessages.addToControl("booking:checkoutDate:input", "Check out date must be after check in date");
+         statusMessages.addToControl(formControls.getCheckoutDateControlId(), "Check out date must be after check in date");
          bookingValid = false;
       }
       else

Added: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManager.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManager.java	                        (rev 0)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManager.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,17 @@
+package org.jboss.seam.examples.booking.session;
+
+import javax.ejb.Local;
+
+/**
+ *
+ * @author Dan Allen
+ */
+public
+ at Local
+interface PasswordManager {
+   void changePassword();
+   boolean isChanged();
+   void setConfirmPassword(String password);
+   String getConfirmPassword();
+   void destroy();
+}

Added: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManagerBean.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManagerBean.java	                        (rev 0)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/PasswordManagerBean.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,71 @@
+package org.jboss.seam.examples.booking.session;
+
+import javax.annotation.PreDestroy;
+import javax.context.RequestScoped;
+import javax.ejb.Stateful;
+import javax.inject.Current;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import org.jboss.seam.examples.booking.Registered;
+import org.jboss.seam.examples.booking.model.User;
+import org.jboss.seam.international.StatusMessages;
+import ui.RegistrationFormControls;
+
+/**
+ *
+ * @author Dan Allen
+ */
+public
+ at Stateful
+ at RequestScoped
+class PasswordManagerBean implements PasswordManager
+{
+   private @PersistenceContext EntityManager em;
+
+   private @Current StatusMessages statusMessages;
+
+   private @Current RegistrationFormControls formControls;
+
+   private @Registered User user;
+
+   private String confirmPassword;
+
+   private boolean changed;
+
+   public void changePassword()
+   {
+      if (user.getPassword().equals(confirmPassword))
+      {
+         user = em.merge(user);
+         statusMessages.add("Password successfully updated.");
+         changed = true;
+      }
+      else
+      {
+         // FIME reverting isn't going to work here
+         //revertUser();
+         confirmPassword = null;
+         statusMessages.addToControl(formControls.getConfirmPasswordControlId(), "Passwords do not match. Please re-type the new password.");
+      }
+   }
+
+   public boolean isChanged()
+   {
+      return changed;
+   }
+
+   public void setConfirmPassword(String password)
+   {
+      this.confirmPassword = password;
+   }
+
+   public String getConfirmPassword()
+   {
+      return this.confirmPassword;
+   }
+
+   @PreDestroy
+   public void destroy()
+   {
+   }
+}

Added: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/Registrar.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/Registrar.java	                        (rev 0)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/Registrar.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,32 @@
+package org.jboss.seam.examples.booking.session;
+
+import javax.ejb.Local;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.jboss.seam.examples.booking.model.User;
+
+/**
+ * @author Dan Allen
+ */
+public
+ at Local
+interface Registrar
+{
+   void register();
+
+   boolean isRegistrationInvalid();
+
+   void notifyIfRegistrationIsInvalid(boolean validationFailed);
+
+   User getNewUser();
+
+   boolean isRegistered();
+
+   @NotNull
+   @Size(min = 5, max = 15)
+   String getConfirmPassword();
+
+   void setConfirmPassword(String password);
+
+   void destroy();
+}

Added: examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/RegistrarBean.java
===================================================================
--- examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/RegistrarBean.java	                        (rev 0)
+++ examples/trunk/booking/ejb-jar/src/main/java/org/jboss/seam/examples/booking/session/RegistrarBean.java	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,129 @@
+package org.jboss.seam.examples.booking.session;
+
+import javax.annotation.Named;
+import javax.annotation.PreDestroy;
+import javax.context.RequestScoped;
+import javax.ejb.Stateful;
+import javax.inject.Current;
+import javax.inject.Produces;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import org.jboss.seam.examples.booking.model.User;
+import org.jboss.seam.international.StatusMessage;
+import org.jboss.seam.international.StatusMessages;
+import ui.RegistrationFormControls;
+
+/**
+ * @author Dan Allen
+ */
+public
+ at Named("registrar")
+ at Stateful
+ at RequestScoped
+class RegistrarBean implements Registrar
+{
+   private 
+   @PersistenceContext
+   EntityManager em;
+
+   private 
+   @Current
+   StatusMessages statusMessages;
+
+   private 
+   @Current
+   RegistrationFormControls formControls;
+
+   private User newUser;
+
+   private String confirmPassword;
+
+   private boolean registered;
+
+   private boolean registrationInvalid;
+
+   public void register()
+   {
+      if (verifyPasswordsMatch() && verifyUsernameIsAvailable())
+      {
+         em.persist(newUser);
+         registered = true;
+         statusMessages.add("You have been successfully registered as the user {0}!", newUser.getUsername());
+      }
+      else
+      {
+         registrationInvalid = true;
+      }
+   }
+
+   public boolean isRegistrationInvalid()
+   {
+      return registrationInvalid;
+   }
+
+   // TODO it would be nice to move the conditional to the UI but <f:event> doesn't support if=""
+   public void notifyIfRegistrationIsInvalid(boolean validationFailed)
+   {
+      if (validationFailed || registrationInvalid)
+      {
+         statusMessages.add(StatusMessage.Severity.WARN, "Invalid registration. Please correct the errors and try again.");
+      }
+   }
+
+   public
+   @Produces
+   @Named
+   @RequestScoped
+   User getNewUser()
+   {
+      newUser = new User();
+      return newUser;
+   }
+
+   public boolean isRegistered()
+   {
+      return registered;
+   }
+
+   public String getConfirmPassword()
+   {
+      return confirmPassword;
+   }
+
+   public void setConfirmPassword(String password)
+   {
+      this.confirmPassword = password;
+   }
+
+   /**
+    * Verify that the same password is entered twice.
+    */
+   private boolean verifyPasswordsMatch()
+   {
+      if (!newUser.getPassword().equals(confirmPassword))
+      {
+         statusMessages.addToControl(formControls.getConfirmPasswordControlId(), "Passwords do not match. Please re-type your password.");
+         confirmPassword = null;
+         return false;
+      }
+
+      return true;
+   }
+
+   private boolean verifyUsernameIsAvailable()
+   {
+      User existing = em.find(User.class, newUser.getUsername());
+      if (existing != null)
+      {
+         statusMessages.addToControl(formControls.getUsernameControlId(), "The username '{0}' is already taken. Please choose another username.", newUser.getUsername());
+         return false;
+      }
+
+      return true;
+   }
+
+   @PreDestroy
+   public void destroy()
+   {
+   }
+}

Modified: examples/trunk/booking/pom.xml
===================================================================
--- examples/trunk/booking/pom.xml	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/pom.xml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -24,6 +24,7 @@
    <build>
       <defaultGoal>package</defaultGoal>
       <pluginManagement>
+
          <plugins>
 
             <!-- version matrix or parent? -->

Modified: examples/trunk/booking/war/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/WEB-INF/faces-config.xml	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/war/src/main/webapp/WEB-INF/faces-config.xml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -9,8 +9,8 @@
 
       <navigation-case>
          <from-action>#{bookingAgent.cancel}</from-action>
+         <if>#{true}</if>
          <to-view-id>/main.xhtml</to-view-id>
-         <if>#{true}</if>
          <redirect/>
       </navigation-case>
 
@@ -23,22 +23,22 @@
       <!--
       <navigation-case>
          <from-action>#{hotelSearch.find}</from-action>
+         <if>#{true}</if>
          <to-view-id>/main.xhtml</to-view-id>
-         <if>#{true}</if>
          <redirect/>
       </navigation-case>
       <navigation-case>
          <from-action>#{hotelSearch.nextPage}</from-action>
+         <if>#{true}</if>
          <to-view-id>/main.xhtml</to-view-id>
-         <if>#{true}</if>
          <redirect/>
       </navigation-case>
       -->
 
       <navigation-case>
          <from-action>#{bookingAgent.selectHotel(_hotel)}</from-action>
+         <if>#{bookingAgent.hotelSelection != null}</if>
          <to-view-id>/hotel.xhtml</to-view-id>
-         <if>#{bookingAgent.hotelSelection != null}</if>
          <redirect/>
       </navigation-case>
 
@@ -49,8 +49,8 @@
 
       <navigation-case>
          <from-action>#{bookingAgent.bookHotel}</from-action>
+         <if>#{bookingAgent.booking != null}</if>
          <to-view-id>/book.xhtml</to-view-id>
-         <if>#{bookingAgent.booking != null}</if>
          <redirect/>
       </navigation-case>
 
@@ -61,8 +61,8 @@
 
       <navigation-case>
          <from-action>#{bookingAgent.validateBooking}</from-action>
+         <if>#{bookingAgent.bookingValid}</if>
          <to-view-id>/confirm.xhtml</to-view-id>
-         <if>#{bookingAgent.bookingValid}</if>
          <redirect/>
       </navigation-case>
 
@@ -73,11 +73,23 @@
 
       <navigation-case>
          <from-action>#{bookingAgent.confirm}</from-action>
+         <if>#{true}</if>
          <to-view-id>/main.xhtml</to-view-id>
-         <if>#{true}</if>
          <redirect/>
       </navigation-case>
 
    </navigation-rule>
 
+   <navigation-rule>
+      <from-view-id>/register.xhtml</from-view-id>
+
+      <navigation-case>
+         <from-action>#{registrar.register}</from-action>
+         <if>#{registrar.registered}</if>
+         <to-view-id>/account.xhtml</to-view-id>
+         <!--<redirect/> disabled until messages can be kept over redirect -->
+      </navigation-case>
+
+   </navigation-rule>
+
 </faces-config>

Added: examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/account.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/account.xhtml	                        (rev 0)
+++ examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/account.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,12 @@
+<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+   xmlns:ui="http://java.sun.com/jsf/facelets"
+   xmlns:f="http://java.sun.com/jsf/core"
+   xmlns:h="http://java.sun.com/jsf/html"
+   xmlns:p="http://http://java.sun.com/jsf/composite/property">
+    
+   <p:display label="Username" value="#{user.username}"/>
+   <p:display label="Real name" value="#{user.name}"/>
+
+</ui:composition>

Added: examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/user.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/user.xhtml	                        (rev 0)
+++ examples/trunk/booking/war/src/main/webapp/WEB-INF/fragments/user.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,21 @@
+<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+   xmlns:ui="http://java.sun.com/jsf/facelets"
+   xmlns:f="http://java.sun.com/jsf/core"
+   xmlns:h="http://java.sun.com/jsf/html"
+   xmlns:p="http://http://java.sun.com/jsf/composite/property">
+    
+   <p:display label="Name" value="#{hotel.name}"/>
+   <p:display label="Address" value="#{hotel.address}"/>
+   <p:display label="City" value="#{hotel.city}"/>
+   <p:display label="State" value="#{hotel.state}"/>
+   <p:display label="Zip" value="#{hotel.zip}"/>
+   <p:display label="Country" value="#{hotel.country}"/>
+   <p:display label="Nightly rate" override="true">
+      <h:outputText value="#{hotel.price}">
+         <f:convertNumber type="currency" currencySymbol="$"/>
+      </h:outputText>
+   </p:display>
+
+</ui:composition>

Modified: examples/trunk/booking/war/src/main/webapp/WEB-INF/layout/template.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/WEB-INF/layout/template.xhtml	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/war/src/main/webapp/WEB-INF/layout/template.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -4,6 +4,9 @@
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"><ui:remove><!-- Using <f:view> as the root prevents conversation from propagating correctly--></ui:remove>
+   <f:facet name="metadata">
+      <ui:insert name="pageMetadata"/>
+   </f:facet>
    <h:head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
       <title>JBoss Suites: Seam Framework</title>
@@ -11,7 +14,7 @@
       <link href="#{request.contextPath}/css/screen.css" rel="stylesheet" type="text/css"/>
       <ui:insert name="head"/>
    </h:head>
-   <h:body>
+   <h:body styleClass="#{empty pageClass ? 'page' : 'home'}">
       <div id="document">
          <div id="header">
             <div id="title"><h:graphicImage value="/img/hdr.title.gif" alt="JBoss Suites: seam framework demo"/></div>

Added: examples/trunk/booking/war/src/main/webapp/account.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/account.xhtml	                        (rev 0)
+++ examples/trunk/booking/war/src/main/webapp/account.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,49 @@
+<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+   xmlns:ui="http://java.sun.com/jsf/facelets"
+   xmlns:f="http://java.sun.com/jsf/core"
+   xmlns:h="http://java.sun.com/jsf/html"
+   template="/WEB-INF/layout/template.xhtml">
+
+   <ui:define name="content">
+
+      <div class="section">
+         <h1>Your Account</h1>
+      </div>
+      
+      <div class="section">
+
+         <div class="errors">
+            <h:messages id="messages" globalOnly="true"/>
+         </div>
+
+         <ui:include src="/WEB-INF/fragments/account.xhtml"/>
+
+         <div class="buttonBox">
+            <h:button id="changePassword" value="Change password" outcome="/password.xhtml"/>
+         </div>
+      </div>
+
+   </ui:define>
+   
+   <ui:define name="sidebar">          
+
+      <h1>Producing variables</h1>
+      <p>
+         You shouldn't need to write accessor methods (getters and setters) on a backing bean just to get at your data.
+         Rather, you should be able to expose data as a top-level variable. The logic necessary to load the data should
+         be produced on demand. That's the role of a @Producer method on a bean, which you can leverage in a Seam
+         application. Here, the user's account is loaded into the session as the variable 'user' when this page is
+         accessed. Once the variable has been produced, it doesn't need to happen again, another cycle-saving benefit of
+         this pattern.
+      </p>
+      <p>
+         <a href="#" onclick="window.open('exp/FIXME.html','exp','width=752,height=500,scrollbars=yes');">
+            What happens when this page loads?
+         </a>
+      </p>
+      
+   </ui:define>
+
+</ui:composition>

Modified: examples/trunk/booking/war/src/main/webapp/book.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/book.xhtml	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/war/src/main/webapp/book.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -13,7 +13,7 @@
       </div>
 
       <div class="section">
-         <div class="entry errors">
+         <div class="errors">
             <h:messages id="messages" globalOnly="true"/>
          </div>
       
@@ -21,17 +21,17 @@
          
          <div style="clear: both;"/>
       
-         <h:form id="booking">
+         <h:form id="bookingForm">
             <fieldset>
                   
                <p:edit id="checkinDate" label="Check-in date">
-                  <h:inputText id="input" value="#{booking.checkinDate}">
+                  <h:inputText id="input" value="#{booking.checkinDate}" binding="#{bookingFormControls.checkinDate}">
                      <f:convertDateTime type="date" pattern="MM/dd/yyyy"/>
                   </h:inputText>
                </p:edit>
 
                <p:edit id="checkoutDate" label="Check-out date">
-                  <h:inputText id="input" value="#{booking.checkoutDate}">
+                  <h:inputText id="input" value="#{booking.checkoutDate}" binding="#{bookingFormControls.checkoutDate}">
                      <f:convertDateTime type="date" pattern="MM/dd/yyyy"/>
                   </h:inputText>
                </p:edit>
@@ -99,15 +99,15 @@
 
       <h1>Workspace management</h1>
       <p>
-         As you can see, Seam makes it easy to work in multiple windows or
-         multiple browser tabs. But you can even switch between multiple tasks
-         inside a single browser tab!  The "Workspaces" section showcases this
-         advanced feature.
+         As you can see, Seam makes it easy to work in multiple windows or multiple browser tabs. But you can even
+         switch between multiple tasks inside a single browser tab!  The "Workspaces" section showcases this advanced
+         feature.
       </p>
       <p>
          <a href="#" onclick="window.open('exp/workspaceExp.html','exp','width=752,height=500,scrollbars=yes');">
             How does the workspace list work?
          </a>
+
       </p>
 
    </ui:define>

Modified: examples/trunk/booking/war/src/main/webapp/confirm.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/confirm.xhtml	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/war/src/main/webapp/confirm.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -28,7 +28,7 @@
          <p:display label="Credit card #" value="#{booking.creditCard}"/>
    
          <div class="buttonBox">
-            <h:form id="confirm">
+            <h:form id="confirmForm">
                <h:commandButton id="confirm" value="Confirm" action="#{bookingAgent.confirm}"/>
                #{' '}
                <h:button id="revise" value="Revise" outcome="/book.xhtml">

Modified: examples/trunk/booking/war/src/main/webapp/css/screen.css
===================================================================
--- examples/trunk/booking/war/src/main/webapp/css/screen.css	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/war/src/main/webapp/css/screen.css	2009-04-30 07:48:46 UTC (rev 10729)
@@ -33,13 +33,13 @@
    border: 1px solid #C3BBB6;
    padding: 4px;
    margin: 5px 0;
-   background: #fff url(../img/input.bg.gif) 0 0 repeat-x;
+   background: #FFFFFF url(../img/input.bg.gif) 0 0 repeat-x;
 }
 select {
    border: 1px solid #C3BBB6;
-   padding: 4px;
+   padding: 1px;
    margin: 5px 0;
-   background: #fff url(../img/input.bg.gif) 0 0 repeat-x;
+   background: #FFFFFF url(../img/input.bg.gif) 0 0 repeat-x;
 }
 ol, ul {
    margin: 10px 0px 10px 6px;
@@ -54,7 +54,7 @@
 ----------------------------------------------- */
 #document {
    padding: 0 1px;
-   background: #fff url(../img/bg.gif) 0 0 repeat-y;
+   background: #FFFFFF url(../img/bg.gif) 0 0 repeat-y;
    float: left;
    border-bottom: 1px solid #C3BBB6;
 }
@@ -81,7 +81,7 @@
    width: 548px;
    margin-top: 75px;
    padding-top: 5px;
-   background: #fff url(../img/cnt.bg.gif) 0 0 repeat-x;
+   background: #FFFFFF url(../img/cnt.bg.gif) 0 0 repeat-x;
 }
 #footer {
    clear: both;
@@ -89,19 +89,20 @@
    float: left;
    padding: 20px;
    border-top: 1px solid #C3BBB6;
-   background-color: #fff;
+   background-color: #FFFFFF;
    width: 718px;
    text-align: right;
 }
 /* General
 ----------------------------------------------- */
-input[type="submit"], input[type="button"] {
+input[type=submit], input[type=button] {
    font-weight: bold;
-   color: #fff;
+   color: #FFFFFF;
    border: 1px solid #5D1414;
    height: 26px;
-   background: #fff url(../img/btn.bg.gif) 0 0 repeat-x;
+   background: #FFFFFF url(../img/btn.bg.gif) 0 0 repeat-x;
    border-style: none;
+	cursor: pointer;
 }
 .center {
    text-align: center;
@@ -117,6 +118,9 @@
    width: 160px;
    text-align: right;
 }
+.entry input {
+   margin: 0;
+}
 .entry .input, .entry .output, .entry .error {
    float: right;
    width: 350px;
@@ -135,8 +139,8 @@
 .errors {
    font-size: small;
    font-weight: bold;
-   text-align: center;
-   color: #600;
+   /*text-align: center;*/
+   color: #600000;
 }
 .errors div {
    text-align: left;
@@ -145,11 +149,18 @@
    text-align: left;
 }
 .errors input {
-   border: 1px solid #600;
+   border: 1px solid #600000;
 }
 .errors ul {
    list-style: none;
 }
+#messages {
+   margin-left: 1px;
+   margin-bottom: 20px;
+}
+#messages li {
+   margin-left: 0;
+}
 .buttonBox {
    text-align: center;
    padding: 5px 0;
@@ -205,7 +216,7 @@
 }
 #content table thead th {
    border-left: 1px solid #D2C9C4;
-   background: #fff url(../img/th.bg.gif) 0 100% repeat-x;   
+   background: #FFFFFF url(../img/th.bg.gif) 0 100% repeat-x;   
    border-bottom: 1px solid #D2C9C4;
    padding: 6px;
    text-align: left;
@@ -260,12 +271,17 @@
 }
 /* Homepage Modifications
 ----------------------------------------------- */
-#pgHome #container {
+body.home #container {
    background: url(../img/hdr.ad.jpg) 0 0 repeat-x;
 }
-#pgHome #sidebar {
+body.home #sidebar {
    margin-top: 207px;
 }
-#pgHome #content {
+body.home #content {
    margin-top: 183px;
 }
+/* Extras
+----------------------------------------------- */
+#javax_faces_developmentstage_messages {
+   display: none;
+}

Modified: examples/trunk/booking/war/src/main/webapp/home.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/home.xhtml	2009-04-29 23:56:18 UTC (rev 10728)
+++ examples/trunk/booking/war/src/main/webapp/home.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -1,87 +1,73 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
+   xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
-   xmlns:f="http://java.sun.com/jsf/core">
-   <head>
-      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
-      <title>JBoss Suites: Seam Framework</title>
-      <link rel="shortcut icon" href="#{request.contextPath}/favicon.ico"/>
-      <link href="#{request.contextPath}/css/screen.css" rel="stylesheet" type="text/css"/>
-   </head>
-   <body id="pgHome">
-      <f:view>
-         <div id="document">
-            <div id="header">
-               <div id="title"><h:graphicImage value="/img/hdr.title.gif" alt="JBoss Suites: seam framework demo"/></div>
+   template="/WEB-INF/layout/template.xhtml">
+
+   <ui:param name="pageClass" value="home"/>
+
+   <ui:define name="content">
+      <div class="section">
+
+         <h1>About this example application</h1>
+
+         <p>
+            This sample application demonstrates how easy it is to develop stateful web applications using JBoss Seam.
+            Just register, login, and book a room to see Seam in action. Throughout the application you'll see popup
+            links like the ones at the bottom of this page. Click them to see how the application works under the hood.
+         </p>
+
+         <p>
+            Note: Please do NOT enter personal information or your credit card number in this sample application.
+         </p>
+
+         <p>
+            <a href="#" onclick="window.open('exp/introExp.html','exp','width=752,height=500,scrollbars=yes');">
+               What is Seam?
+            </a>
+         </p>
+
+         <p>
+            <a href="#" onclick="window.open('exp/loginExp.html','exp','width=752,height=500,scrollbars=yes');">
+               What happens when I login?
+            </a>
+         </p>
+
+      </div>
+   </ui:define>
+
+   <ui:define name="sidebar">
+      <h:form id="login">
+         <fieldset>
+            <ui:remove>
+            <div>
+               <h:outputLabel id="UsernameLabel" for="username">Login Name</h:outputLabel>
+               <h:inputText id="username" value="#{identity.username}" style="width: 175px;"/>
+               <div class="errors"><h:message id="UsernameMessage" for="username"/></div>
             </div>
-            <div id="container">
-               <div id="sidebar">
-                  <h:link id="search" outcome="/main.xhtml" value="Search"/>
-                  <ui:remove>
-                  <h:form id="login">
-                  <fieldset>
-                     <div>
-                        <h:outputLabel id="UsernameLabel" for="username">Login Name</h:outputLabel>
-                        <h:inputText id="username" value="#{identity.username}" style="width: 175px;"/>
-                        <div class="errors"><h:message id="UsernameMessage" for="username"/></div>
-                     </div>
-                     <div>
-                        <h:outputLabel id="PasswordLabel" for="password">Password</h:outputLabel>
-                        <h:inputSecret id="password" value="#{identity.password}" style="width: 175px;"/>
-                     </div>
-                     <div class="errors"><h:messages id="messages" globalOnly="true"/></div>
-                     <div class="buttonBox"><h:commandButton id="login" action="#{identity.login}" value="Account Login"/></div>
-                     <div class="notes"><!--<h:link id="register" outcome="/register.xhtml" value="Register New User"/>--></div>
-                         <div class="subnotes">
-                             Or use a demo account:
-                             <ul>
-                                 <li>gavin/mexico</li>
-                                 <li>pete/edinburgh</li>
-                                 <li>shane/brisbane</li>
-                                 <li>dan/maryland</li>
-                             </ul>
-                         </div>
-                  </fieldset>
-                  </h:form>
-                  </ui:remove>
-               </div>
-               <div id="content">
-                  <div class="section">
-                     
-                      <h1>About this example application</h1>
-                      
-                      <p>
-                         This sample application demonstrates how easy it is to develop stateful web 
-                         applications using JBoss Seam. Just register, login, and book a room to see 
-                         Seam in action. Throughout the application you'll see popup links like 
-                         the ones at the bottom of this page. Click them to see how the application 
-                         works under the hood.
-                      </p>
-                      
-                      <p>
-                         Note: Please do NOT enter personal information or your credit card number in 
-                         this sample application.
-                      </p>
-                      
-                      <p>
-                         <a href="#" onclick="window.open('exp/introExp.html','exp','width=752,height=500,scrollbars=yes');">
-                            What is JBoss Seam?
-                         </a>
-                      </p>
-                      
-                      <p>
-                         <a href="#" onclick="window.open('exp/loginExp.html','exp','width=752,height=500,scrollbars=yes');">
-                            What happens when I login?
-                         </a>
-                      </p>
-                                 
-                  </div>
-               </div>
+            <div>
+               <h:outputLabel id="PasswordLabel" for="password">Password</h:outputLabel>
+               <h:inputSecret id="password" value="#{identity.password}" style="width: 175px;"/>
             </div>
-            <div id="footer">Created with Seam 3.0, Web Beans, EJB 3.0 and JSF 2.0</div>
-         </div>
-      </f:view>
-   </body>
-</html>
+            <div class="errors"><h:messages id="messages" globalOnly="true"/></div>
+            <div class="buttonBox"><h:commandButton id="login" action="#{identity.login}" value="Account Login"/></div>
+            </ui:remove>
+            <div class="notes"><h:link id="register" outcome="/register.xhtml" value="Register New User"/></div>
+            <ui:remove>
+            <div class="subnotes">
+               Or use a demo account:
+               <ul>
+                  <li>gavin/mexico</li>
+                  <li>pete/edinburgh</li>
+                  <li>shane/brisbane</li>
+                  <li>dan/maryland</li>
+               </ul>
+            </div>
+            </ui:remove>
+         </fieldset>
+      </h:form>
+   </ui:define>
+
+</ui:composition>

Added: examples/trunk/booking/war/src/main/webapp/password.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/password.xhtml	                        (rev 0)
+++ examples/trunk/booking/war/src/main/webapp/password.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,62 @@
+<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+   xmlns:ui="http://java.sun.com/jsf/facelets"
+   xmlns:f="http://java.sun.com/jsf/core"
+   xmlns:h="http://java.sun.com/jsf/html"
+   xmlns:p="http://http://java.sun.com/jsf/composite/property"
+   template="/WEB-INF/layout/template.xhtml">
+
+   <ui:define name="content">
+
+      <div class="section">
+         <h1>Change Your Password</h1>
+      </div>
+      
+      <div class="section">
+      
+         <div class="errors">
+            <h:messages id="messages" globalOnly="true"/>
+         </div>
+               
+         <h:form id="changePasswordForm">
+         
+            <fieldset>
+            
+               <p:edit id="password" label="Password">
+                  <h:inputSecret id="password" value="#{user.password}" redisplay="true"/>
+               </p:edit>
+
+               <p:edit id="confirmPassword" label="Confirm password">
+                  <h:inputSecret id="password" value="#{passwordManager.confirmPassword}" redisplay="true"
+                     binding="#{registrationFormControls.confirmPassword}"/>
+               </p:edit>
+
+               <div class="buttonBox">
+                  <h:commandButton id="change" value="Change" action="#{passwordManager.changePassword}"/>
+                  #{' '}
+                  <h:button id="cancel" value="Cancel" outcome="/main.xhtml"/>
+               </div>
+               
+            </fieldset>
+            
+         </h:form>
+      </div>
+
+</ui:define>
+
+   <ui:define name="sidebar">
+
+      <h1>Simple things should be easy</h1>
+      <p>
+         (And so should some complex things.) You shouldn't have to write four different classes just to change a
+         password. Traditional J2EE architectures require that developers spend more time writing code to make the
+         frameworks happy, than they ever get to spend writing code to make the user happy. Seam lets you reduce the
+         size of your code dramatically.  And that reduces bugs. And it makes refactoring easier. And it makes
+         delivering new functionality quicker. Productivity matters. But with Seam, JSF, EJB 3.0 and jBPM, you don't
+         need to sacrifice the ability to handle complex problems just to achieve great productivity.
+      </p>
+
+   </ui:define>
+
+</ui:composition>

Added: examples/trunk/booking/war/src/main/webapp/register.xhtml
===================================================================
--- examples/trunk/booking/war/src/main/webapp/register.xhtml	                        (rev 0)
+++ examples/trunk/booking/war/src/main/webapp/register.xhtml	2009-04-30 07:48:46 UTC (rev 10729)
@@ -0,0 +1,90 @@
+<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+   xmlns:ui="http://java.sun.com/jsf/facelets"
+   xmlns:f="http://java.sun.com/jsf/core"
+   xmlns:h="http://java.sun.com/jsf/html"
+   xmlns:p="http://http://java.sun.com/jsf/composite/property"
+   template="/WEB-INF/layout/template.xhtml">
+
+   <ui:param name="pageClass" value="home"/>
+
+   <ui:define name="pageMetadata">
+      <f:event type="preRenderView" listener="#{registrar.notifyIfRegistrationIsInvalid(facesContext.validationFailed)}"/>
+   </ui:define>
+
+   <ui:define name="content">
+      
+      <div class="section">
+         <h1>Register</h1>
+      </div>
+      
+      <div class="section">
+             
+         <div class="errors">
+            <h:messages id="messages" globalOnly="true"/>
+         </div>
+
+         <h:form id="registrationForm">
+
+            <fieldset>
+         
+               <p:edit id="username" label="Username">
+                  <h:inputText id="input" value="#{newUser.username}"
+                     binding="#{registrationFormControls.username}">
+                     <ui:remove><f:ajax event="blur" render="username"/></ui:remove>
+                  </h:inputText>
+               </p:edit>
+
+               <p:edit id="name" label="Real name">
+                  <h:inputText id="input" value="#{newUser.name}">
+                     <ui:remove><f:ajax event="blur" render="name"/></ui:remove>
+                  </h:inputText>
+               </p:edit>
+
+               <p:edit id="password" label="Password">
+                  <h:inputSecret id="input" value="#{newUser.password}" redisplay="true">
+                     <ui:remove><f:ajax event="blur" render="password"/></ui:remove>
+                  </h:inputSecret>
+               </p:edit>
+
+               <p:edit id="confirmPassword" label="Confirm Password">
+                  <h:inputSecret id="input" value="#{registrar.confirmPassword}" redisplay="true"
+                     binding="#{registrationFormControls.confirmPassword}">
+                     <ui:remove><f:ajax event="blur" render="confirmPassword"/></ui:remove>
+                  </h:inputSecret>
+               </p:edit>
+               
+               <div class="buttonBox">
+                  <h:commandButton id="register" value="Register" action="#{registrar.register}"/>
+                  #{' '}
+                  <h:button id="cancel" value="Cancel" outcome="/home.xhtml"/>
+               </div>
+
+            </fieldset>
+         </h:form>
+             
+      </div>
+
+   </ui:define>
+   
+   <ui:define name="sidebar">          
+
+      <h1>Integrated multi-layer validation</h1>
+      <p>
+         Robust applications need data validation in several different places. Seam integrates Hibernate Validator, a
+         set of annotations for expressing data model constraints in your domain model classes. Then, these constraints
+         are applied almost completely transparently at three levels of the application: by Seam when the user first
+         enters data, by EJB before persisting data to the database, and, if you use Hibernate to generate your database
+         schema, by the database constraints themselves. Multi-layer validation hardens your application and protects
+         your data. Even better, it's self-documenting, and easy to change when your business rules change.
+      </p>
+      <p>
+         <a href="#" onclick="window.open('exp/registerExp.html','exp','width=752,height=500,scrollbars=yes');">
+            What happens when I register?
+         </a>
+      </p>
+      
+   </ui:define>
+
+</ui:composition>




More information about the seam-commits mailing list