SWF-1379 Remove dependency on the Portlet bridge for JSF and provide basic support within Web Flow for working Portlets and JSF. Update portlet samples

This commit is contained in:
Rossen Stoyanchev
2010-09-13 14:57:14 +00:00
parent 7986cbdb0e
commit 9e2137d3c6
32 changed files with 1448 additions and 348 deletions

View File

@@ -8,5 +8,6 @@
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.junit-3.8.2.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.junit-sources-3.8.2.jar"/>
<classpathentry kind="var" path="IVY_CACHE/javax.portlet/com.springsource.javax.portlet/2.0.0/com.springsource.javax.portlet-2.0.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.javax.portlet-sources-2.0.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -1,4 +1,4 @@
#Wed Jun 02 12:02:05 BST 2010
#Sun Sep 12 18:04:00 GMT 2010
eclipse.preferences.version=1
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
@@ -56,13 +56,13 @@ org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_block_comments=false
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_html=false
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
org.eclipse.jdt.core.formatter.comment.format_line_comments=false
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
@@ -83,6 +83,9 @@ org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
@@ -251,6 +254,8 @@ org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
@@ -261,7 +266,7 @@ org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=mixed
org.eclipse.jdt.core.formatter.tabulation.size=8
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

View File

@@ -1,7 +1,7 @@
#Thu Aug 09 13:12:30 EDT 2007
#Sun Sep 12 18:04:00 GMT 2010
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_Spring Java Conventions
formatter_profile=_Spring
formatter_settings_version=11
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
sp_cleanup.add_default_serial_version_id=true

View File

@@ -47,8 +47,11 @@
<dependency org="org.springframework" name="org.springframework.web.servlet" rev="3.0.4.RELEASE" conf="compile->compile"/>
<dependency org="org.springframework.webflow" name="org.springframework.webflow" rev="latest.integration" conf="compile->compile"/>
<dependency org="org.springframework.webflow" name="org.springframework.faces" rev="latest.integration" conf="compile->myfaces12,myfacesPortlet20"/>
<dependency org="org.springframework.webflow" name="org.springframework.faces" rev="latest.integration" conf="compile->myfaces12"/>
<dependency org="com.sun.facelets" name="com.springsource.com.sun.facelets" rev="1.1.14" conf="compile->compile"/>
<!-- Temporarily add these while experimenting without portlet bridge -->
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->runtime" />
<!-- test-time only dependencies -->
<dependency org="org.junit" name="com.springsource.junit" rev="3.8.2" conf="test->compile"/>

View File

@@ -1,172 +0,0 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.samples;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import java.util.logging.Level;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKit;
import javax.portlet.MimeResponse;
import javax.portlet.faces.Bridge;
import com.sun.facelets.FaceletViewHandler;
/**
* See: http://www.mail-archive.com/users@myfaces.apache.org/msg55213.html
*/
public class PortletFaceletViewHandler extends FaceletViewHandler {
public PortletFaceletViewHandler(ViewHandler parent) {
super(new FaceletViewHandler(parent));
}
protected ResponseWriter createResponseWriter(FacesContext context) throws IOException, FacesException {
// Only override if in a portlet request
if (context.getExternalContext().getRequestMap().get(Bridge.PORTLET_LIFECYCLE_PHASE) == null) {
return super.createResponseWriter(context);
}
ExternalContext extContext = context.getExternalContext();
RenderKit renderKit = context.getRenderKit();
// Avoid a cryptic NullPointerException when the renderkit ID
// is incorrectly set
if (renderKit == null) {
String id = context.getViewRoot().getRenderKitId();
throw new IllegalStateException("No render kit was available for id \"" + id + "\"");
}
MimeResponse response = (MimeResponse) extContext.getResponse();
// get our content type
String contentType = (String) extContext.getRequestMap().get("facelets.ContentType");
// get the encoding
String encoding = (String) extContext.getRequestMap().get("facelets.Encoding");
ResponseWriter writer;
// append */* to the contentType so createResponseWriter will succeed no matter
// the requested contentType.
if (contentType != null && !contentType.equals("*/*")) {
contentType += ",*/*";
}
// Create a dummy ResponseWriter with a bogus writer,
// so we can figure out what content type the ReponseWriter
// is really going to ask for
try {
writer = renderKit.createResponseWriter(NullWriter.Instance, contentType, encoding);
} catch (IllegalArgumentException e) {
// Added because of an RI bug prior to 1.2_05-b3. Might as well leave it in case other impls have the same
// problem.
// https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=613
log.fine("The impl didn't correctly handled '*/*' in the content type list. Trying '*/*' directly.");
writer = renderKit.createResponseWriter(NullWriter.Instance, "*/*", encoding);
}
// Override the JSF provided content type if necessary
contentType = getResponseContentType(context, writer.getContentType());
encoding = getResponseEncoding(context, writer.getCharacterEncoding());
// apply them to the response
response.setContentType(contentType + "; charset=" + encoding);
// removed 2005.8.23 to comply with J2EE 1.3
// response.setCharacterEncoding(encoding);
// Now, clone with the real writer
writer = writer.cloneWithWriter(response.getWriter());
return writer;
}
/**
* Generate the encoding
*
* @param context
* @param orig
* @return
*/
protected String getResponseEncoding(FacesContext context, String orig) {
String encoding = orig;
// see if we need to override the encoding
Map m = context.getExternalContext().getRequestMap();
Map sm = context.getExternalContext().getSessionMap();
// 1. check the request attribute
if (m.containsKey("facelets.Encoding")) {
encoding = (String) m.get("facelets.Encoding");
if (log.isLoggable(Level.FINEST)) {
log.finest("Facelet specified alternate encoding '" + encoding + "'");
}
sm.put(CHARACTER_ENCODING_KEY, encoding);
}
// 2. get it from request
if (encoding == null) {
encoding = context.getExternalContext().getResponseCharacterEncoding();
}
// 3. get it from the session
if (encoding == null) {
encoding = (String) sm.get(CHARACTER_ENCODING_KEY);
if (log.isLoggable(Level.FINEST)) {
log.finest("Session specified alternate encoding '" + encoding + "'");
}
}
// 4. default it
if (encoding == null) {
encoding = "UTF-8";
if (log.isLoggable(Level.FINEST)) {
log.finest("ResponseWriter created had a null CharacterEncoding, defaulting to UTF-8");
}
}
return encoding;
}
protected static class NullWriter extends Writer {
static final NullWriter Instance = new NullWriter();
public void write(char[] buffer) {
}
public void write(char[] buffer, int off, int len) {
}
public void write(String str) {
}
public void write(int c) {
}
public void write(String str, int off, int len) {
}
public void close() {
}
public void flush() {
}
}
}

