polishing and simplifications

This commit is contained in:
Keith Donald
2008-02-27 16:37:05 +00:00
parent e07ba1a4fe
commit 09ae98d264
25 changed files with 427 additions and 390 deletions

View File

@@ -1,9 +1,14 @@
#Thu Aug 09 13:12:30 EDT 2007
#Wed Feb 27 11:35:00 EST 2008
eclipse.preferences.version=1
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true
org.springframework.ide.eclipse.core.builders.enable.osgibundleupdater=true
org.springframework.ide.eclipse.core.enable.project.preferences=false
org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.bestpractices.beansvalidator=true
org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=true
org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true
org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.legacyxmlusage.jndiobjectfactory-com.springsource.sts.bestpractices.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=true
@@ -13,7 +18,10 @@ org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.i
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.methodOverride-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.parsingProblems-org.springframework.ide.eclipse.beans.core.beansvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true
org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true

View File

@@ -7,8 +7,7 @@
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
<config>src/main/webapp/WEB-INF/config/application-layer-config.xml</config>
<config>src/main/webapp/WEB-INF/config/web-application-config.xml</config>
<config>src/main/webapp/WEB-INF/web-application-config.xml</config>
</configs>
<configSets>
<configSet>
@@ -16,8 +15,6 @@
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/webapp/WEB-INF/config/application-layer-config.xml</config>
<config>src/main/webapp/WEB-INF/config/web-application-config.xml</config>
</configs>
</configSet>
<configSet>
@@ -25,7 +22,6 @@
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/webapp/WEB-INF/config/application-layer-config.xml</config>
</configs>
</configSet>
<configSet>
@@ -33,7 +29,6 @@
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/webapp/WEB-INF/config/application-layer-config.xml</config>
</configs>
</configSet>
</configSets>

View File

@@ -13,7 +13,7 @@ public interface BookingService {
* @param username the user's name
* @return their bookings
*/
public List<Booking> findBookings(String username);
public List<Booking> findBookings(User user);
/**
* Find hotels available for booking by some criteria.
@@ -29,17 +29,9 @@ public interface BookingService {
*/
public Hotel findHotelById(Long id);
/**
* Returns a new booking object attached to the current persistence context.
* @param hotel the hotel being booked
* @param user the user performing the booking
* @return the booking
*/
public Booking createBooking(Hotel hotel, User user);
/**
* Cancel an existing booking.
* @param id the booking id
*/
public void cancelBooking(Long id);
public void cancelBooking(Booking booking);
}

View File

