[seam-commits] Seam SVN: r13211 - in examples/trunk/booking-simplified: src/main/java/org/jboss/seam/examples/booking and 13 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Jun 17 05:33:30 EDT 2010


Author: dan.j.allen
Date: 2010-06-17 05:33:29 -0400 (Thu, 17 Jun 2010)
New Revision: 13211

Added:
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ChangePasswordValidator.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ConfirmPasswordValidator.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifier.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifierBean.java
Removed:
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordConfirmValidator.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingEvent.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ConfirmedLiteral.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/controls/
Modified:
   examples/trunk/booking-simplified/
   examples/trunk/booking-simplified/pom.xml
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordManagerBean.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/Registrar.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/RegistrarBean.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgent.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgentBean.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistory.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistoryBean.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationDateRangeValidator.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/bootstrap/ApplicationSetupBean.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/inventory/HotelSearchBean.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/Booking.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User_.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardExpiryYears.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardReferenceProducer.java
   examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java
   examples/trunk/booking-simplified/src/main/resources/messages.properties
   examples/trunk/booking-simplified/src/main/webapp/WEB-INF/
   examples/trunk/booking-simplified/src/main/webapp/WEB-INF/faces-config.xml
   examples/trunk/booking-simplified/src/main/webapp/WEB-INF/fragments/account.xhtml
   examples/trunk/booking-simplified/src/main/webapp/book.xhtml
   examples/trunk/booking-simplified/src/main/webapp/home.xhtml
   examples/trunk/booking-simplified/src/main/webapp/hotel.xhtml
   examples/trunk/booking-simplified/src/main/webapp/password.xhtml
   examples/trunk/booking-simplified/src/main/webapp/register.xhtml
   examples/trunk/booking-simplified/src/main/webapp/resources/components/property/input.xhtml
   examples/trunk/booking-simplified/src/test/java/org/jboss/seam/examples/booking/booking/BookingAgentTest.java
Log:
major cleanup
add email to user
use xval for registration form
fix bugs in UIInputContainer
add automatic ajax to UIInputContainer



Property changes on: examples/trunk/booking-simplified
___________________________________________________________________
Name: svn:ignore
   - .settings
.classpath
.project
faces-config.NavData
nbactions*
target

   + .settings
.classpath
.project
faces-config.NavData
nbactions*
target
.pom.xml.swp


Modified: examples/trunk/booking-simplified/pom.xml
===================================================================
--- examples/trunk/booking-simplified/pom.xml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/pom.xml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -108,7 +108,16 @@
          </exclusions>
       </dependency>
 
+      <!-- Bean Validation Implementation; provides portable constraints @NotEmpty, @Email and @Url -->
+      <!-- Hibernate Validator is the only JSR-303 implementation at the moment, so we can assume it's provided -->
       <dependency>
+         <groupId>org.hibernate</groupId>
+         <artifactId>hibernate-validator</artifactId>
+         <version>4.0.0.GA</version>
+         <scope>provided</scope>
+      </dependency>
+
+      <dependency>
          <groupId>javax.enterprise</groupId>
          <artifactId>cdi-api</artifactId>
          <scope>provided</scope>
@@ -135,12 +144,14 @@
          <scope>test</scope>
       </dependency>
 
+      <!--
       <dependency>
          <groupId>org.codehaus.groovy.maven.runtime</groupId>
          <artifactId>gmaven-runtime-1.6</artifactId>
          <version>1.0</version>
          <scope>test</scope>
       </dependency>
+      -->
 
    </dependencies>
 
@@ -153,13 +164,14 @@
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-compiler-plugin</artifactId>
             <configuration>
-               <source>1.6</source>
-               <target>1.6</target>
-               <!-- don't waste time on generation -->
+               <source>1.5</source>
+               <target>1.5</target>
+               <!-- activate only when you need to generate the metamodel -->
                <compilerArgument>-proc:none</compilerArgument>
             </configuration>
          </plugin>
 
+         <!--
          <plugin>
             <groupId>org.codehaus.groovy.maven</groupId>
             <artifactId>gmaven-plugin</artifactId>
@@ -172,6 +184,7 @@
                </execution>
             </executions>
          </plugin>
+         -->
 
          <plugin>
             <artifactId>maven-eclipse-plugin</artifactId>

Added: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ChangePasswordValidator.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ChangePasswordValidator.java	                        (rev 0)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ChangePasswordValidator.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -0,0 +1,59 @@
+package org.jboss.seam.examples.booking.account;
+
+import java.util.Map;
+import javax.enterprise.inject.Instance;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.FacesValidator;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+import javax.inject.Inject;
+import org.jboss.seam.examples.booking.Bundles;
+import org.jboss.seam.examples.booking.model.User;
+import org.jboss.seam.faces.validation.InputField;
+import org.jboss.seam.international.status.builder.BundleKey;
+import org.jboss.seam.international.status.builder.BundleTemplateMessage;
+
+/**
+ * @author Dan Allen
+ */
+ at FacesValidator(value = "changePasswordValidator")
+public class ChangePasswordValidator implements Validator
+      // extending throws an unsatisified dependency exception
+      //extends ConfirmPasswordValidator
+{
+   @Inject
+   private Instance<BundleTemplateMessage> messageBuilder;
+
+   @Inject
+   @Authenticated
+   private User currentUser;
+
+   @Inject
+   @InputField
+   private String currentPassword;
+
+   @Override
+   public void validate(FacesContext ctx, UIComponent form, Object value) throws ValidatorException
+   {
+      Map<String, UIInput> fieldMap = (Map<String, UIInput>) value;
+      if (currentUser.getPassword() != null && !currentUser.getPassword().equals(currentPassword))
+      {
+         /*
+          * This is an ugly way to put i18n in FacesMessages:
+          * https://jira.jboss.org/browse/SEAMFACES-24
+          */
+         throw new ValidatorException(
+               new FacesMessage(messageBuilder.get().text(
+                     new BundleKey(Bundles.MESSAGES, "account.passwordNotConfirmed"))
+                           .targets(fieldMap.get("oldPassword").getClientId())
+                           .build().getText()));
+      }
+
+      // TODO enable when we can extend
+      //super.validate(ctx, form, value);
+   }
+
+}

