diff --git a/spring-webflow-samples/booking-faces/ivy.xml b/spring-webflow-samples/booking-faces/ivy.xml
index 90fe3420..db613820 100755
--- a/spring-webflow-samples/booking-faces/ivy.xml
+++ b/spring-webflow-samples/booking-faces/ivy.xml
@@ -51,6 +51,7 @@
+
diff --git a/spring-webflow-samples/booking-faces/pom.xml b/spring-webflow-samples/booking-faces/pom.xml
index a941e438..297c5379 100644
--- a/spring-webflow-samples/booking-faces/pom.xml
+++ b/spring-webflow-samples/booking-faces/pom.xml
@@ -152,6 +152,11 @@
jsf-impl2.0.3
+
+ org.primefaces
+ primefaces
+ 2.2.M1-SNAPSHOT
+ javax.servlet
@@ -217,6 +222,12 @@
Repository for Projects On Hosted on java.nethttp://download.java.net/maven/2
+
+ prime-repo
+ Prime Technology Maven Repository
+ http://repository.prime.com.tr
+ default
+ swf-booking-faces
diff --git a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/BookingService.java b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/BookingService.java
index 854859b9..00d2bc31 100755
--- a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/BookingService.java
+++ b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/BookingService.java
@@ -18,9 +18,12 @@ public interface BookingService {
/**
* Find hotels available for booking by some criteria.
* @param criteria the search criteria
+ * @param firstResult the index of the first result to return
+ * @param sortBy the field to sort by
+ * @param ascending true if the sorting should be in ascending order, false for descending
* @return a list of hotels meeting the criteria
*/
- public List findHotels(SearchCriteria criteria);
+ public List findHotels(SearchCriteria criteria, int firstResult, String sortBy, boolean ascending);
/**
* Find hotels by their identifier.
@@ -43,4 +46,11 @@ public interface BookingService {
*/
public void cancelBooking(Booking booking);
+ /**
+ * Return the total number of hotels for the given criteria.
+ * @param criteria the criteria to use
+ * @return the number of matching hotels
+ */
+ int getNumberOfHotels(SearchCriteria criteria);
+
}
diff --git a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/HotelLazyDataModel.java b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/HotelLazyDataModel.java
new file mode 100644
index 00000000..9e914e91
--- /dev/null
+++ b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/HotelLazyDataModel.java
@@ -0,0 +1,45 @@
+/**
+ *
+ */
+package org.springframework.webflow.samples.booking;
+
+import java.util.List;
+import java.util.Map;
+
+import org.primefaces.model.LazyDataModel;
+
+public class HotelLazyDataModel extends LazyDataModel {
+
+ private static final long serialVersionUID = -8832831134966938627L;
+
+ SearchCriteria searchCriteria;
+
+ BookingService bookingService;
+
+ private Hotel selected;
+
+ public HotelLazyDataModel(SearchCriteria searchCriteria, BookingService bookingService) {
+ this.searchCriteria = searchCriteria;
+ this.bookingService = bookingService;
+ }
+
+ @Override
+ public List load(int first, int pageSize, String sortField, boolean sortOrder, Map filters) {
+ searchCriteria.setCurrentPage(first / pageSize + 1);
+ return bookingService.findHotels(searchCriteria, first, sortField, sortOrder);
+ }
+
+ @Override
+ public int getRowCount() {
+ return bookingService.getNumberOfHotels(searchCriteria);
+ }
+
+ public Hotel getSelected() {
+ return selected;
+ }
+
+ public void setSelected(Hotel selected) {
+ this.selected = selected;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/JpaBookingService.java b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/JpaBookingService.java
index e5a19ed4..e68a4206 100755
--- a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/JpaBookingService.java
+++ b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/JpaBookingService.java
@@ -1,5 +1,6 @@
package org.springframework.webflow.samples.booking;
+import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
@@ -17,7 +18,9 @@ import org.springframework.util.StringUtils;
*/
@Service("bookingService")
@Repository
-public class JpaBookingService implements BookingService {
+public class JpaBookingService implements BookingService, Serializable {
+
+ private static final long serialVersionUID = 1L;
private EntityManager em;
@@ -39,13 +42,25 @@ public class JpaBookingService implements BookingService {
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
- public List findHotels(SearchCriteria criteria) {
+ public List findHotels(SearchCriteria criteria, int firstResult, String orderBy, boolean ascending) {
String pattern = getSearchPattern(criteria);
+ orderBy = (orderBy != null) ? orderBy : "name";
+ String orderDirection = (ascending) ? " ASC" : " DESC";
return em.createQuery(
- "select h from Hotel h where lower(h.name) like " + pattern + " or lower(h.city) like " + pattern
- + " or lower(h.zip) like " + pattern + " or lower(h.address) like " + pattern + " order by h."
- + criteria.getSortBy()).setMaxResults(criteria.getPageSize()).setFirstResult(
- criteria.getPage() * criteria.getPageSize()).getResultList();
+ "select h from Hotel h where lower(h.name) like :pattern or lower(h.city) like :pattern "
+ + "or lower(h.zip) like :pattern or lower(h.address) like :pattern order by h." + orderBy
+ + orderDirection).setParameter("pattern", pattern).setMaxResults(criteria.getPageSize())
+ .setFirstResult(firstResult).getResultList();
+ }
+
+ @Transactional(readOnly = true)
+ public int getNumberOfHotels(SearchCriteria criteria) {
+ String pattern = getSearchPattern(criteria);
+ Long count = (Long) em.createQuery(
+ "select count(h.id) from Hotel h where lower(h.name) like :pattern or lower(h.city) like :pattern "
+ + "or lower(h.zip) like :pattern or lower(h.address) like :pattern").setParameter("pattern",
+ pattern).getSingleResult();
+ return count.intValue();
}
@Transactional(readOnly = true)
@@ -75,9 +90,9 @@ public class JpaBookingService implements BookingService {
private String getSearchPattern(SearchCriteria criteria) {
if (StringUtils.hasText(criteria.getSearchString())) {
- return "'%" + criteria.getSearchString().toLowerCase().replace('*', '%') + "%'";
+ return "%" + criteria.getSearchString().toLowerCase().replace('*', '%') + "%";
} else {
- return "'%'";
+ return "%";
}
}
diff --git a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/SearchCriteria.java b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/SearchCriteria.java
index 109ded0d..ddae0954 100755
--- a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/SearchCriteria.java
+++ b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/SearchCriteria.java
@@ -2,6 +2,8 @@ package org.springframework.webflow.samples.booking;
import java.io.Serializable;
+import javax.faces.model.DataModel;
+
/**
* A backing bean for the main hotel search form. Encapsulates the criteria needed to perform a hotel search.
*/
@@ -20,18 +22,16 @@ public class SearchCriteria implements Serializable {
private int pageSize = 5;
/**
- * The current page of the Hotel result list.
+ * The page the user is currently on.
*/
- private int page;
+ private int currentPage = 1;
- private String sortBy = "name";
-
- public String getSortBy() {
- return sortBy;
- }
-
- public void setSortBy(String sortBy) {
- this.sortBy = sortBy;
+ /**
+ * Returns a {@link DataModel} based on the search criteria.
+ * @param bookingService the service to use to retrieve hotels.
+ */
+ public DataModel getDataModel(BookingService bookingService) {
+ return new HotelLazyDataModel(this, bookingService);
}
public String getSearchString() {
@@ -50,28 +50,16 @@ public class SearchCriteria implements Serializable {
this.pageSize = pageSize;
}
- public int getPage() {
- return page;
+ public int getCurrentPage() {
+ return currentPage;
}
- public void setPage(int page) {
- this.page = page;
- }
-
- public void nextPage() {
- page++;
- }
-
- public void previousPage() {
- page--;
- }
-
- public void resetPage() {
- page = 0;
- sortBy = "name";
+ public void setCurrentPage(int currentPage) {
+ this.currentPage = currentPage;
}
public String toString() {
return "[Search Criteria searchString = '" + searchString + "'";
}
+
}
\ No newline at end of file
diff --git a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/config/security-config.xml b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/config/security-config.xml
index eae5ca29..e0433c15 100644
--- a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/config/security-config.xml
+++ b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/config/security-config.xml
@@ -9,10 +9,11 @@
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
-
+
+
-
-
- Credit Card #:
-
-
-
-
-
-
-
-
+ -->
+
+
+ Credit Card #:
-
-
- Credit Card Name:
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
- Expiration Date:
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Credit Card Name:
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ Expiration Date:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/booking/reviewBooking.xhtml b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/booking/reviewBooking.xhtml
index 996afded..bd22b15e 100755
--- a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/booking/reviewBooking.xhtml
+++ b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/booking/reviewBooking.xhtml
@@ -3,8 +3,14 @@
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:p="http://primefaces.prime.com.tr/ui"
template="/WEB-INF/layouts/standard.xhtml">
-
+
+
+ Note that the command button actions raise events (e.g. "revise") instead of specifying method expressions.
+ The events result in transitions on the server side (see reviewBooking state in booking-flow.xml).
+
+ This page uses the PrimeFaces panel component to display a search form.
+ Mouse over the "Search String" field to see its tooltip.
+ If you are logged a second panel will show your current bookings.
+ Both panels can be toggled on and off.
+
+ Clicking "Book" will launch the booking sub-flow (see the subflow state in main-flow.xml).
+
+
+ The booking flow is protected with Spring Security (see the secured attribute in booking-flow.xml).
+
+
+ Clicking "Back to Search" will take you to the stateful search results.
+
+
-
${hotel.name}
${hotel.address}
@@ -25,10 +35,9 @@
-
-
+
+
-
\ No newline at end of file
diff --git a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/main/reviewHotels.xhtml b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/main/reviewHotels.xhtml
index 89e26986..d9f63389 100644
--- a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/main/reviewHotels.xhtml
+++ b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/flows/main/reviewHotels.xhtml
@@ -3,61 +3,50 @@
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:p="http://primefaces.prime.com.tr/ui"
template="/WEB-INF/layouts/standard.xhtml">
-
+
+
+ This page uses the PrimeFaces data table backed by a lazily loaded DataModel (see HotelLazyDataModel.java).
+ Page navigation is Ajax-based and uses JSF 2 partial rendering.
+ The name and city columns support forward and reverse sorting.
+
+
+ The DataModel is created and stored in view scope when the view is first entered (see main-flow.xml).
+ When the user makes a selection, the selection is stored in a flow-scoped "hotel" variable before transitioning to the detail page.
+
+
+
+
+ Hotel Search Results
+
+
+
+ Name
+ #{h.name}
+
+
+ Address
+ #{h.address}
+
+
+ City, State
+ #{h.city}, #{h.state}, #{h.country}
+
+
+ Zip
+ #{h.zip}
+
+
+ Action
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/intro.xhtml b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/intro.xhtml
index f6e3a982..d9e3852a 100755
--- a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/intro.xhtml
+++ b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/intro.xhtml
@@ -6,35 +6,39 @@
xmlns:sf="http://www.springframework.org/tags/faces"
template="layouts/standard.xhtml">
-
+
+
+ This is a simple standalone JSF page.
+
+
+ Clicking the "Start" link below will launch the main to search for hotels (see main-flow.xml).
+ The main flow in turn launches the booking sub-flow to book the hotel (see booking-flow.xml).
+
+
+ The main flow is accessible without logging in while the booking flow requires authentication.
+
+
+
Welcome to Spring Travel
-
- This demonstrates how to use Spring MVC and Spring Web Flow with JSF component views.
-
+
Spring Web Flow and JSF 2 with PrimeFaces components
- The key features illustrated in this sample include:
+ Key features illustrated in this sample:
A declarative navigation model enabling full browser button support and dynamic navigation rules
-
A fine-grained state management model, including support for ConversationScope and ViewScope
+
A fine-grained state management model, including support for conversation, view, and flash scopes
+
Partial page rendering via Ajax with JSF 2
Modularization of web application functionality by domain use case, illustrating project structure best-practices
-
Spring Expression Language (SpEL) integration
-
Managed persistence contexts with the Java Persistence API (JPA)
-
Unified Expression Language (EL) integration
Spring Security integration
-
Declarative page authoring with Facelets, including applying reusable page layouts
-
A lightweight component library for Ajax and client-side validation that employs progressive enhancement techniques
-
A grid layout with Blueprint CSS
+
Page layout with Blueprint CSS
Exception handling support across all layers of the application
-
Spring IDE tooling integration, with support for graphical flow modeling and visualization
-
-
-
+
+
-
\ No newline at end of file
diff --git a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/login.xhtml b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/login.xhtml
index 54676e32..b37fb945 100755
--- a/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/login.xhtml
+++ b/spring-webflow-samples/booking-faces/src/main/webapp/WEB-INF/login.xhtml
@@ -3,9 +3,15 @@
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
template="layouts/standard.xhtml">
-
+
+
+ Form-based authentication with Spring Security.
+ Spring Security is first enabled in web.xml via DelegatingFilterProxy.
+ It's configuration is located in security-config.xml.
+ Flow definitions can further be protected using the secured attribute (see booking-flow.xml).
+