View File

@@ -5,7 +5,6 @@
<faces-config>
<application>
<!-- Enables Facelets -->
<view-handler>org.springframework.webflow.samples.PortletFaceletViewHandler</view-handler>
<view-handler>org.springframework.faces.webflow.application.portlet.PortletFaceletViewHandler</view-handler>
</application>
</faces-config>
</faces-config>

View File

@@ -2,8 +2,7 @@
<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">
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html">
@@ -45,11 +44,9 @@
<h:outputLabel for="checkinDate">Check In Date:</h:outputLabel>
</td>
<td class="input">
<sf:clientDateValidator required="true" >
<h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true">
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
</h:inputText>
</sf:clientDateValidator>
<h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true">
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
</h:inputText>
</td>
</tr>
<tr class="field">
@@ -57,11 +54,9 @@
<h:outputLabel for="checkoutDate">Check Out Date:</h:outputLabel>
</td>
<td class="input">
<sf:clientDateValidator required="true">
<h:inputText id="checkoutDate" value="#{booking.checkoutDate}" required="true">
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
</h:inputText>
</sf:clientDateValidator>
<h:inputText id="checkoutDate" value="#{booking.checkoutDate}" required="true">
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
</h:inputText>
</td>
</tr>
<tr class="field">
@@ -89,9 +84,7 @@
<h:outputLabel for="creditCard">Credit Card #:</h:outputLabel>
</td>
<td class="input">
<sf:clientTextValidator required="true" regExp="[0-9]{16}" invalidMessage="A 16-digit credit card number is required.">
<h:inputText id="creditCard" value="#{booking.creditCard}" required="true"/>
</sf:clientTextValidator>
<h:inputText id="creditCard" value="#{booking.creditCard}" required="true"/>
</td>
</tr>
<tr class="field">
@@ -99,9 +92,7 @@
<h:outputLabel for="creditCardName">Credit Card Name:</h:outputLabel>
</td>
<td class="input">
<sf:clientTextValidator required="true">
<h:inputText id="creditCardName" value="#{booking.creditCardName}" required="true"/>
</sf:clientTextValidator>
<h:inputText id="creditCardName" value="#{booking.creditCardName}" required="true"/>
</td>
</tr>
<tr class="field">
@@ -119,9 +110,7 @@
</tr>
<tr>
<td colspan="2" class="buttonGroup">
<sf:validateAllOnClick>
<h:commandButton id="proceed" action="proceed" value="Proceed"/>&#160;
</sf:validateAllOnClick>
<h:commandButton id="proceed" action="proceed" value="Proceed"/>&#160;
<h:commandButton id="cancel" immediate="true" value="Cancel" action="cancel"/>
</td>
</tr>

View File

