Using client-side validation support. Applied full Spring look-and-feel.

This commit is contained in:
Jeremy Grelle
2007-08-15 22:22:17 +00:00
parent 8fffbf1665
commit 4729dacd53
17 changed files with 139 additions and 105 deletions

View File

@@ -1,11 +1,12 @@
insert into Customer (username, password, name) values ('jeremy', 'barfoo', 'Jeremy Grelle')
insert into Customer (username, password, name) values ('springuser', 'barfoo', 'Spring User')
insert into Customer (username, password, name) values ('demo', 'demo', 'Demo User')
insert into Hotel (id, price, name, address, city, state, zip, country) values (1, 120, 'Marriott Courtyard', 'Tower Place, Buckhead', 'Atlanta', 'GA', '30305', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (2, 180, 'Doubletree', 'Tower Place, Buckhead', 'Atlanta', 'GA', '30305', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (3, 450, 'W Hotel', 'Union Square, Manhattan', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (4, 450, 'W Hotel', 'Lexington Ave, Manhattan', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (5, 250, 'Hotel Rouge', '1315 16th Street NW', 'Washington', 'DC', '20036', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (6, 300, '70 Park Avenue Hotel', '70 Park Avenue', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (1, 199, 'Westin Diplomat', '3555 S. Ocean Drive', 'Hollywood', 'FL', '33019', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (2, 120, 'Marriott Courtyard', 'Tower Place, Buckhead', 'Atlanta', 'GA', '30305', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (3, 180, 'Doubletree', 'Tower Place, Buckhead', 'Atlanta', 'GA', '30305', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (4, 450, 'W Hotel', 'Union Square, Manhattan', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (5, 450, 'W Hotel', 'Lexington Ave, Manhattan', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (6, 250, 'Hotel Rouge', '1315 16th Street NW', 'Washington', 'DC', '20036', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (7, 300, '70 Park Avenue Hotel', '70 Park Avenue', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (8, 300, 'Conrad Miami', '1395 Brickell Ave', 'Miami', 'FL', '33131', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (9, 80, 'Sea Horse Inn', '2106 N Clairemont Ave', 'Eau Claire', 'WI', '54703', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (10, 90, 'Super 8 Eau Claire Campus Area', '1151 W Macarthur Ave', 'Eau Claire', 'WI', '54701', 'USA')

View File

@@ -16,11 +16,6 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
//import org.hibernate.validator.Length;
//import org.hibernate.validator.NotNull;
//import org.hibernate.validator.Pattern;
@Entity
public class Booking implements Serializable {
private Long id;
@@ -68,7 +63,6 @@ public class Booking implements Serializable {
this.id = id;
}
// @NotNull
@Basic
@Temporal(TemporalType.DATE)
public Date getCheckinDate() {
@@ -80,7 +74,6 @@ public class Booking implements Serializable {
}
@ManyToOne
// @NotNull
public Hotel getHotel() {
return hotel;
}
@@ -90,7 +83,6 @@ public class Booking implements Serializable {
}
@ManyToOne
// @NotNull
public User getUser() {
return user;
}
@@ -101,7 +93,6 @@ public class Booking implements Serializable {
@Basic
@Temporal(TemporalType.DATE)
// @NotNull
public Date getCheckoutDate() {
return checkoutDate;
}
@@ -110,9 +101,6 @@ public class Booking implements Serializable {
this.checkoutDate = checkoutDate;
}
// @NotNull(message="Credit card number is required")
// @Length(min=16, max=16, message="Credit card number must 16 digits long")
// @Pattern(regex="^\\d*$", message="Credit card number must be numeric")
public String getCreditCard() {
return creditCard;
}
@@ -144,8 +132,6 @@ public class Booking implements Serializable {
this.beds = beds;
}
// @NotNull(message="Credit card name is required")
// @Length(min=3, max=70, message="Credit card name is required")
public String getCreditCardName() {
return creditCardName;
}

View File

@@ -8,9 +8,6 @@ import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
//import org.hibernate.validator.Length;
//import org.hibernate.validator.NotNull;
@Entity
public class Hotel implements Serializable {
private Long id;
@@ -32,7 +29,6 @@ public class Hotel implements Serializable {
this.id = id;
}
// @Length(max=50) @NotNull
public String getName() {
return name;
}
@@ -41,7 +37,6 @@ public class Hotel implements Serializable {
this.name = name;
}
// @Length(max=100) @NotNull
public String getAddress() {
return address;
}
@@ -50,7 +45,6 @@ public class Hotel implements Serializable {
this.address = address;
}
// @Length(max=40) @NotNull
public String getCity() {
return city;
}
@@ -59,7 +53,6 @@ public class Hotel implements Serializable {
this.city = city;
}
// @Length(min=4, max=6) @NotNull
public String getZip() {
return zip;
}
@@ -68,7 +61,6 @@ public class Hotel implements Serializable {
this.zip = zip;
}
// @Length(min=2, max=10) @NotNull
public String getState() {
return state;
}
@@ -77,7 +69,6 @@ public class Hotel implements Serializable {
this.state = state;
}
// @Length(min=2, max=40) @NotNull
public String getCountry() {
return country;
}

View File

@@ -6,10 +6,6 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
//import org.hibernate.validator.Length;
//import org.hibernate.validator.NotNull;
//import org.hibernate.validator.Pattern;
@Entity
@Table(name = "Customer")
public class User implements Serializable {
@@ -26,8 +22,6 @@ public class User implements Serializable {
public User() {
}
// @NotNull
// @Length(max = 100)
public String getName() {
return name;
}
@@ -36,8 +30,6 @@ public class User implements Serializable {
this.name = name;
}
// @NotNull
// @Length(min = 5, max = 15)
public String getPassword() {
return password;
}
@@ -47,8 +39,6 @@ public class User implements Serializable {
}
@Id
// @Length(min = 5, max = 15)
// @Pattern(regex = "^\\w*$", message = "not a valid username")
public String getUsername() {
return username;
}

View File

@@ -13,7 +13,7 @@
<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="jpaConversationListener" class="org.springframework.webflow.support.persistence.JpaFlowExecutionListener">
<bean id="jpaConversationListener" class="org.springframework.webflow.persistence.JpaFlowExecutionListener">
<constructor-arg>
<ref bean="entityManagerFactory"/>
</constructor-arg>

View File

@@ -1,5 +1,8 @@
package org.springframework.webflow.samples.booking.util;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
@@ -21,6 +24,12 @@ public class DebuggingPhaseListener implements PhaseListener {
public void beforePhase(PhaseEvent event) {
if (logger.isDebugEnabled()) {
logger.debug("Entering JSF Phase: " + event.getPhaseId());
if (event.getPhaseId() == PhaseId.APPLY_REQUEST_VALUES) {
Map input = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
for (Object key : input.keySet())
logger.debug(key + " : " + input.get(key));
}
}
}

View File

@@ -15,9 +15,9 @@
<flow:enable-scopes/>
<bean id="user" class="org.springframework.webflow.samples.booking.model.User" scope="conversation">
<property name="username" value="jeremy"/>
<property name="username" value="springuser"/>
<property name="password" value="barfoo"/>
<property name="name" value="Jeremy Grelle"/>
<property name="name" value="Spring User"/>
</bean>
<bean id="searchAction" class="org.springframework.webflow.samples.booking.SearchAction">

View File

@@ -8,7 +8,7 @@ body, div, dd, dt, dl, img, ul, ol, li, p, h1, h2, h3, h4, h5, form, hr, fieldse
----------------------------------------------- */
html {
height: 100%;
background-color: #DBD4C6;
background-color: #9cac7c;
}
img {
border: 0;
@@ -59,18 +59,25 @@ fieldset {
#header {
float: left;
width: 758px;
height:76px;
background: url(../images/hdr.bg.gif) 0 0 repeat-x;
height:36px;
background-color: #414f23;
}
#container {
float: left;
width: 758px;
background: url(../images/spring-logo.jpg) 0 0 repeat-x;
background: url(../images/header.graphic.jpg) 0 0 repeat-x;
}
#sidebar {
float: left;
width: 205px;
margin-left: 5px;
margin-top: 185px;
padding-top: 5px;
}
#content {
float: left;
width: 548px;
margin-top: 75px;
width: 448px;
margin-top: 195px;
padding-top: 5px;
background: #fff url(../img/cnt.bg.gif) 0 0 repeat-x;
}
@@ -170,7 +177,7 @@ input[type="submit"], input[type="button"] {
#content .section {
float: left;
width: 518px;
padding: 15px 15px 0 15px;
padding: 15px 15px 0 3px;
}
#content .section h1 {
font-family: "Trebuchet MS", Arial, sans-serif;
@@ -225,14 +232,22 @@ input[type="submit"], input[type="button"] {
border-left: 0px;
border-bottom: 0px;
}
#content .section .prev {
float: left;
width: 120px;
}
#content .section .next {
float: left;
}
/* Header
----------------------------------------------- */
#title {
float: left;
padding: 1px 0 6px 15px;
padding: 10px 0 6px 15px;
color: #e9efdb;
}
#status {
color: #C7B299;
color: #e9efdb;
float: right;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-weight: bold;
@@ -242,6 +257,6 @@ input[type="submit"], input[type="button"] {
padding-right: 15px;
}
#status a {
color: #C7B299;
color: #e9efdb;
text-decoration: none;
}

View File

@@ -4,6 +4,7 @@
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a="https://ajax4jsf.dev.java.net/ajax"
xmlns:sf="http://springframework.org/faces"
template="/template.xhtml">
<!-- content -->
@@ -13,7 +14,7 @@
</div>
<div class="section">
<h:form id="booking">
<h:messages/>
<h:messages errorClass="errors" />
<fieldset>
<div class="entry">
<div class="label">Name:</div>
@@ -49,29 +50,22 @@
<div class="label"><h:outputLabel for="checkinDate">Check In Date:</h:outputLabel></div>
<div class="input">
<h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true">
<f:convertDateTime pattern="MM/dd/yyyy"/>
<a:support event="onblur" reRender="checkinDateDecorate"/>
</h:inputText>
<h:graphicImage url="img/dtpick.gif" style="margin-left:5px;cursor:pointer"/>
<sf:clientDateValidator allowBlank="false" msgDisplay="block" msgClass="errors">
<h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true">
<f:convertDateTime pattern="MM/dd/yy" timeZone="EST"/>
</h:inputText>
</sf:clientDateValidator>
</div>
</div>
<div class="entry">
<div class="label"><h:outputLabel for="checkoutDate">Check Out Date:</h:outputLabel></div>
<div class="input">
<h:inputText id="checkoutDate" value="#{booking.checkoutDate}" required="true">
<f:convertDateTime pattern="MM/dd/yyyy"/>
<a:support event="onblur" reRender="checkoutDateDecorate"/>
</h:inputText>
<h:graphicImage url="img/dtpick.gif" style="margin-left:5px;cursor:pointer"/>
<sf:clientDateValidator allowBlank="false" msgDisplay="block" msgClass="errors">
<h:inputText id="checkoutDate" value="#{booking.checkoutDate}" required="true">
<f:convertDateTime pattern="MM/dd/yy" timeZone="EST"/>
</h:inputText>
</sf:clientDateValidator>
</div>
</div>
@@ -103,22 +97,19 @@
<div class="entry">
<div class="label"><h:outputLabel for="creditCard">Credit Card #:</h:outputLabel></div>
<div class="input">
<h:inputText id="creditCard" value="#{booking.creditCard}" required="true">
<a:support event="onblur" reRender="creditCardDecorate"/>
</h:inputText>
<sf:clientNumberValidator allowBlank="false" allowNegative="false" allowDecimals="false"
minLength="16" maxLength="16" msgDisplay="block" msgClass="errors">
<h:inputText id="creditCard" value="#{booking.creditCard}" required="true"/>
</sf:clientNumberValidator>
</div>
</div>
<div class="entry">
<div class="label"><h:outputLabel for="creditCardName">Credit Card Name:</h:outputLabel></div>
<div class="input">
<h:inputText id="creditCardName" value="#{booking.creditCardName}" required="true">
<a:support event="onblur" reRender="creditCardNameDecorate"/>
</h:inputText>
<sf:clientTextValidator allowBlank="false" msgDisplay="block" msgClass="errors">
<h:inputText id="creditCardName" value="#{booking.creditCardName}" required="true"/>
</sf:clientTextValidator>
</div>
</div>
@@ -154,14 +145,15 @@
<div class="entry errors">
<h:messages globalOnly="true"/>
</div>
<div class="entry">
<div class="label">&#160;</div>
<div class="input">
<h:commandButton id="proceed" value="Proceed" action="reviewDetails"/>&#160;
<sf:validateAllOnClick>
<h:commandButton id="proceed" value="Proceed" action="reviewDetails"/>
</sf:validateAllOnClick>&#160;
<h:commandButton id="cancel" immediate="true" value="Cancel" action="cancel"/>
</div>
</div>
</div>
</fieldset>
</h:form>
</div>

View File

@@ -13,7 +13,7 @@
<span class="errors">
<h:messages/>
<h:messages globalOnly="true"/>
</span>
<h1>Search Hotels</h1>
@@ -65,10 +65,14 @@
</h:commandLink>
</h:column>
</h:dataTable>
<h:commandLink id="prevPageLink" value="Previous results" actionListener="#{hotelSearch.prevPageListener}"
action="findHotels" rendered="#{hotelSearch.page > 0}"/>
<h:commandLink id="nextPageLink" value="More results" actionListener="#{hotelSearch.nextPageListener}"
action="findHotels" rendered="#{hotels != null and hotels.rowCount == hotelSearch.pageSize}"/>
<div class="prev">
<h:commandLink id="prevPageLink" value="Previous results" actionListener="#{hotelSearch.prevPageListener}"
action="findHotels" rendered="#{hotelSearch.page > 0}"/>
</div>
<div class="next">
<h:commandLink id="nextPageLink" value="More results" actionListener="#{hotelSearch.nextPageListener}"
action="findHotels" rendered="#{hotels != null and hotels.rowCount == hotelSearch.pageSize}"/>
</div>
</div>
<div class="section">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 70 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,22 +1,55 @@
<!DOCTYPE html 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"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Spring Web Stack: SWF + JSF Booking Sample</title>
<link href="/swf-booking-jsf/css/screen.css" rel="stylesheet" type="text/css" />
<ui:insert name="headIncludes"/>
</head>
<body>
<f:view>
<div align="left">Booking SWF + JSF - A Spring Web Flow Sample</div>
<hr/>
<div align="left">
<p>
<h:form>
<h:commandLink value="Book Hotels" action="flowId:main-flow"/>
</h:form>
</p>
<div id="document">
<div id="header">
<div id="title">Spring Web Stack: SWF + JSF Booking Sample</div>
</div>
<hr/>
</f:view>
</body>
<div id="container">
<a href="http://www.thespringexperience.com">
<div id="sidebar">
<img src="/swf-booking-jsf/images/diplomat.jpg" />
<img src="/swf-booking-jsf/images/tse.gif" />
<p>
The features shown in this sample are just the beginning. To see what else we've got in store
for Spring Web Flow and JSF, join us at The Spring Experience December 12 - 15, 2007 at the Westin
Diplomat in Hollywood, Florida.
</p>
</div>
</a>
<div id="content">
<div class="section">
<h1>Welcome to the Spring Web Flow Booking Sample</h1>
<p>
This sample will continue to evolve as Spring Web Flow 2.0 is developed.
</p>
<p>
As of SWF 2.0-m1, some of the new features that this sample serves to demonstrate include:
<li>Flow-scoped persistence contexts</li>
<li>Unified EL integration</li>
<li>Spring 2.0 custom scopes</li>
<li>Client-side validation support</li>
</p>
<p>
<a href="controller.swf?_flowId=main-flow">Click here to book your hotel.</a>
</p>
</div>
</div>
</div>
<div id="footer">Created with Spring, Spring Web Flow, MyFaces, and Facelets</div>
</div>
</body>
</html>

View File

@@ -6,17 +6,30 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Spring Web Stack: SWF + JSF Booking Sample</title>
<link href="/swf-booking-jsf/css/screen.css" rel="stylesheet" type="text/css" />
<ui:insert name="headIncludes"/>
</head>
<body>
<div id="document">
<div id="header">
<div id="title"><img src="/swf-booking-jsf/images/webflow-logo.jpg" alt="Spring Web Stack: SWF + JSF Booking Sample"/></div>
<div id="title">Spring Web Stack: SWF + JSF Booking Sample</div>
<div id="status">
Welcome #{user.name}
</div>
</div>
<div id="container">
<a href="http://www.thespringexperience.com">
<div id="sidebar">
<img src="/swf-booking-jsf/images/diplomat.jpg" />
<img src="/swf-booking-jsf/images/tse.gif" />
<p>
The features shown in this sample are just the beginning. To see what else we've got in store
for Spring Web Flow and JSF, join us at The Spring Experience December 12 - 15, 2007 at the Westin
Diplomat in Hollywood, Florida.
</p>
</div>
</a>
<div id="content">
<ui:insert name="content"/>
</div>