Copied: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ConfirmPasswordValidator.java (from rev 13210, examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordConfirmValidator.java)
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ConfirmPasswordValidator.java	                        (rev 0)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/ConfirmPasswordValidator.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -0,0 +1,66 @@
+/* 
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.examples.booking.account;
+
+import javax.enterprise.inject.Instance;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.FacesValidator;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+import javax.inject.Inject;
+import org.jboss.seam.examples.booking.Bundles;
+
+import org.jboss.seam.faces.validation.InputField;
+import org.jboss.seam.international.status.builder.BundleKey;
+import org.jboss.seam.international.status.builder.BundleTemplateMessage;
+
+/**
+ * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
+ */
+ at FacesValidator(value = "confirmPasswordValidator")
+public class ConfirmPasswordValidator implements Validator
+{
+   @Inject
+   private Instance<BundleTemplateMessage> messageBuilder;
+
+   @Inject
+   @InputField
+   private String newPassword;
+
+   @Inject
+   @InputField
+   private String confirmPassword;
+
+   public void validate(final FacesContext ctx, final UIComponent c, final Object value) throws ValidatorException
+   {
+      if (newPassword != null && !newPassword.equals(confirmPassword))
+      {
+         throw new ValidatorException(
+               new FacesMessage(messageBuilder.get().text(
+                     new BundleKey(Bundles.MESSAGES, "account.passwordsDoNotMatch"))
+                           .build().getText()));
+      }
+   }
+
+}

Deleted: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordConfirmValidator.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordConfirmValidator.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordConfirmValidator.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -1,83 +0,0 @@
-/* 
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.seam.examples.booking.account;
-
-import javax.faces.application.FacesMessage;
-import javax.faces.component.UIComponent;
-import javax.faces.context.FacesContext;
-import javax.faces.validator.FacesValidator;
-import javax.faces.validator.Validator;
-import javax.faces.validator.ValidatorException;
-import javax.inject.Inject;
-import org.jboss.seam.examples.booking.Bundles;
-
-import org.jboss.seam.examples.booking.model.User;
-import org.jboss.seam.faces.validation.InputField;
-import org.jboss.seam.international.status.MessageFactory;
-import org.jboss.seam.international.status.builder.BundleKey;
-
-/**
- * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
- */
- at FacesValidator(value = "passwordConfirmValidator")
-public class PasswordConfirmValidator implements Validator
-{
-   @Inject
-   @Authenticated
-   private User currentUser;
-
-   @Inject
-   private MessageFactory msg;
-
-   @Inject
-   @InputField
-   private String oldPassword;
-
-   @Inject
-   @InputField
-   private String newPassword;
-
-   @Inject
-   @InputField
-   private String confirmNewPassword;
-
-   public void validate(final FacesContext context, final UIComponent comp, final Object components) throws ValidatorException
-   {
-      if ((currentUser.getPassword() != null) && !currentUser.getPassword().equals(oldPassword))
-      {
-         /*
-          * This is an ugly way to put i18n in FacesMessages:
-          * https://jira.jboss.org/browse/SEAMFACES-24
-          */
-         throw new ValidatorException(
-               new FacesMessage(msg.info(
-                     new BundleKey(Bundles.MESSAGES, "account.passwordNotConfirmed"))
-                     .build().getText()));
-      }
-
-      if ((newPassword != null) && !newPassword.equals(confirmNewPassword))
-      {
-         throw new ValidatorException(new FacesMessage(msg.info(new BundleKey(Bundles.MESSAGES, "account.passwordsDoNotMatch")).build().getText()));
-      }
-   }
-
-}

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordManagerBean.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordManagerBean.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/PasswordManagerBean.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -58,7 +58,8 @@
    public void changePassword()
    {
       em.merge(user);
-      messages.info(new BundleKey(Bundles.MESSAGES, "account.passwordChanged")).textDefault("Password successfully updated.");
+      messages.info(new BundleKey(Bundles.MESSAGES, "account.passwordChanged"))
+            .textDefault("Password successfully updated.");
       changed = true;
    }
 

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/Registrar.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/Registrar.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/Registrar.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -22,6 +22,7 @@
 package org.jboss.seam.examples.booking.account;
 
 import javax.ejb.Local;
+import javax.faces.component.UIInput;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 import org.jboss.seam.examples.booking.model.User;
@@ -36,7 +37,7 @@
 
    boolean isRegistrationInvalid();
 
-   void notifyIfRegistrationIsInvalid(boolean validationFailed);
+   void notifyIfRegistrationIsInvalid();
 
    User getNewUser();
 
@@ -47,4 +48,8 @@
    String getConfirmPassword();
 
    void setConfirmPassword(String password);
+
+   UIInput getUsernameInput();
+
+   void setUsernameInput(UIInput input);
 }

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/RegistrarBean.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/RegistrarBean.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/account/RegistrarBean.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -24,13 +24,14 @@
 import javax.ejb.Stateful;
 import javax.enterprise.context.RequestScoped;
 import javax.enterprise.inject.Produces;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import org.jboss.seam.examples.booking.Bundles;
 
-import org.jboss.seam.examples.booking.controls.RegistrationFormControls;
 import org.jboss.seam.examples.booking.model.User;
 import org.jboss.seam.international.status.Messages;
 import org.jboss.seam.international.status.builder.BundleKey;
@@ -39,8 +40,8 @@
  * @author Dan Allen
  */
 @Stateful
+ at RequestScoped
 @Named("registrar")