@@ -2,82 +2,76 @@
<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">
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html">
<ui:fragment id="hotelSearchFragment">
<div id="hotelSearch">
<h2>Search Hotels</h2>
<span class="errors">
<h:messages globalOnly="true" />
</span>
<h:form id="mainForm">
<fieldset>
<div class="searchGroup">
<div class="searchField">
<sf:clientTextValidator promptMessage="Search hotels by name, address, city, or zip.">
<h:inputText id="searchString" value="#{searchCriteria.searchString}" style="width: 165px; height: 15px;" />
</sf:clientTextValidator>
</div>
<div class="searchSize">
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
<h:selectOneMenu id="pageSize" value="#{searchCriteria.pageSize}">
<f:selectItems value="#{referenceData.pageSizeOptions}" />
</h:selectOneMenu>
</div>
<div class="searchButton">
<sf:commandButton id="findHotels" value="Find Hotels" processIds="hotelSearchFragment" action="search" />
</div>
<div id="hotelSearch">
<h2>Search Hotels</h2>
<span class="errors">
<h:messages globalOnly="true" />
</span>
<h:form id="mainForm">
<fieldset>
<div class="searchGroup">
<div class="searchField">
<h:outputLabel for="searchString">Search String:</h:outputLabel>
<h:inputText id="searchString" value="#{searchCriteria.searchString}" style="width: 165px; height: 15px;" />
</div>
</fieldset>
</h:form>
</div>
</ui:fragment>
<div class="searchSize">
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
<h:selectOneMenu id="pageSize" value="#{searchCriteria.pageSize}">
<f:selectItems value="#{referenceData.pageSizeOptions}" />
</h:selectOneMenu>
</div>
<div class="searchButton">
<h:commandButton value="Find Hotels" action="search" />
</div>
</div>
</fieldset>
</h:form>
</div>
<ui:fragment id="bookingsFragment">
<div id="bookingsSection">
<h:form id="bookingsForm">
<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>
<f:facet name="header">Name</f:facet>
#{booking.hotel.name}
</h:column>
<h:column>
<f:facet name="header">Address</f:facet>
#{booking.hotel.address}
</h:column>
<h:column>
<f:facet name="header">City, State</f:facet>
#{booking.hotel.city}, #{booking.hotel.state}
</h:column>
<h:column>
<f:facet name="header">Check in date</f:facet>
<h:outputText value="#{booking.checkinDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">Check out date</f:facet>
<h:outputText value="#{booking.checkoutDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">Confirmation number</f:facet>
#{booking.id}
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
<sf:commandLink id="cancel" value="Cancel" processIds="bookingsFragment" action="cancelBooking" />
</h:column>
</h:dataTable>
</h:form>
</div>
</ui:fragment>
<div id="bookingsSection">
<h:form id="bookingsForm">
<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>
<f:facet name="header">Name</f:facet>
#{booking.hotel.name}
</h:column>
<h:column>
<f:facet name="header">Address</f:facet>
#{booking.hotel.address}
</h:column>
<h:column>
<f:facet name="header">City, State</f:facet>
#{booking.hotel.city}, #{booking.hotel.state}
</h:column>
<h:column>
<f:facet name="header">Check in date</f:facet>
<h:outputText value="#{booking.checkinDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">Check out date</f:facet>
<h:outputText value="#{booking.checkoutDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">Confirmation number</f:facet>
#{booking.id}
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
<h:commandLink value="Cancel" action="cancelBooking" />
</h:column>
</h:dataTable>
</h:form>
</div>
</f:view>
</ui:composition>

View File

@@ -12,7 +12,6 @@
<transition on="search" to="reviewHotels" />
<transition on="cancelBooking">
<evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />
<render fragments="bookingsFragment"/>
</transition>
</view-state>
@@ -22,14 +21,12 @@
</on-render>
<transition on="previous">
<evaluate expression="searchCriteria.previousPage()" />
<render fragments="hotels:searchResultsFragment" />
</transition>
<transition on="next">
<evaluate expression="searchCriteria.nextPage()" />
<render fragments="hotels:searchResultsFragment" />
</transition>
<transition on="select" to="reviewHotel" />
<transition on="changeSearch" to="changeSearchCriteria" />
<transition on="changeSearch" to="enterSearchCriteria" />
</view-state>
<view-state id="reviewHotel">
@@ -46,15 +43,6 @@
<transition on="bookingCancelled" to="enterSearchCriteria" />
</subflow-state>
<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
<on-entry>
<render fragments="hotelSearchFragment" />
</on-entry>
<transition on="search" to="reviewHotels">
<evaluate expression="searchCriteria.resetPage()"/>
</transition>
</view-state>
<end-state id="finish" />
</flow>

View File