@@ -6,6 +6,7 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -13,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
* against the backing repository. The EntityManager reference is provided by the managing container (Spring)
* automatically.
*/
@Service
@Repository
public class JpaBookingService implements BookingService {
@@ -25,9 +27,9 @@ public class JpaBookingService implements BookingService {
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Booking> findBookings(String username) {
public List<Booking> findBookings(User user) {
return em.createQuery("select b from Booking b where b.user.username = :username order by b.checkinDate")
.setParameter("username", username).getResultList();
.setParameter("username", user.getName()).getResultList();
}
@Transactional(readOnly = true)
@@ -48,18 +50,8 @@ public class JpaBookingService implements BookingService {
// read-write transactional methods
@Transactional
public Booking createBooking(Hotel hotel, User user) {
Booking booking = new Booking(hotel, user);
em.persist(booking);
return booking;
}
@Transactional
public void cancelBooking(Long id) {
Booking booking = em.find(Booking.class, id);
if (booking != null) {
em.remove(booking);
}
public void cancelBooking(Booking booking) {
em.remove(booking);
}
// helpers

View File

@@ -0,0 +1,76 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import org.springframework.util.StringUtils;
/**
* A backing bean for the main hotel search form. Encapsulates the criteria needed to perform a hotel search.
*/
public class SearchCriteria implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The user-provided search criteria for finding Hotels.
*/
private String searchString = "";
/**
* The maximum page size of the Hotel result list
*/
private int pageSize = 5;
/**
* The current page of the Hotel result list.
*/
private int page;
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
/**
* Increase the current page
*/
public void nextPage() {
page++;
}
/**
* Decrease the current page
*/
public void prevPage() {
page--;
}
public String toString() {
StringBuffer criteria = new StringBuffer();
if (StringUtils.hasText(searchString)) {
criteria.append("Text: " + searchString + ", ");
}
criteria.append("Page Size: " + pageSize);
return criteria.toString();
}
}

View File

@@ -0,0 +1,94 @@
package org.springframework.webflow.samples.booking.web;
import java.util.ArrayList;
import java.util.List;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import org.springframework.stereotype.Service;
import org.springframework.webflow.samples.booking.Booking;
import org.springframework.webflow.samples.booking.Hotel;
import org.springframework.webflow.samples.booking.User;
@Service
public class FlowHelper {
private List<SelectItem> bedOptions;
private List<SelectItem> smokingOptions;
private List<SelectItem> creditCardExpMonths;
private List<SelectItem> creditCardExpYears;
private List<SelectItem> pageSizeOptions;
public List<SelectItem> getBedOptions() {
if (bedOptions == null) {
bedOptions = new ArrayList<SelectItem>();
bedOptions.add(new SelectItem(new Integer(1), "One king-size bed"));
bedOptions.add(new SelectItem(new Integer(2), "Two double beds"));
bedOptions.add(new SelectItem(new Integer(3), "Three beds"));
}
return bedOptions;
}
public List<SelectItem> getSmokingOptions() {
if (smokingOptions == null) {
smokingOptions = new ArrayList<SelectItem>();
smokingOptions.add(new SelectItem(Boolean.TRUE, "Smoking"));
smokingOptions.add(new SelectItem(Boolean.FALSE, "Non-Smoking"));
}
return smokingOptions;
}
public List<SelectItem> getCreditCardExpMonths() {
if (creditCardExpMonths == null) {
creditCardExpMonths = new ArrayList<SelectItem>();
creditCardExpMonths.add(new SelectItem(new Integer(1), "Jan"));
creditCardExpMonths.add(new SelectItem(new Integer(2), "Feb"));
creditCardExpMonths.add(new SelectItem(new Integer(3), "Mar"));
creditCardExpMonths.add(new SelectItem(new Integer(4), "Apr"));
creditCardExpMonths.add(new SelectItem(new Integer(5), "May"));
creditCardExpMonths.add(new SelectItem(new Integer(6), "Jun"));
creditCardExpMonths.add(new SelectItem(new Integer(7), "Jul"));
creditCardExpMonths.add(new SelectItem(new Integer(8), "Aug"));
creditCardExpMonths.add(new SelectItem(new Integer(9), "Sep"));
creditCardExpMonths.add(new SelectItem(new Integer(10), "Oct"));
creditCardExpMonths.add(new SelectItem(new Integer(11), "Nov"));
creditCardExpMonths.add(new SelectItem(new Integer(12), "Dec"));
}
return creditCardExpMonths;
}
public List<SelectItem> getCreditCardExpYears() {
if (creditCardExpYears == null) {
creditCardExpYears = new ArrayList<SelectItem>();
creditCardExpYears.add(new SelectItem(new Integer(2005), "2005"));
creditCardExpYears.add(new SelectItem(new Integer(2006), "2006"));
creditCardExpYears.add(new SelectItem(new Integer(2007), "2007"));
creditCardExpYears.add(new SelectItem(new Integer(2008), "2008"));
creditCardExpYears.add(new SelectItem(new Integer(2009), "2009"));
creditCardExpYears.add(new SelectItem(new Integer(2010), "2010"));
}
return creditCardExpYears;
}
public List<SelectItem> getPageSizeOptions() {
if (pageSizeOptions == null) {
pageSizeOptions = new ArrayList<SelectItem>();
pageSizeOptions.add(new SelectItem(new Integer(5), "5"));
pageSizeOptions.add(new SelectItem(new Integer(10), "10"));
pageSizeOptions.add(new SelectItem(new Integer(20), "20"));
}
return pageSizeOptions;
}
public Booking createBooking(Hotel hotel, User user, EntityManager em) {
Booking booking = new Booking(hotel, user);
em.persist(booking);
return booking;
}
}

View File

@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- The central service of this application that can query hotels and bookings, as well as cancel bookings -->
<bean id="bookingService" class="org.springframework.webflow.samples.booking.JpaBookingService" />
<!-- Creates a EntityManagerFactory for use with the Hibernate JPA provider and a simple in-memory data source populated with test data -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<!-- Deploys a in-memory "booking" datasource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:booking" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<!-- Executes transactions around @Transactional methods -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Drives transactions using local JPA APIs -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Automatically injects EntityManager references into data access objects that require one -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Maps JPA exceptions that occur to Spring's DataAccessException hierarchy -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
</beans>

View File

@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:web="http://www.springframework.org/schema/webflow-config"
xmlns:faces="http://www.springframework.org/schema/faces-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
http://www.springframework.org/schema/faces-config
http://www.springframework.org/schema/faces-config/spring-faces-config-2.0.xsd">
<!-- Imports the "application-layer" definining business logic and data access services -->
<import resource="application-layer-config.xml"/>
<bean name="/flows/*" class="org.springframework.webflow.mvc.FlowController">
<constructor-arg ref="flowExecutor" />
</bean>
<web:flow-executor id="flowExecutor" flow-registry="flowRegistry">
<web:flow-execution-listeners>
<web:listener ref="jpaFlowExecutionListener" criteria="*"/>
</web:flow-execution-listeners>
</web:flow-executor>
<web:flow-registry id="flowRegistry" flow-builder-services="facesServices">
<web:flow-location path="/WEB-INF/flow/main/main.xml" />
<web:flow-location path="/WEB-INF/flow/booking/booking.xml" />
</web:flow-registry>
<faces:flow-builder-services id="facesServices"/>
<!-- Installs a listener that manages JPA persistence contexts for flows that require them -->
<bean id="jpaFlowExecutionListener" class="org.springframework.webflow.persistence.JpaFlowExecutionListener">
<constructor-arg>
<ref bean="entityManagerFactory"/>
</constructor-arg>
<constructor-arg>
<ref bean="transactionManager"/>
</constructor-arg>
</bean>
</beans>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
<managed-bean>
<managed-bean-name>testBean</managed-bean-name>
<managed-bean-class>org.springframework.webflow.samples.booking.TestJsfBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<application>
<!-- Enables Facelets -->
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>
</faces-config>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="bookingActions" class="org.springframework.webflow.samples.booking.flow.booking.BookingActions"/>
</beans>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="mainActions" class="org.springframework.webflow.samples.booking.flow.main.MainActions">
<constructor-arg ref="bookingService" />
</bean>
</beans>

View File

@@ -4,7 +4,7 @@
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<attribute name="description" value="The flow that handles the process of booking a hotel for a user"/>
<attribute name="description" value="The flow that handles the process of booking a hotel for a user" />
<!--
Indicates this flow requires a persistence context
@@ -19,12 +19,12 @@
<start-state idref="loadHotel"/>
<action-state id="loadHotel">
<evaluate-action expression="#{bookingService.findHotelById(id)}" result="#{flowScope.hotel}"/>
<evaluate-action expression="#{bookingService.findHotelById(id)}" result="#{flowScope.hotel}" />
<transition on="success" to="createBooking"/>
</action-state>
<action-state id="createBooking">
<evaluate-action expression="#{bookingService.createBooking(hotel, user)}" result="#{flowScope.booking}"/>
<evaluate-action expression="#{flowHelper.createBooking(hotel, user, entityManager)}" result="#{flowScope.booking}" />
<transition on="success" to="enterBookingDetails" />
</action-state>

View File

@@ -4,7 +4,6 @@
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:sf="http://www.springframework.org/tags/faces"
xmlns:sfe="http://www.springframework.org/tags/faces-ext"
template="/template.xhtml">
<ui:define name="content">
@@ -119,13 +118,12 @@
</h:selectOneMenu>
</div>
</div>
<div class="buttonGroup">
<sf:validateAllOnClick>
<h:commandButton id="proceed" action="proceed" value="Proceed"/>
</sf:validateAllOnClick>
<h:commandButton id="cancel" immediate="true" value="Cancel" action="cancel"/>
</div>
<div class="buttonGroup">
<sf:validateAllOnClick>
<h:commandButton id="proceed" action="proceed" value="Proceed"/>
</sf:validateAllOnClick>
<h:commandButton id="cancel" immediate="true" value="Cancel" action="cancel"/>
</div>
</fieldset>
</h:form>
</div>

View File

@@ -38,8 +38,7 @@
<div class="label">Total payment:</div>
<div class="output">
<h:outputText value="#{booking.total}">
<f:convertNumber type="currency"
currencySymbol="$"/>
<f:convertNumber type="currency" currencySymbol="$"/>
</h:outputText>
</div>
</div>
@@ -60,10 +59,9 @@
<h:commandButton id="revise" value="Revise" action="revise"/>&#160;
<h:commandButton id="cancel" value="Cancel" action="cancel"/>
</div>
</fieldset>
</h:form>
</div>
</ui:define>
</ui:composition>
</ui:composition>

View File

@@ -7,6 +7,7 @@
template="/template.xhtml">
<ui:define name="content">
<h:form id="displayHotelsForm">
<div class="section">
<sf:commandLink ajaxEnabled="false" value="Return to Main" action="changeSearch"/>
@@ -17,7 +18,7 @@
</p>
<ui:fragment id="searchResultsFragment">
<div id="searchResults">
<h:outputText id="noHotelsTxt" value="No Hotels Found" rendered="#{hotels.rowCount==0}"/>
<h:outputText id="noHotelsTxt" value="No Hotels Found" rendered="#{hotels.rowCount == 0}"/>
<h:dataTable id="hotels" styleClass="summary" value="#{hotels}" var="hotel" rendered="#{hotels.rowCount > 0}">
<h:column>
<f:facet name="header">Name</f:facet>
@@ -37,17 +38,14 @@
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
<!-- @TODO - THIS LINK DOES NOT WORK ON MYFACES 1.2.0 WHEN AJAX IS ENABLED BECAUSE THEY HAVE NOT IMPLEMENTED UIData.invokeOnComponent -->
<sf:commandLink id="viewHotelLink" value="View Hotel" action="selectHotel"/>
</h:column>
</h:dataTable>
<div class="next">
<sf:commandLink id="nextPageLink" value="More Results" action="next"
rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"/>
<sf:commandLink id="nextPageLink" value="More Results" action="next" rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"/>
</div>
<div class="prev">
<sf:commandLink id="prevPageLink" value="Previous results" action="previous"
rendered="#{searchCriteria.page > 0}"/>
<sf:commandLink id="prevPageLink" value="Previous results" action="previous" rendered="#{searchCriteria.page > 0}"/>
</div>
</div>
</ui:fragment>

View File

@@ -7,46 +7,42 @@
template="/template.xhtml">
<ui:define name="content">
<ui:fragment id="hotelSearchFragment">
<div id="hotelSearch" class="section">
<span class="errors">
<h:messages globalOnly="true"/>
</span>
<h2>Search Hotels</h2>
<h:form id="mainForm">
<br/>
<br/>
<fieldset>
<div class="searchGroup">
<div class="searchField">
<sf:clientTextValidator promptMessage="Search hotels by name, address, city or zip.">
<h:inputText id="searchString" value="#{flowScope.searchCriteria.searchString}" style="width: 165px; height: 15px;"/>
</sf:clientTextValidator>
</div>
<div class="searchSize">
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
<h:selectOneMenu value="#{flowScope.searchCriteria.pageSize}" id="pageSize">
<f:selectItem itemLabel="5" itemValue="5"/>
<f:selectItem itemLabel="10" itemValue="10"/>
<f:selectItem itemLabel="20" itemValue="20"/>
</h:selectOneMenu>
</div>
<div class="searchButton">
<sf:commandButton id="findHotels" value="Find Hotels" processIds="*" actionListener="#{searchCriteria.findHotelsListener}" action="findHotels"/>
</div>
</div>
</fieldset>
</h:form>
<h:form id="mainForm"><br/><br/>
<fieldset>
<div class="searchGroup">
<div class="searchField">
<sf:clientTextValidator promptMessage="Search hotels by name, address, city, or zip.">
<h:inputText id="searchString" value="#{flowScope.searchCriteria.searchString}" style="width: 165px; height: 15px;"/>
</sf:clientTextValidator>
</div>
<div class="searchSize">
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
<h:selectOneMenu value="#{flowScope.searchCriteria.pageSize}" id="pageSize">
<f:selectItem itemLabel="5" itemValue="5"/>
<f:selectItem itemLabel="10" itemValue="10"/>
<f:selectItem itemLabel="20" itemValue="20"/>
</h:selectOneMenu>
</div>
<div class="searchButton">
<sf:commandButton id="findHotels" value="Find Hotels" processIds="hotelSearchFragment" action="findHotels"/>
</div>
</div>
</fieldset>
</h:form>
</div>
</ui:fragment>
<ui:fragment id="bookingsSection">
<ui:fragment id="bookingsFragment">
<div class="section">
<h:form id="bookingsForm">
<h2>Current Hotel Bookings</h2>
<h2>Current Hotel Bookings</h2>
<h:outputText value="No Bookings Found" rendered="#{bookings.rowCount == 0}"/>
<h:dataTable id="bookings" styleClass="summary" value="#{bookings}" var="booking" rendered="#{bookings.rowCount > 0}">
<h:column>
@@ -75,13 +71,12 @@
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
<!-- @TODO - THIS LINK DOES NOT WORK ON MYFACES 1.2.0 WHEN AJAX IS ENABLED BECAUSE THEY HAVE NOT IMPLEMENTED UIData.invokeOnComponent -->
<sf:commandLink id="cancel" value="Cancel" ajaxEnabled="false" processIds="bookingsSection" action="cancelBooking"/>
<sf:commandLink id="cancel" value="Cancel" ajaxEnabled="false" processIds="bookingsFragment" action="cancelBooking"/>
</h:column>
</h:dataTable>
</h:form>
</div>
</ui:fragment>
</ui:define>
</ui:define>
</ui:composition>

View File

@@ -4,51 +4,48 @@
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<attribute name="description" value="The main flow of the application that handles searching for hotels to book"/>
<attribute name="description" value="The main flow of the application lets a user search for hotels to book" />
<var name="searchCriteria" class="org.springframework.webflow.samples.booking.flow.main.SearchCriteria" scope="flow" />
<var name="searchCriteria" class="org.springframework.webflow.samples.booking.SearchCriteria" />
<start-actions>
<action method="initCurrentUser" bean="mainActions" />
<evaluate-action expression="#{bookingService.findBookings(user.username)}" result="#{flowScope.bookings}"
type="selectOneDataModel"/>
<evaluate-action expression="#{bookingService.findBookings(currentUser)}" result="#{flowScope.bookings}" type="dataModel" />
</start-actions>
<start-state idref="displayMain"/>
<start-state idref="displayMain" />
<view-state id="displayMain" view="/WEB-INF/flow/main/main.xhtml">
<transition on="findHotels" to="findHotels" />
<view-state id="displayMain" view="main.xhtml">
<transition on="findHotels" to="displayHotels" />
<transition on="cancelBooking" to="cancelBooking" />
</view-state>
<view-state id="findHotels" view="displayHotels.xhtml">
<view-state id="displayHotels" view="displayHotels.xhtml">
<render-actions>
<evaluate-action expression="#{bookingService.findHotels(searchCriteria.searchString, searchCriteria.pageSize, searchCriteria.page)}"
result="#{flowScope.hotels}" type="selectOneDataModel"/>
<evaluate-action expression="#{bookingService.findHotels(searchCriteria)}" result="#{flowScope.hotels}" type="dataModel" />
</render-actions>
<transition on="previous" to="findHotels">
<evaluate-action expression="#{searchCriteria.prevPage()}"/>
<set attribute="#{flashScope.renderIds}" value="searchResultsFragment"/>
<evaluate-action expression="#{searchCriteria.prevPage()}" />
<set attribute="#{flashScope.renderIds}" value="searchResultsFragment" />
</transition>
<transition on="next" to="findHotels">
<evaluate-action expression="#{searchCriteria.nextPage()}"/>
<set attribute="#{flashScope.renderIds}" value="searchResultsFragment"/>
<evaluate-action expression="#{searchCriteria.nextPage()}" />
<set attribute="#{flashScope.renderIds}" value="searchResultsFragment" />
</transition>
<transition on="selectHotel" to="displayHotel"/>
<transition on="changeSearch" to="editSearchPopup"/>
<transition on="selectHotel" to="displayHotel" />
<transition on="changeSearch" to="editSearchPopup" />
</view-state>
<view-state id="editSearchPopup" view="main.xhtml">
<attribute name="modal" value="true" type="java.lang.Boolean"/>
<attribute name="modal" value="true" type="boolean" />
<entry-actions>
<set attribute="#{flashScope.renderIds}" value="hotelSearchFragment"/>
<set attribute="#{flashScope.renderIds}" value="hotelSearchFragment" />
</entry-actions>
<transition on="findHotels" to="findHotels" />
<transition on="findHotels" to="displayHotels" />
</view-state>
<view-state id="displayHotel" view="hotelDetails.xhtml">
<render-actions>
<set attribute="#{hotel}" value="#{hotels.selectedRow}" scope="request"/>
<set attribute="#{hotel}" value="#{hotels.selectedRow}" scope="request" />
</render-actions>
<transition on="book" to="bookHotel" />
<transition on="cancel" to="displayMain" />
@@ -57,7 +54,7 @@
<subflow-state id="bookHotel" flow="booking">
<attribute-mapper>
<input-mapper>
<mapping source="#{hotels.selectedRow.id}" target="#{id}"/>
<mapping source="#{hotels.selectedRow.id}" target="#{id}" />
</input-mapper>
</attribute-mapper>
<transition on="bookingAuthorized" to="reloadCurrentUserBookings" />
@@ -67,18 +64,15 @@
<action-state id="cancelBooking">
<bean-action method="cancelBooking" bean="bookingService">
<method-arguments>
<argument expression="#{bookings.selectedRow.id}" parameter-type="long"/>
<argument expression="#{bookings.selectedRow}" parameter-type="long" />
</method-arguments>
</bean-action>
<transition on="success" to="reloadCurrentUserBookings" />
</action-state>
<action-state id="reloadCurrentUserBookings">
<evaluate-action expression="#{bookingService.findBookings(user.username)}" result="#{flowScope.bookings}"
type="selectOneDataModel"/>
<evaluate-action expression="#{bookingService.findBookings(currentUser)}" result="#{flowScope.bookings}" type="dataModel" />
<transition on="success" to="displayMain" />
</action-state>
<import resource="main-beans.xml"/>
</flow>

View File

@@ -0,0 +1,40 @@
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:sf="http://www.springframework.org/tags/faces"
template="/template.xhtml">
<ui:define name="content">
<div class="section">
<h1>Welcome to the Spring Faces Sample Application</h1>
<p>
This hotel booking sample application illustrates "Spring Faces", Spring's first-class support for Java Server Faces (JSF).
Spring Faces integrates Spring, Spring Web Flow, Dojo, Ext, and Facelets to provide a
compelling solution for developing rich web applications with JSF.
</p>
<p>
Currently, Spring Faces is released as a component of the Spring Web Flow distribution,
and has been available beginning with Spring Web Flow 2.0.
</p>
<p>
The key features illustrated in this sample include:
</p>
<ul>
<li>A unified navigation model</li>
<li>A robust state management model</li>
<li>Modularization of web application functionality by domain responsibility</li>
<li>Flow-managed persistence contexts with the Java Persistence API (JPA)</li>
<li>Unified Expression Language (EL) integration</li>
<li>Client-side validation with Dojo and Ext</li>
<li>Spring IDE integration, with support for graphical flow modeling</li>
</ul>
<p align="right">
<a href="spring/main">Start your hotel booking experience</a>
</p>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,52 @@
<!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: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 Faces: Hotel Booking Sample Application</title>
<style type="text/css" media="screen">
@import url("${request.contextPath}/resources/css-framework/css/tools.css");
@import url("${request.contextPath}/resources/css-framework/css/typo.css");
@import url("${request.contextPath}/resources/css-framework/css/forms.css");
@import url("${request.contextPath}/resources/css-framework/css/layout-navtop-localleft.css");
@import url("${request.contextPath}/resources/css-framework/css/layout.css");
@import url("${request.contextPath}/resources/css/booking.css");
</style>
<ui:insert name="headIncludes"/>
</head>
<body class="tundra spring">
<div id="page">
<div id="header" class="clearfix spring">
<div id="welcome">
<div class="left">Spring Faces: Hotel Booking Sample Application</div>
<div class="right">
Welcome, #{currentUser.name}
</div>
</div>
<div id="branding" class="spring">
<img src="${request.contextPath}/images/header.jpg" alt="foo bar"/>
</div>
</div>
<div id="content" class="clearfix spring">
<div id="local" class="spring">
<a href="http://www.thespringexperience.com">
<img src="${request.contextPath}/images/diplomat.jpg" />
</a>
<a href="http://www.thespringexperience.com">
<img src="${request.contextPath}/images/tse.gif" />
</a>
<p>
</p>
</div>
<div id="main">
<ui:insert name="content"/>
</div>
</div>
<div id="footer" class="clearfix spring">
<a href="http://www.springframework.org"><img src="${request.contextPath}/images/powered-by-spring.png" /></a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:faces="http://www.springframework.org/schema/faces-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
http://www.springframework.org/schema/faces-config
http://www.springframework.org/schema/faces-config/spring-faces-config-2.0.xsd">
<!-- Activates annotation-based bean configuration -->
<context:annotation-config/>
<!-- Instructs Spring to perfrom declarative transaction managemenet on annotated classes -->
<tx:annotation-driven />
<!-- Handles requests to the Spring Web Flow system -->
<bean name="/flows/*" class="org.springframework.webflow.mvc.FlowController">
<constructor-arg ref="flowExecutor" />
</bean>
<!-- Executes flows: the central entry point into the Spring Web Flow system -->
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
<webflow:flow-execution-listeners>
<webflow:listener ref="jpaFlowExecutionListener" criteria="*"/>
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices">
<webflow:flow-location path="/WEB-INF/flows/*/*-flow.xml" />
</webflow:flow-registry>
<!-- Installs a listener that manages JPA persistence contexts for flows that require them -->
<bean id="jpaFlowExecutionListener" class="org.springframework.webflow.persistence.JpaFlowExecutionListener">
<constructor-arg ref="entityManagerFactory" />
<constructor-arg ref="transactionManager" />
</bean>
<!-- Configures the Spring Web Flow JSF integration -->
<faces:flow-builder-services id="facesFlowBuilderServices"/>
<!-- Drives transactions using local JPA APIs -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Creates a EntityManagerFactory for use with the Hibernate JPA provider and a simple in-memory data source populated with test data -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<!-- Deploys a in-memory "booking" datasource populated -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:booking" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
</beans>

View File

@@ -10,38 +10,32 @@
<param-value>.xhtml</param-value>
</context-param>
<!-- Special Facelets Debug Output for Development -->
<!-- Enables special Facelets debug output during development -->
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<!-- Cause Facelets to refresh templates during development -->
<!-- Causes Facelets to refresh templates during development -->
<context-param>
<param-name>facelets.REFRESH_PERIOD</param-name>
<param-value>1</param-value>
</context-param>
<!-- Cause Facelets always reconstruct the component tree, cutting down on the amount of state that needs to be
serialized -->
<context-param>
<param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
<param-value>false</param-value>
</context-param>
<!-- Serves static resource content from .jar files such as spring-faces.jar -->
<servlet>
<servlet-name>Resources Servlet</servlet-name>
<servlet-class>org.springframework.faces.ui.resource.ResourceServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<!-- Map all *.spring requests to the Web Servlet for handling -->
<!-- Map all /resources requests to the Resource Servlet for handling -->
<servlet-mapping>
<servlet-name>Resources Servlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<!-- Here so the JSF implementation can initialize, not used at runtime -->
<!-- Here so the JSF implementation can initialize, *not* used at runtime -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
@@ -54,18 +48,18 @@
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<!-- The front controller of the Spring Web application, responsible for handling all application requests -->
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>Spring Web MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/web-application-config.xml</param-value>
<param-value>/WEB-INF/web-application-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- Map all *.spring requests to the Web Servlet for handling -->
<!-- Map all /spring requests to the Dispatcher Servlet for handling -->
<servlet-mapping>
<servlet-name>Spring Web MVC Dispatcher Servlet</servlet-name>
<url-pattern>/spring/*</url-pattern>

View File

@@ -1,5 +1,5 @@
<html>
<head>
<meta http-equiv="Refresh" content="0; URL=intro.faces">
<meta http-equiv="Refresh" content="0; URL=/spring/intro">
</head>
</html>

View File

@@ -1,79 +0,0 @@
<!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: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 Faces: Hotel Booking Sample Application</title>
<style type="text/css" media="screen">
@import url("resources/css-framework/css/tools.css");
@import url("resources/css-framework/css/typo.css");
@import url("resources/css-framework/css/forms.css");
@import url("resources/css-framework/css/layout-navtop-localleft.css");
@import url("resources/css-framework/css/layout.css");
@import url("resources/css/booking.css");
</style>
</head>
<body class="spring">
<div id="page">
<div id="header" class="clearfix spring">
<div id="welcome">
<div class="left">Spring Faces: Hotel Booking Sample Application</div>
</div>
<div id="branding" class="spring">
<img src="images/header.jpg" alt="A room at the Westin Diplomat in Hollywood, Florida"/>
</div>
</div>
<div id="content" class="clearfix spring">
<div id="local" class="spring">
<a href="http://www.thespringexperience.com">
<img src="images/diplomat.jpg" alt="The Westin Diplomat in Hollywood, Florida"/>
</a>
<a href="http://www.thespringexperience.com">
<img src="images/tse.gif" alt="The Spring Experience"/>
</a>
<p>
The features illustrated in this sample are just the beginning.
To see what is in store for developing rich web applications with Spring, join us at
<a href="http://www.thespringexperience.com">The Spring Experience</a>
December 12 - 15, 2007 at the Westin Diplomat in Hollywood, Florida.
</p>
</div>
<div id="main">
<div class="section">
<h1>Welcome to the Spring Faces Sample Application</h1>
<p>
This hotel booking sample application illustrates "Spring Faces", Spring's first-class support for Java Server Faces (JSF).
Spring Faces integrates Spring, Spring Web Flow, Dojo, Ext, and Facelets to provide a
compelling solution for developing rich web applications with JSF.
</p>
<p>
Currently, Spring Faces is released as a component of the Spring Web Flow distribution,
and has been available beginning with Spring Web Flow 2.0 m1. The current version is running
against Spring Web Flow 2.0m2.
</p>
<p>
The key features illustrated in this sample include:
</p>
<ul>
<li>A unified navigation model</li>
<li>A robust state management model</li>
<li>Modularization of web application functionality by domain responsibility</li>
<li>Flow-managed persistence contexts with the Java Persistence API (JPA)</li>
<li>Unified Expression Language (EL) integration</li>
<li>Client-side validation with Dojo</li>
<li>Spring IDE integration, with support for graphical flow modeling</li>
</ul>
<p align="right">
<a href="spring/main">Start your hotel booking experience</a>
</p>
</div>
</div>
</div>
<div id="footer" class="clearfix spring">
<a href="http://www.springframework.org"><img src="images/powered-by-spring.png" alt="Powered By Spring" /></a>
</div>
</div>
</body>
</html>

View File

@@ -1,57 +0,0 @@
<!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: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 Faces: Hotel Booking Sample Application</title>
<style type="text/css" media="screen">
@import url("${facesContext.externalContext.requestContextPath}/resources/css-framework/css/tools.css");
@import url("${facesContext.externalContext.requestContextPath}/resources/css-framework/css/typo.css");
@import url("${facesContext.externalContext.requestContextPath}/resources/css-framework/css/forms.css");
@import url("${facesContext.externalContext.requestContextPath}/resources/css-framework/css/layout-navtop-localleft.css");
@import url("${facesContext.externalContext.requestContextPath}/resources/css-framework/css/layout.css");
@import url("${facesContext.externalContext.requestContextPath}/resources/css/booking.css");
</style>
<ui:insert name="headIncludes"/>
</head>
<body class="tundra spring">
<div id="page">
<div id="header" class="clearfix spring">
<div id="welcome">
<div class="left">Spring Faces: Hotel Booking Sample Application</div>
<div class="right">
Welcome, #{user.name}
</div>
</div>
<div id="branding" class="spring">
<img src="${facesContext.externalContext.requestContextPath}/images/header.jpg" alt="foo bar"/>
</div>
</div>
<div id="content" class="clearfix spring">
<div id="local" class="spring">
<a href="http://www.thespringexperience.com">
<img src="${facesContext.externalContext.requestContextPath}/images/diplomat.jpg" />
</a>
<a href="http://www.thespringexperience.com">
<img src="${facesContext.externalContext.requestContextPath}/images/tse.gif" />
</a>
<p>
The features illustrated in this sample are just the beginning.
To see what is in store for developing rich web applications with Spring, join us at
<a href="http://www.thespringexperience.com">The Spring Experience</a>
December 12 - 15, 2007 at the Westin Diplomat in Hollywood, Florida.
</p>
</div>
<div id="main">
<ui:insert name="content"/>
</div>
</div>
<div id="footer" class="clearfix spring">
<a href="http://www.springframework.org"><img src="${facesContext.externalContext.requestContextPath}/images/powered-by-spring.png" /></a>
</div>
</div>
</body>
</html>