- at RequestScoped
 public class RegistrarBean implements Registrar
 {
    @PersistenceContext
@@ -50,8 +51,10 @@
    private Messages messages;
 
    @Inject
-   private RegistrationFormControls formControls;
+   private FacesContext facesContext;
 
+   private UIInput usernameInput;
+
    private final User newUser = new User();
 
    private String confirmPassword;
@@ -62,11 +65,14 @@
 
    public void register()
    {
-      if (verifyPasswordsMatch() && verifyUsernameIsAvailable())
+      if (verifyUsernameIsAvailable())
       {
          registered = true;
          em.persist(newUser);
-         messages.info(new BundleKey(Bundles.MESSAGES, "registration.registered")).textDefault("You have been successfully registered as the user {0}!").textParams(newUser.getUsername());
+
+         messages.info(new BundleKey(Bundles.MESSAGES, "registration.registered"))
+               .textDefault("You have been successfully registered as the user {0}! You can now login.")
+               .textParams(newUser.getUsername());
       }
       else
       {
@@ -79,19 +85,28 @@
       return registrationInvalid;
    }
 
-   // TODO it would be nice to move the conditional to the UI but <f:event>
-   // doesn't support if=""
-   public void notifyIfRegistrationIsInvalid(final boolean validationFailed)
+   /**
+    * This method just shows another approach to adding a status message.
+    * <p>
+    * Invoked by:
+    * </p>
+    * 
+    * <pre>
+    * &lt;f:event type="preRenderView" listener="#{registrar.notifyIfRegistrationIsInvalid}"/>
+    * </pre>
+    */
+   public void notifyIfRegistrationIsInvalid()
    {
-      if (validationFailed || registrationInvalid)
+      if (facesContext.isValidationFailed() || registrationInvalid)
       {
-         messages.warn(new BundleKey(Bundles.MESSAGES, "registration.invalid")).textDefault("Invalid registration. Please correct the errors and try again.");
+         messages.warn(new BundleKey(Bundles.MESSAGES, "registration.invalid"))
+               .textDefault("Invalid registration. Please correct the errors and try again.");
       }
    }
 
-   @Named("newUser")
+   @Produces
    @RequestScoped
-   @Produces
+   @Named
    public User getNewUser()
    {
       return newUser;
@@ -112,19 +127,14 @@
       this.confirmPassword = password;
    }
 
-   /**
-    * Verify that the same password is entered twice.
-    */
-   private boolean verifyPasswordsMatch()
+   public UIInput getUsernameInput()
    {
-      if (!newUser.getPassword().equals(confirmPassword))
-      {
-         messages.warn(new BundleKey(Bundles.MESSAGES, "account.passwordsDoNotMatch")).textDefault("Passwords do not match. Please re-type your password.").targets(formControls.getConfirmPasswordControlId());
-         confirmPassword = null;
-         return false;
-      }
+      return usernameInput;
+   }
 
-      return true;
+   public void setUsernameInput(UIInput usernameInput)
+   {
+      this.usernameInput = usernameInput;
    }
 
    private boolean verifyUsernameIsAvailable()
@@ -132,10 +142,14 @@
       User existing = em.find(User.class, newUser.getUsername());
       if (existing != null)
       {
-         messages.warn(new BundleKey("messages", "account.usernameTaken")).textDefault("The username '{0}' is already taken. Please choose another username.").targets(formControls.getUsernameControlId()).textParams(newUser.getUsername());
+         messages.warn(new BundleKey("messages", "account.usernameTaken"))
+               .textDefault("The username '{0}' is already taken. Please choose another username.")
+               .targets(usernameInput.getClientId())
+               .textParams(newUser.getUsername());
          return false;
       }
 
       return true;
    }
+
 }

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgent.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgent.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgent.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -42,8 +42,10 @@
 
    void confirm();
 
-   Hotel getHotelSelection();
+   void onBookingComplete(Booking booking);
 
+   Hotel getSelectedHotel();
+
    Booking getBooking();
 
    boolean isBookingValid();

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgentBean.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgentBean.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingAgentBean.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -23,13 +23,11 @@
 
 import static javax.persistence.PersistenceContextType.EXTENDED;
 
-import java.util.Calendar;
 
 import javax.ejb.Stateful;
 import javax.enterprise.context.ConversationScoped;
 import javax.enterprise.context.RequestScoped;
 import javax.enterprise.inject.Produces;
-import javax.enterprise.inject.spi.BeanManager;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.persistence.EntityManager;
@@ -41,17 +39,21 @@
 import org.jboss.seam.examples.booking.model.User;
 import org.jboss.seam.faces.context.conversation.Begin;
 import org.jboss.seam.faces.context.conversation.End;
-import org.jboss.seam.international.status.MessageFactory;
 import org.jboss.seam.international.status.Messages;
 import org.jboss.seam.international.status.builder.BundleKey;
 import org.slf4j.Logger;
 
 import com.ocpsoft.pretty.time.PrettyTime;
+import javax.enterprise.event.Event;
+import javax.enterprise.event.Observes;
+import javax.enterprise.event.TransactionPhase;
+import javax.enterprise.inject.Instance;
 import org.jboss.seam.examples.booking.Bundles;
+import org.jboss.seam.international.status.builder.TemplateMessage;
 
- at Named("bookingAgent")
 @Stateful
 @ConversationScoped
+ at Named("bookingAgent")
 public class BookingAgentBean implements BookingAgent
 {
    @Inject
@@ -61,7 +63,7 @@
    private EntityManager em;
 
    @Inject
-   private MessageFactory msg;
+   private Instance<TemplateMessage> messageBuilder;
 
    @Inject
    private Messages messages;
@@ -70,9 +72,8 @@
    @Authenticated
    private User user;
 
-   // @Inject @Fires @Confirmed Event<BookingEvent> bookingConfirmedEvent;
-   @Inject
-   private BeanManager manager;
+   @Inject @Confirmed
+   private Event<Booking> bookingConfirmedEventSrc;
 
    private Hotel hotelSelection;
 
@@ -87,21 +88,22 @@
       hotelSelection = em.find(Hotel.class, id);
       if (hotelSelection != null)
       {
-         log.info(msg.info("Selected the {0} in {1}").textParams(hotelSelection.getName(), hotelSelection.getCity()).build().getText());
+         log.info(messageBuilder.get().text("Selected the {0} in {1}")
+               .textParams(hotelSelection.getName(), hotelSelection.getCity()).build().getText());
       }
    }
 
    public void bookHotel()
    {
-      booking = new Booking(hotelSelection, user);
-      // QUESTION push logic into Booking?
-      Calendar calendar = Calendar.getInstance();
-      calendar.add(Calendar.DAY_OF_MONTH, 1);
-      booking.setCheckinDate(calendar.getTime());
-      calendar.add(Calendar.DAY_OF_MONTH, 1);
-      booking.setCheckoutDate(calendar.getTime());
+      booking = new Booking(hotelSelection, user, 7, 2);
       hotelSelection = null;
-      messages.info(new BundleKey(Bundles.MESSAGES, "booking.initiated")).textDefault("You've initiated a booking at the {0}.").textParams(booking.getHotel().getName());
+
+      // for demo convenience
+      booking.setCreditCardNumber("1111222233334444");
+
+      messages.info(new BundleKey(Bundles.MESSAGES, "booking.initiated"))
+            .textDefault("You've initiated a booking at the {0}.")
+            .textParams(booking.getHotel().getName());
    }
 
    public void validate()