@@ -2,8 +2,7 @@
<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">
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html">
@@ -45,10 +44,8 @@
<h:form id="hotel">
<input name="execution" type="hidden" value="${flowExecutionContext.key}"/>
<fieldset class="buttonGroup">
<sf:commandButton id="book" ajaxEnabled="false" action="book" value="Book Hotel"/>&#160;
<sf:commandButton id="cancel" ajaxEnabled="false" action="cancel" value="Back to Search"/>
</fieldset>
<h:commandButton id="book" action="book" value="Book Hotel"/>&#160;
<h:commandButton id="cancel" action="cancel" value="Back to Search"/>
</h:form>
</f:view>

View File

@@ -2,49 +2,46 @@
<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">
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html">
<h:form id="hotels">
<h2>Hotel Results</h2>
<p>
<sf:commandLink value="Change Search" action="changeSearch"/>
<h:commandLink value="Change Search" action="changeSearch"/>
</p>
<ui:fragment id="searchResultsFragment">
<div id="searchResults">
<h:outputText id="noHotelsText" 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>
#{hotel.name}
</h:column>
<h:column>
<f:facet name="header">Address</f:facet>
#{hotel.address}
</h:column>
<h:column>
<f:facet name="header">City, State</f:facet>
#{hotel.city}, #{hotel.state}, #{hotel.country}
</h:column>
<h:column>
<f:facet name="header">Zip</f:facet>
#{hotel.zip}
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
<sf:commandLink id="viewHotelLink" value="View Hotel" action="select"/>
</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}"/>
</div>
<div class="previous">
<sf:commandLink id="previousPageLink" value="Previous results" action="previous" rendered="#{searchCriteria.page > 0}"/>
</div>
<div id="searchResults">
<h:outputText id="noHotelsText" 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>
#{hotel.name}
</h:column>
<h:column>
<f:facet name="header">Address</f:facet>
#{hotel.address}
</h:column>
<h:column>
<f:facet name="header">City, State</f:facet>
#{hotel.city}, #{hotel.state}, #{hotel.country}
</h:column>
<h:column>
<f:facet name="header">Zip</f:facet>
#{hotel.zip}
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
<h:commandLink id="viewHotelLink" value="View Hotel" action="select"/>
</h:column>
</h:dataTable>
<div class="next">
<h:commandLink id="nextPageLink" value="More Results" action="next" rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"/>
</div>
</ui:fragment>
<div class="previous">
<h:commandLink id="previousPageLink" value="Previous results" action="previous" rendered="#{searchCriteria.page > 0}"/>
</div>
</div>
</h:form>
</f:view>

View File

@@ -2,7 +2,6 @@ package org.springframework.webflow.samples.booking;
import java.io.Serializable;
/**
* A backing bean for the main hotel search form. Encapsulates the criteria needed to perform a hotel search.
*
@@ -53,4 +52,17 @@ public class SearchCriteria implements Serializable {
public void setPage(int page) {
this.page = page;
}
public void nextPage() {
page++;
}
public void previousPage() {
page--;
}
public void resetPage() {
page = 0;
}
}

View File

@@ -11,6 +11,7 @@
<form:errors path="*"/>
</span>
<fieldset>
<label for="searchString">Search For:</label>
<form:input path="searchString"/>
<label for="pageSize">Maximum results:</label>
<form:select path="pageSize">

View File

@@ -9,7 +9,9 @@
<on-render>
<evaluate expression="bookingService.findBookings(currentUser.name)" result="requestScope.bookings" />
</on-render>
<transition on="search" to="reviewHotels" />
<transition on="search" to="reviewHotels" >
<evaluate expression="searchCriteria.resetPage()" />
</transition>
<transition on="cancelBooking" to="cancelBooking" bind="false" />
</view-state>

View File

@@ -1,9 +1,16 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<h2>Hotel Results</h2>
<portlet:actionURL var="changeSearchUrl">
<portlet:param name="execution" value="${flowExecutionKey}" />
<portlet:param name="_eventId" value="changeSearch" />
</portlet:actionURL>
<a href="${changeSearchUrl}">Change Search</a>
<table class="summary">
<thead>
<tr>
@@ -38,3 +45,19 @@
</c:if>
</tbody>
</table>
<c:if test="${searchCriteria.page > 0}">
<portlet:actionURL var="prevResultsUrl">
<portlet:param name="execution" value="${flowExecutionKey}" />
<portlet:param name="_eventId" value="previous" />
</portlet:actionURL>
<a href="${prevResultsUrl}">Previous Results</a>
</c:if>
<c:if test="${not empty hotels && fn:length(hotels) == searchCriteria.pageSize}">
<portlet:actionURL var="moreResultsUrl">
<portlet:param name="execution" value="${flowExecutionKey}" />
<portlet:param name="_eventId" value="next" />
</portlet:actionURL>
<a href="${moreResultsUrl}">More Results</a>
</c:if>