@@ -114,13 +116,7 @@
    public void confirm()
    {
       em.persist(booking);
-      // FIXME can't inject event object into bean with passivating scope
-      manager.fireEvent(new BookingEvent(booking), ConfirmedLiteral.INSTANCE);
-      log.info(msg.info("New booking at the {0} confirmed for {1}")
-            .textParams(booking.getHotel().getName(), booking.getUser().getName()).build().getText());
-      messages.info(new BundleKey(Bundles.MESSAGES, "booking.confirmed"))
-            .textDefault("You're booked to stay at the {0} {1}.")
-            .textParams(booking.getHotel().getName(), new PrettyTime().format(booking.getCheckinDate()));
+      bookingConfirmedEventSrc.fire(booking);
    }
 
    @End
@@ -130,6 +126,16 @@
       hotelSelection = null;
    }
 
+   public void onBookingComplete(@Observes(during = TransactionPhase.AFTER_SUCCESS)
+         @Confirmed final Booking booking)
+   {
+       log.info(messageBuilder.get().text("New booking at the {0} confirmed for {1}")
+            .textParams(booking.getHotel().getName(), booking.getUser().getName()).build().getText());
+       messages.info(new BundleKey(Bundles.MESSAGES, "booking.confirmed"))
+            .textDefault("You're booked to stay at the {0} {1}.")
+            .textParams(booking.getHotel().getName(), new PrettyTime().format(booking.getCheckinDate()));
+   }
+
    @Produces
    @Named
    @ConversationScoped
@@ -141,7 +147,7 @@
    @Produces
    @Named("hotel")
    @RequestScoped
-   public Hotel getHotelSelection()
+   public Hotel getSelectedHotel()
    {
       return booking != null ? booking.getHotel() : hotelSelection;
    }

Deleted: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingEvent.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingEvent.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingEvent.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -1,46 +0,0 @@
-/* 
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.seam.examples.booking.booking;
-
-import org.jboss.seam.examples.booking.model.Booking;
-
-/**
- * An event that is raised when a booking change occurs
- * (either a new booking is confirmed or an existing
- * booking is canceled).
- *
- * @author Dan Allen
- */
-public class BookingEvent
-{
-   private Booking booking;
-
-   public BookingEvent(Booking booking)
-   {
-      this.booking = booking;
-   }
-
-   public Booking getBooking()
-   {
-      return booking;
-   }
-}

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistory.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistory.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistory.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -35,5 +35,5 @@
 
    void cancelBooking(Booking booking);
 
-   void afterBookingConfirmed(BookingEvent bookingEvent);
+   void onBookingComplete(Booking booking);
 }

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistoryBean.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistoryBean.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/BookingHistoryBean.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -21,11 +21,14 @@
  */
 package org.jboss.seam.examples.booking.booking;
 
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.List;
 
 import javax.ejb.Stateful;
 import javax.enterprise.context.SessionScoped;
 import javax.enterprise.event.Observes;
+import javax.enterprise.event.Reception;
 import javax.enterprise.event.TransactionPhase;
 import javax.enterprise.inject.Instance;
 import javax.enterprise.inject.Produces;
@@ -86,14 +89,19 @@
       return bookingsForUser;
    }
 
-   public void afterBookingConfirmed(@Observes(during = TransactionPhase.AFTER_SUCCESS)
-         @Confirmed final BookingEvent bookingEvent)
+   public void onBookingComplete(@Observes(during = TransactionPhase.AFTER_SUCCESS, notifyObserver = Reception.IF_EXISTS)
+         @Confirmed final Booking booking)
    {
       // optimization, save the db call
       if (bookingsForUser != null)
       {
-         bookingsForUser.add(bookingEvent.getBooking());
+         log.info("Adding new booking to user's cached booking history");
+         bookingsForUser.add(booking);
       }
+      else
+      {
+         log.info("User's booking history not loaded. Skipping cache update.");
+      }
    }
 
    public void cancelBooking(final Booking selectedBooking)
@@ -103,11 +111,15 @@
       if (booking != null)
       {
          em.remove(booking);
-         messages.info(new BundleKey(Bundles.MESSAGES, "booking.canceled")).textDefault("The booking at the {0} on {1,date} has been canceled.").textParams(selectedBooking.getHotel().getName(), selectedBooking.getCheckinDate());
+         messages.info(new BundleKey(Bundles.MESSAGES, "booking.canceled"))
+               .textDefault("The booking at the {0} on {1} has been canceled.")
+               .textParams(selectedBooking.getHotel().getName(),
+                     DateFormat.getDateInstance(SimpleDateFormat.MEDIUM).format(selectedBooking.getCheckinDate()));
       }
       else
       {
-         messages.info(new BundleKey(Bundles.MESSAGES, "booking.doesNotExist")).textDefault("Our records indicate that the booking you selected has already been canceled.");
+         messages.info(new BundleKey(Bundles.MESSAGES, "booking.doesNotExist"))
+               .textDefault("Our records indicate that the booking you selected has already been canceled.");
       }
 
       bookingsForUser.remove(selectedBooking);

Deleted: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ConfirmedLiteral.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ConfirmedLiteral.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ConfirmedLiteral.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -1,29 +0,0 @@
-/* 
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.seam.examples.booking.booking;
-
-import javax.enterprise.util.AnnotationLiteral;
-
-public class ConfirmedLiteral extends AnnotationLiteral<Confirmed> implements Confirmed
-{
-   public static final Confirmed INSTANCE = new ConfirmedLiteral();
-}

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationDateRangeValidator.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationDateRangeValidator.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationDateRangeValidator.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -23,8 +23,11 @@
 
 import java.util.Calendar;
 import java.util.Date;
+import java.util.Map;
+import javax.enterprise.inject.Instance;
 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
 import javax.faces.context.FacesContext;
 import javax.faces.validator.FacesValidator;
 import javax.faces.validator.Validator;
@@ -32,8 +35,8 @@
 import javax.inject.Inject;
 import org.jboss.seam.examples.booking.Bundles;
 import org.jboss.seam.faces.validation.InputField;
-import org.jboss.seam.international.status.MessageFactory;
 import org.jboss.seam.international.status.builder.BundleKey;
+import org.jboss.seam.international.status.builder.BundleTemplateMessage;
 
 /**
  * A cross-field validator that validates the begin date
@@ -42,7 +45,8 @@
  * @author Dan Allen
  */
 @FacesValidator("reservationDateRangeValidator")
-public class ReservationDateRangeValidator implements Validator {
+public class ReservationDateRangeValidator implements Validator
+{
    @Inject
    @InputField
    private Date beginDate;
@@ -52,28 +56,27 @@
    private Date endDate;
 
    @Inject
-   private MessageFactory msg;
+   private Instance<BundleTemplateMessage> messageBuilder;
 
    @Override
-   public void validate(FacesContext ctx, UIComponent c, Object value) throws ValidatorException
+   public void validate(FacesContext ctx, UIComponent form, Object value) throws ValidatorException
    {
+      Map<String, UIInput> fieldMap = (Map<String, UIInput>) value;
       Calendar calendar = Calendar.getInstance();
       calendar.add(Calendar.DAY_OF_MONTH, -1);
       if (beginDate.before(calendar.getTime()))
       {
-         String message = msg.info(new BundleKey(Bundles.MESSAGES, "booking.checkInNotFutureDate"))
-               .textDefault("Check-in date must be in the future")
-               // FIXME this information should come through via injection
-               .targets("checkInDate:input")
+         String message = messageBuilder.get().text(new BundleKey(Bundles.MESSAGES, "booking.checkInNotFutureDate"))
+               // FIXME the component should come through via injection
+               .targets(fieldMap.get("beginDate").getClientId())
                .build().getText();
          throw new ValidatorException(new FacesMessage(message));
       }
       else if (!beginDate.before(endDate))
       {
-         String message = msg.info(new BundleKey(Bundles.MESSAGES, "booking.checkOutBeforeCheckIn"))
-               .textDefault("Check-out date must be after check-in date")
-               // FIXME this information should come through via injection
-               .targets("checkOutDate:input")
+         String message = messageBuilder.get().text(new BundleKey(Bundles.MESSAGES, "booking.checkOutBeforeCheckIn"))
+               // FIXME the component should come through via injection
+               .targets(fieldMap.get("endDate").getClientId())
                .build().getText();
          throw new ValidatorException(new FacesMessage(message));
       }

Added: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifier.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifier.java	                        (rev 0)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifier.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -0,0 +1,8 @@
+package org.jboss.seam.examples.booking.booking;
+
+import org.jboss.seam.examples.booking.model.Booking;
+
+public interface ReservationNotifier
+{
+   void onBookingComplete(Booking booking);
+}

Added: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifierBean.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifierBean.java	                        (rev 0)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/booking/ReservationNotifierBean.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -0,0 +1,19 @@
+package org.jboss.seam.examples.booking.booking;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.event.TransactionPhase;
+import javax.inject.Inject;
+import org.jboss.seam.examples.booking.model.Booking;
+import org.slf4j.Logger;
+
+public class ReservationNotifierBean implements ReservationNotifier
+{
+   @Inject
+   private Logger log;
+
+   public void onBookingComplete(@Observes(during = TransactionPhase.AFTER_SUCCESS)
+         @Confirmed final Booking booking)
+   {
+      log.info("In a real-world application, send e-mail containing reservation information to " + booking.getUser().getEmailWithName());
+   }
+}
\ No newline at end of file

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/bootstrap/ApplicationSetupBean.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/bootstrap/ApplicationSetupBean.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/bootstrap/ApplicationSetupBean.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -55,11 +55,11 @@
 
    public ApplicationSetupBean()
    {
-      users.add(new User("Dan Allen", "dan", "laurel"));
-      users.add(new User("Pete Muir", "pete", "edinburgh"));
-      users.add(new User("Lincoln Baxter III", "lincoln", "charlotte"));
-      users.add(new User("Shane", "shane", "brisbane"));
-      users.add(new User("Gavin King", "gavin", "mexico"));
+      users.add(new User("Dan Allen", "dan", "dan at example.com", "laurel"));
+      users.add(new User("Pete Muir", "pete", "pete at example.com", "edinburgh"));
+      users.add(new User("Lincoln Baxter III", "lincoln", "lincoln at example.com", "charlotte"));
+      users.add(new User("Shane Bryzak", "shane", "shane at example.com", "brisbane"));
+      users.add(new User("Gavin King", "gavin", "gavin at example.com", "mexico"));
 
       hotels.add(new Hotel(129, 3, "Marriott Courtyard", "Tower Place, Buckhead", "Atlanta", "GA", "30305", "USA"));
       hotels.add(new Hotel(84, 4, "Doubletree Atlanta-Buckhead", "3342 Peachtree Road NE", "Atlanta", "GA", "30326", "USA"));

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/inventory/HotelSearchBean.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/inventory/HotelSearchBean.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/inventory/HotelSearchBean.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -25,8 +25,8 @@
 import java.util.List;
 
 import javax.ejb.Stateful;
-import javax.enterprise.context.Dependent;
 import javax.enterprise.context.SessionScoped;
+import javax.enterprise.inject.Instance;
 import javax.enterprise.inject.Produces;
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -38,12 +38,12 @@
 
 import org.jboss.seam.examples.booking.model.Hotel;
 import org.jboss.seam.examples.booking.model.Hotel_;
-import org.jboss.seam.international.status.MessageFactory;
+import org.jboss.seam.international.status.builder.TemplateMessage;
 import org.slf4j.Logger;
 
- at Named("hotelSearch")
 @Stateful
 @SessionScoped
+ at Named("hotelSearch")
 public class HotelSearchBean implements HotelSearch
 {
    @Inject
@@ -56,7 +56,7 @@
    private SearchCriteria criteria;
 
    @Inject
-   private MessageFactory msg;
+   private Instance<TemplateMessage> messageBuilder;
 
    private boolean nextPageAvailable = false;
 
@@ -80,12 +80,9 @@
       queryHotels(criteria);
    }
 
-   public @Produces
+   @Produces
    @Named
-   @Dependent
-   // @RequestScoped // if enabled, variable doesn't get updated after the
-   // action is executed w/o a redirect
-   List<Hotel> getHotels()
+   public List<Hotel> getHotels()
    {
       return hotels;
    }
@@ -128,7 +125,7 @@
       {
          hotels = results;
       }
-      log.info(msg.info("Found {0} hotel(s) matching search term [ {1} ] (limit {2})")
+      log.info(messageBuilder.get().text("Found {0} hotel(s) matching search term [ {1} ] (limit {2})")
             .textParams(hotels.size(), criteria.getQuery(), criteria.getPageSize()).build().getText());
    }
 }

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/Booking.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/Booking.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/Booking.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -26,6 +26,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.text.DateFormat;
+import java.util.Calendar;
 import java.util.Date;
 import javax.enterprise.inject.Typed;
 
@@ -71,13 +72,15 @@
    {
    }
 
-   public Booking(Hotel hotel, User user)
+   public Booking(Hotel hotel, User user, int daysFromNow, int nights)
    {
       this.hotel = hotel;
       this.user = user;
       this.creditCardName = user.getName();
       this.smoking = false;
       this.beds = 1;
+      setReservationDates(daysFromNow, nights);
+      creditCardExpiryMonth = Calendar.getInstance().get(Calendar.MONTH) + 1;
    }
 
    @Id
@@ -198,6 +201,12 @@
       this.creditCardName = creditCardName;
    }
 
+   /**
+    * The credit card expiration month, represented using a 1-based
+    * numeric value (i.e., Jan = 1, Feb = 2, ...).
+    *
+    * @return 1-based numeric month value
+    */
    public int getCreditCardExpiryMonth()
    {
       return creditCardExpiryMonth;
@@ -208,6 +217,11 @@
       this.creditCardExpiryMonth = creditCardExpiryMonth;
    }
 
+   /**
+    * The credit card expiration year.
+    *
+    * @return numberic year value
+    */
    public int getCreditCardExpiryYear()
    {
       return creditCardExpiryYear;
@@ -239,6 +253,24 @@
       return (int) (checkoutDate.getTime() - checkinDate.getTime()) / 1000 / 60 / 60 / 24;
    }
 
+   /**
+    * Initialize the check-in and check-out dates.
+    *
+    * @param daysFromNow Number of days the stay will begin from now
+    * @param nights Length of the stay in number of nights
+    */
+   public void setReservationDates(int daysFromNow, int nights)
+   {
+      Calendar refDate = Calendar.getInstance();
+      refDate.set(
+            refDate.get(Calendar.YEAR),
+            refDate.get(Calendar.MONTH),
+            refDate.get(Calendar.DAY_OF_MONTH) + daysFromNow, 0, 0, 0);
+      setCheckinDate(refDate.getTime());
+      refDate.add(Calendar.DAY_OF_MONTH, nights);
+      setCheckoutDate(refDate.getTime());
+   }
+
    @Override
    public String toString()
    {

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -27,9 +27,11 @@
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.Table;
+import javax.persistence.Transient;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Pattern;
 import javax.validation.constraints.Size;
+import org.hibernate.validator.constraints.Email;
 
 /**
  * <p>
@@ -48,25 +50,27 @@
    private String username;
    private String password;
    private String name;
+   private String email;
 
    public User()
    {
    }
 
-   public User(final String name, final String username)
+   public User(final String name, final String username, final String email)
    {
       this.name = name;
       this.username = username;
+      this.email = email;
    }
 
-   public User(final String name, final String username, final String password)
+   public User(final String name, final String username, final String email, final String password)
    {
-      this(name, username);
+      this(name, username, email);
       this.password = password;
    }
 
    @NotNull
-   @Size(max = 100)
+   @Size(min = 1, max = 100)
    public String getName()
    {
       return name;
@@ -103,6 +107,24 @@
       this.username = username;
    }
 
+   @NotNull
+   @Email
+   public String getEmail()
+   {
+      return email;
+   }
+
+   public void setEmail(final String email)
+   {
+      this.email = email;
+   }
+
+   @Transient
+   public String getEmailWithName()
+   {
+      return name + " <" + email + ">";
+   }
+
    @Override
    public String toString()
    {

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User_.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User_.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/model/User_.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -21,15 +21,16 @@
  */
 package org.jboss.seam.examples.booking.model;
 
-import javax.persistence.metamodel.SingularAttribute;
-import javax.persistence.metamodel.StaticMetamodel;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.StaticMetamodel;
 
 @StaticMetamodel(User.class)
 public abstract class User_ {
 
+   public static volatile SingularAttribute<User, String> name;
 	public static volatile SingularAttribute<User, String> username;
-	public static volatile SingularAttribute<User, String> name;
 	public static volatile SingularAttribute<User, String> password;
+	public static volatile SingularAttribute<User, String> email;
 
 }
 

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardExpiryYears.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardExpiryYears.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardExpiryYears.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -27,7 +27,6 @@
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardReferenceProducer.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardReferenceProducer.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/examples/booking/reference/CreditCardReferenceProducer.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -56,9 +56,9 @@
    {
       List<Integer> years = new ArrayList<Integer>(8);
       int currentYear = Calendar.getInstance().get(Calendar.YEAR);
-      for (int y = currentYear; y <= (currentYear + 8); y++)
+      for (int i = 0; i < 8; i++)
       {
-         years.add(y);
+         years.add(currentYear + i);
       }
 
       return years;

Modified: examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java
===================================================================
--- examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/java/org/jboss/seam/faces/component/UIInputContainer.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -23,8 +23,10 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import javax.el.ValueReference;
 import javax.faces.FacesException;
@@ -34,9 +36,12 @@
 import javax.faces.component.NamingContainer;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIComponentBase;
+import javax.faces.component.UIInput;
 import javax.faces.component.UIMessage;
 import javax.faces.component.UINamingContainer;
 import javax.faces.component.UIViewRoot;
+import javax.faces.component.behavior.AjaxBehavior;
+import javax.faces.component.behavior.ClientBehavior;
 import javax.faces.component.html.HtmlOutputLabel;
 import javax.faces.context.FacesContext;
 import javax.faces.validator.BeanValidator;
@@ -197,6 +202,8 @@
       return "message";
    }
 
+   private InputContainerElements elements;
+
    @Override
    public void encodeBegin(final FacesContext context) throws IOException
    {
@@ -207,19 +214,15 @@
 
       super.encodeBegin(context);
 
-      InputContainerElements elements = scan(getFacet(UIComponent.COMPOSITE_FACET_NAME), null, context);
+      elements = scan(getFacet(UIComponent.COMPOSITE_FACET_NAME), context);
       // assignIds(elements, context);
       wire(elements, context);
 
       getAttributes().put(getElementsAttributeName(), elements);
 
-      if (elements.hasValidationError())
-      {
-         getAttributes().put(getInvalidAttributeName(), true);
-      }
+      getAttributes().put(getInvalidAttributeName(), elements.hasValidationError());
 
-      // set the required attribute, but only if the user didn't already assign
-      // it
+      // set the required attribute, but only if the user didn't already assign it
       if (!getAttributes().containsKey(getRequiredAttributeName()) && elements.hasRequiredInput())
       {
          getAttributes().put(getRequiredAttributeName(), true);
@@ -250,6 +253,16 @@
       {
          endContainerElement(context);
       }
+
+      // temporary workaround for state saving bug; remove any ClientBehaviors added dynamically
+      for (EditableValueHolder i : elements.getInputs())
+      {
+         Map<String, List<ClientBehavior>> b = ((UIInput) i).getClientBehaviors();
+         for (String k : b.keySet())
+         {
+            b.get(k).clear();
+         }
+      }
    }
 
    protected void startContainerElement(final FacesContext context) throws IOException
@@ -304,11 +317,11 @@
     * 
     * @return a composite object of the input container elements
     */
-   protected InputContainerElements scan(final UIComponent component, InputContainerElements elements, final FacesContext context)
+   protected InputContainerElements scan(final UIComponent component, final FacesContext context)
    {
       if (elements == null)
       {
-         elements = new InputContainerElements();
+         elements = new InputContainerElements(getId(), getAttributes());
       }
 
       // NOTE we need to walk the tree ignoring rendered attribute because it's
@@ -329,9 +342,8 @@
       // may need to walk smarter to ensure "element of least suprise"
       for (UIComponent child : component.getChildren())
       {
-         scan(child, elements, context);
+         scan(child, context);
       }
-
       return elements;
    }
 
@@ -447,6 +459,8 @@
 
    public static class InputContainerElements
    {
+      private String containerId;
+      private Map<String, Object> attributes;
       private String propertyName;
       private HtmlOutputLabel label;
       private final List<EditableValueHolder> inputs = new ArrayList<EditableValueHolder>();
@@ -454,6 +468,12 @@
       private boolean validationError = false;
       private boolean requiredInput = false;
 
+      public InputContainerElements(final String containerId, final Map<String, Object> attributes)
+      {
+         this.containerId = containerId;
+         this.attributes = attributes;
+      }
+
       public HtmlOutputLabel getLabel()
       {
          return label;
@@ -472,6 +492,17 @@
       public void registerInput(final EditableValueHolder input, final Validator validator, final FacesContext context)
       {
          inputs.add(input);
+         if (Boolean.TRUE.equals(attributes.get("ajax")))
+         {
+            UIInput inputc = (UIInput) input;
+            Map<String, List<ClientBehavior>> behaviors = inputc.getClientBehaviors();
+            if (!behaviors.containsKey("blur"))
+            {
+               AjaxBehavior ajax = new AjaxBehavior();
+               ajax.setRender(Arrays.asList(containerId));
+               inputc.addClientBehavior("blur", ajax);
+            }
+         }
          if (input.isRequired() || isRequiredByConstraint(input, validator, context))
          {
             requiredInput = true;

Modified: examples/trunk/booking-simplified/src/main/resources/messages.properties
===================================================================
--- examples/trunk/booking-simplified/src/main/resources/messages.properties	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/resources/messages.properties	2010-06-17 09:33:29 UTC (rev 13211)
@@ -2,13 +2,13 @@
 booking.checkInNotFutureDate=Check-in date must be a future date.
 booking.checkOutBeforeCheckIn=Check-out date must be after check in date.
 booking.confirmed=You're booked to stay at the {0} {1}.
-booking.canceled=Your booking at the {0} on {1,date} has been canceled.
+booking.canceled=Your booking at the {0} on {1} has been canceled.
 booking.doesNotExist=Our records indicate that the booking you selected has already been canceled.
 account.passwordChanged=Password successfully updated.
 account.passwordNotConfirmed=Your current password was not valid. Please try again.
 account.passwordsDoNotMatch=Passwords do not match. Please re-type the new password.
 account.usernameTaken=The username '{0}' is already taken. Please choose another username.
-registration.registered=You have been successfully registered as the user {0}!
+registration.registered=You have been successfully registered as the user {0}! You may now login.
 registration.invalid=Invalid registration. Please correct the errors and try again.
 identity.loggedOut=You have successfully ended your session.
 identity.loggedIn=You're signed in as {0}.


Property changes on: examples/trunk/booking-simplified/src/main/webapp/WEB-INF
___________________________________________________________________
Name: svn:ignore
   - sun-web.xml

.faces-config.xml.jsfdia

lib


Modified: examples/trunk/booking-simplified/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/WEB-INF/faces-config.xml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/WEB-INF/faces-config.xml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -105,7 +105,7 @@
       <navigation-case>
          <from-action>#{registrar.register}</from-action>
          <if>#{registrar.registered}</if>
-         <to-view-id>/account.xhtml</to-view-id>
+         <to-view-id>/home.xhtml</to-view-id>
          <redirect/>
       </navigation-case>
 

Modified: examples/trunk/booking-simplified/src/main/webapp/WEB-INF/fragments/account.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/WEB-INF/fragments/account.xhtml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/WEB-INF/fragments/account.xhtml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -6,7 +6,8 @@
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://http://java.sun.com/jsf/composite/components/property">
     
+   <p:output label="Full name" value="#{currentUser.name}"/>
    <p:output label="Username" value="#{currentUser.username}"/>
-   <p:output label="Full name" value="#{currentUser.name}"/>
+   <p:output label="Email address" value="#{currentUser.email}"/>
 
 </ui:composition>

Modified: examples/trunk/booking-simplified/src/main/webapp/book.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/book.xhtml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/book.xhtml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -65,7 +65,7 @@
                   </h:selectOneMenu>
                </p:input>
 
-               <p:input id="creditCardExpiry" inputs="2">
+               <p:input id="creditCardExpiration" inputs="2">
                   <h:selectOneMenu id="month" value="#{booking.creditCardExpiryMonth}">
                      <f:selectItems value="#{months}" var="_month" itemValue="#{_month.number}" itemLabel="#{_month.shortName}"/>
                   </h:selectOneMenu>

Modified: examples/trunk/booking-simplified/src/main/webapp/home.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/home.xhtml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/home.xhtml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -15,9 +15,9 @@
 
          <p>
             This sample application demonstrates how easy it is to develop stateful web applications using Java EE 6
-            with portable Seam modules. Just register, login, and book a room to see the future of Java EE 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.
+            augmented with portable Seam modules. Just register, login, and book a room to see the future of Java EE in
+            action. Throughout the application you'll see notes in the sidebar that explain how this platform helps you
+            meet enterprise application requirements.
          </p>
 
          <p>
@@ -68,10 +68,6 @@
             </div>
          </fieldset>
       </h:form>
-      
-      <h:panelGroup rendered="#{identity.loggedIn}">
-      		You are logged in.
-      </h:panelGroup>
    </ui:define>
 
 </ui:composition>

Modified: examples/trunk/booking-simplified/src/main/webapp/hotel.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/hotel.xhtml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/hotel.xhtml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -7,10 +7,10 @@
    xmlns:s="http://jboss.org/seam/faces"
    template="/WEB-INF/layout/template.xhtml">
 
-	<f:metadata>
-		<f:viewParam name="id" value="#{_hotel}" />
-		<s:viewAction action="#{bookingAgent.selectHotel(_hotel)}" />
-	</f:metadata>
+   <f:metadata>
+      <f:viewParam name="id" value="#{_hotelId}"/>
+      <s:viewAction action="#{bookingAgent.selectHotel(_hotelId)}"/>
+   </f:metadata>
 
    <ui:define name="content">
 

Modified: examples/trunk/booking-simplified/src/main/webapp/password.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/password.xhtml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/password.xhtml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -25,7 +25,7 @@
             <fieldset>
             
                <p:input id="current">
-                  <h:inputSecret id="password"  value="#{currentUser.password}"/>
+                  <h:inputSecret id="password" value="#{currentUser.password}"/>
                </p:input>
             
                <p:input id="new">
@@ -44,8 +44,10 @@
                
             </fieldset>
             
-            <s:validateForm validatorId="passwordConfirmValidator" 
-            	fields="oldPassword=current:password newPassword=new:password confirmNewPassword=confirm:password"/>
+            <s:validateForm validatorId="changePasswordValidator"
+            	fields="currentPassword=current:password"/>
+            <s:validateForm validatorId="confirmPasswordValidator"
+            	fields="newPassword=new:password confirmPassword=confirm:password"/>
          </h:form>
       </div>
 

Modified: examples/trunk/booking-simplified/src/main/webapp/register.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/register.xhtml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/register.xhtml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -4,13 +4,16 @@
    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:s="http://jboss.org/seam/faces"
    xmlns:p="http://http://java.sun.com/jsf/composite/components/property"
    template="/WEB-INF/layout/template.xhtml">
 
    <ui:param name="pageClass" value="home"/>
 
    <ui:define name="metadata">
-      <f:event type="preRenderView" listener="#{registrar.notifyIfRegistrationIsInvalid(facesContext.validationFailed)}"/>
+      <f:metadata>
+         <f:event type="preRenderView" listener="#{registrar.notifyIfRegistrationIsInvalid}"/>
+      </f:metadata>
    </ui:define>
 
    <ui:define name="content">
@@ -26,34 +29,31 @@
          </div>
 
          <h:form id="registrationForm" prependId="false">
+            <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
+            <fieldset>
 
-            <fieldset>
-         
                <p:input id="username">
                   <h:inputText id="input" value="#{newUser.username}"
-                     binding="#{registrationFormControls.username}">
+                     binding="#{registrar.usernameInput}">
                      <f:ajax event="blur" render="username"/>
                   </h:inputText>
                </p:input>
 
-               <p:input id="name">
-                  <h:inputText id="input" value="#{newUser.name}">
-                     <f:ajax event="blur" render="name"/>
-                  </h:inputText>
+               <p:input id="name" ajax="true">
+                  <h:inputText id="input" value="#{newUser.name}"/>
                </p:input>
 
-               <p:input id="password">
-                  <h:inputSecret id="input" value="#{newUser.password}" redisplay="true">
-                     <f:ajax event="blur" render="password"/>
-                  </h:inputSecret>
+               <p:input id="email" ajax="true">
+                  <h:inputText id="input" value="#{newUser.email}"/>
                </p:input>
 
-               <p:input id="confirmPassword">
-                  <h:inputSecret id="input" value="#{registrar.confirmPassword}" redisplay="true"
-                     binding="#{registrationFormControls.confirmPassword}">
-                     <f:ajax event="blur" render="confirmPassword"/>
-                  </h:inputSecret>
+               <p:input id="password" ajax="true">
+                  <h:inputSecret id="input" value="#{newUser.password}" redisplay="true"/>
                </p:input>
+
+               <p:input id="confirmPassword" ajax="true">
+                  <h:inputSecret id="input" value="#{registrar.confirmPassword}" redisplay="true"/>
+               </p:input>
                
                <div class="buttonBox">
                   <h:commandButton id="register" value="Register" action="#{registrar.register}"/>
@@ -62,6 +62,10 @@
                </div>
 
             </fieldset>
+
+            <s:validateForm validatorId="confirmPasswordValidator"
+            	fields="newPassword=password:input confirmPassword=confirmPassword:input"/>
+
          </h:form>
              
       </div>

Modified: examples/trunk/booking-simplified/src/main/webapp/resources/components/property/input.xhtml
===================================================================
--- examples/trunk/booking-simplified/src/main/webapp/resources/components/property/input.xhtml	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/main/webapp/resources/components/property/input.xhtml	2010-06-17 09:33:29 UTC (rev 13211)
@@ -10,6 +10,7 @@
    <cc:interface componentType="org.jboss.seam.faces.InputContainer">
       <cc:attribute name="label" required="true"/>
       <cc:attribute name="required" required="false"/>
+      <cc:attribute name="ajax" required="false" default="false" type="java.lang.Boolean"/>
       <cc:attribute name="inputs" required="false" default="1"/>
    </cc:interface>
    

Modified: examples/trunk/booking-simplified/src/test/java/org/jboss/seam/examples/booking/booking/BookingAgentTest.java
===================================================================
--- examples/trunk/booking-simplified/src/test/java/org/jboss/seam/examples/booking/booking/BookingAgentTest.java	2010-06-17 01:01:35 UTC (rev 13210)
+++ examples/trunk/booking-simplified/src/test/java/org/jboss/seam/examples/booking/booking/BookingAgentTest.java	2010-06-17 09:33:29 UTC (rev 13211)
@@ -39,7 +39,7 @@
       WebArchive war = ShrinkWrap.create("test.war", WebArchive.class)
             .addPackage(Hotel.class.getPackage())
             .addClasses(BookingAgent.class, BookingAgentBean.class, Confirmed.class,
-                  Authenticated.class, BookingEvent.class, NoOpLogger.class)
+                  Authenticated.class, NoOpLogger.class)
             .addLibraries(
                   MavenArtifactResolver.resolve("joda-time:joda-time:1.6"),
                   MavenArtifactResolver.resolve("org.jboss.seam.international:seam-international-api:3.0.0.Alpha1"),



More information about the seam-commits mailing list