SWF-1219 Update booking-mvc sample to use template URLs with path variables, the Spring MVC namespace, the HiddenHttpMethodFilter, and the spring:url tag.
This commit is contained in:
@@ -10,16 +10,18 @@ import org.springframework.webflow.mvc.servlet.AbstractFlowHandler;
|
||||
|
||||
public class BookingFlowHandler extends AbstractFlowHandler {
|
||||
|
||||
private static final String DEFAULT_URL = "/hotels/search";
|
||||
|
||||
@Override
|
||||
public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return "/hotels/index";
|
||||
return DEFAULT_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleException(FlowException e, HttpServletRequest request, HttpServletResponse response) {
|
||||
if (e instanceof NoSuchFlowExecutionException) {
|
||||
return "/hotels/index";
|
||||
return DEFAULT_URL;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
public class HotelsController {
|
||||
@@ -20,30 +20,31 @@ public class HotelsController {
|
||||
this.bookingService = bookingService;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public void index(SearchCriteria searchCriteria, Principal currentUser, Model model) {
|
||||
@RequestMapping(value = "/hotels/search", method = RequestMethod.GET)
|
||||
public void search(SearchCriteria searchCriteria, Principal currentUser, Model model) {
|
||||
if (currentUser != null) {
|
||||
List<Booking> booking = bookingService.findBookings(currentUser.getName());
|
||||
model.addAttribute(booking);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String search(SearchCriteria criteria, Model model) {
|
||||
@RequestMapping(value = "/hotels", method = RequestMethod.GET)
|
||||
public String list(SearchCriteria criteria, Model model) {
|
||||
List<Hotel> hotels = bookingService.findHotels(criteria);
|
||||
model.addAttribute(hotels);
|
||||
return "hotels/search";
|
||||
return "hotels/list";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public Hotel show(@RequestParam("id") Long id) {
|
||||
return bookingService.findHotelById(id);
|
||||
@RequestMapping(value = "/hotels/{id}", method = RequestMethod.GET)
|
||||
public String show(@PathVariable Long id, Model model) {
|
||||
model.addAttribute(bookingService.findHotelById(id));
|
||||
return "hotels/show";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String deleteBooking(@RequestParam("id") Long id) {
|
||||
@RequestMapping(value = "/bookings/{id}", method = RequestMethod.DELETE)
|
||||
public String deleteBooking(@PathVariable Long id) {
|
||||
bookingService.cancelBooking(id);
|
||||
return "redirect:index";
|
||||
return "redirect:../hotels/search";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<!-- Configure Spring Security -->
|
||||
<security:http auto-config="true">
|
||||
<security:form-login login-page="/spring/login" login-processing-url="/spring/loginProcess"
|
||||
default-target-url="/spring/hotels/index" authentication-failure-url="/spring/login?login_error=1" />
|
||||
default-target-url="/spring/hotels/search" authentication-failure-url="/spring/login?login_error=1" />
|
||||
<security:logout logout-url="/spring/logout" logout-success-url="/spring/logoutSuccess" />
|
||||
</security:http>
|
||||
|
||||
|
||||
@@ -5,20 +5,19 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||
|
||||
<!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->
|
||||
<!-- Enables controllers mapped with @RequestMapping annotations, formatting annotations @NumberFormat @DateTimeFormat, and JSR 303 style validation -->
|
||||
<mvc:annotation-driven/>
|
||||
|
||||
<!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking". -->
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
|
||||
<property name="order" value="0" />
|
||||
<property name="order" value="-1"/>
|
||||
<property name="flowRegistry" ref="flowRegistry" />
|
||||
</bean>
|
||||
|
||||
<!-- Maps request paths to @Controller classes; e.g. a path of /hotels looks for a controller named HotelsController -->
|
||||
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
|
||||
<property name="order" value="1" />
|
||||
<property name="defaultHandler">
|
||||
<!-- If no @Controller match, map path to a view to render; e.g. the "/intro" path would map to the view named "intro" -->
|
||||
<bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
|
||||
</property>
|
||||
</bean>
|
||||
<!-- Map paths directly to view names without controller processing. Use the view-name attribute if necessary: by convention the view name equals the path without the leading slash -->
|
||||
<mvc:view-controller path="/intro" />
|
||||
<mvc:view-controller path="/login" />
|
||||
<mvc:view-controller path="/logoutSuccess" />
|
||||
|
||||
<!-- Resolves logical view names returned by Controllers to Tiles; a view name to resolve is treated as the name of a tiles definition -->
|
||||
<bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
|
||||
@@ -35,12 +34,6 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Dispatches requests mapped to POJO @Controllers implementations -->
|
||||
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
|
||||
|
||||
<!-- Dispatches requests mapped to org.springframework.web.servlet.mvc.Controller implementations -->
|
||||
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
|
||||
|
||||
<!-- Dispatches requests mapped to flows to FlowHandler implementations -->
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
|
||||
<property name="flowExecutor" ref="flowExecutor"/>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<transition on="cancel" to="cancel" />
|
||||
</view-state>
|
||||
|
||||
<end-state id="bookingConfirmed" commit="true" view="externalRedirect:servletRelative:/hotels/index" />
|
||||
<end-state id="bookingConfirmed" commit="true" />
|
||||
|
||||
<end-state id="cancel" />
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
|
||||
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
|
||||
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
|
||||
|
||||
<div id="bookings" "class="section">
|
||||
<security:authorize ifAllGranted="ROLE_USER">
|
||||
@@ -34,14 +36,12 @@
|
||||
<td>${booking.checkoutDate}</td>
|
||||
<td>${booking.id}</td>
|
||||
<td>
|
||||
<a id="cancelLink_${booking.id}" href="deleteBooking?id=${booking.id}">Cancel</a>
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({
|
||||
elementId:"cancelLink_${booking.id}",
|
||||
event:"onclick",
|
||||
params: {fragments:"bookingsTable"}
|
||||
}));
|
||||
</script>
|
||||
<spring:url var="bookingUrl" value="/spring/bookings/{id}">
|
||||
<spring:param name="id" value="${booking.id}"/>
|
||||
</spring:url>
|
||||
<form:form action="${bookingUrl}" method="delete">
|
||||
<button type="submit">Cancel</button>
|
||||
</form:form>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
|
||||
|
||||
<form:form modelAttribute="searchCriteria" action="search" method="get">
|
||||
<c:url var="hotelsUrl" value="/spring/hotels"/>
|
||||
<form:form modelAttribute="searchCriteria" action="${hotelsUrl}" method="get">
|
||||
<div class="section">
|
||||
<span class="errors">
|
||||
<form:errors path="*"/>
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
|
||||
|
||||
<tiles:insertAttribute name="hotelSearchForm" />
|
||||
|
||||
<tiles:insertAttribute name="bookingsTable" />
|
||||
@@ -0,0 +1,72 @@
|
||||
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
|
||||
|
||||
<div id="heading" class="section">
|
||||
<h2>Hotel Results</h2>
|
||||
</div>
|
||||
<p>
|
||||
<a id="changeSearchLink" href="hotels/search?searchString=${searchCriteria.searchString}&pageSize=${searchCriteria.pageSize}">Change Search</a>
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({
|
||||
elementId: "changeSearchLink",
|
||||
event: "onclick",
|
||||
popup: true,
|
||||
params: {fragments: "hotelSearchForm"}
|
||||
}));
|
||||
</script>
|
||||
</p>
|
||||
<div id="hotelResults" class="section">
|
||||
<c:if test="${not empty hotelList}">
|
||||
<table class="summary">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Address</th>
|
||||
<th>City, State</th>
|
||||
<th>Zip</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:forEach var="hotel" items="${hotelList}">
|
||||
<tr>
|
||||
<td>${hotel.name}</td>
|
||||
<td>${hotel.address}</td>
|
||||
<td>${hotel.city}, ${hotel.state}, ${hotel.country}</td>
|
||||
<td>${hotel.zip}</td>
|
||||
<td><a href="hotels/${hotel.id}">View Hotel</a></td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
<c:if test="${empty hotelList}">
|
||||
<tr>
|
||||
<td colspan="5">No hotels found</td>
|
||||
</tr>
|
||||
</c:if>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="buttonGroup">
|
||||
<c:if test="${searchCriteria.page > 0}">
|
||||
<a id="prevResultsLink" href="hotels?searchString=${searchCriteria.searchString}&pageSize=${searchCriteria.pageSize}&page=${searchCriteria.page - 1}">Previous Results</a>
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({
|
||||
elementId: "prevResultsLink",
|
||||
event: "onclick",
|
||||
params: {fragments: "body"}
|
||||
}));
|
||||
</script>
|
||||
</c:if>
|
||||
<c:if test="${not empty hotelList && fn:length(hotelList) == searchCriteria.pageSize}">
|
||||
<a id="moreResultsLink" href="hotels?searchString=${searchCriteria.searchString}&pageSize=${searchCriteria.pageSize}&page=${searchCriteria.page + 1}">More Results</a>
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({
|
||||
elementId: "moreResultsLink",
|
||||
event: "onclick",
|
||||
params: {fragments: "body"}
|
||||
}));
|
||||
</script>
|
||||
</c:if>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
|
||||
@@ -1,72 +1,5 @@
|
||||
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
|
||||
|
||||
<div id="heading" class="section">
|
||||
<h2>Hotel Results</h2>
|
||||
</div>
|
||||
<p>
|
||||
<a id="changeSearchLink" href="index?searchString=${searchCriteria.searchString}&pageSize=${searchCriteria.pageSize}">Change Search</a>
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({
|
||||
elementId: "changeSearchLink",
|
||||
event: "onclick",
|
||||
popup: true,
|
||||
params: {fragments: "hotelSearchForm"}
|
||||
}));
|
||||
</script>
|
||||
</p>
|
||||
<div id="hotelResults" class="section">
|
||||
<c:if test="${not empty hotelList}">
|
||||
<table class="summary">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Address</th>
|
||||
<th>City, State</th>
|
||||
<th>Zip</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:forEach var="hotel" items="${hotelList}">
|
||||
<tr>
|
||||
<td>${hotel.name}</td>
|
||||
<td>${hotel.address}</td>
|
||||
<td>${hotel.city}, ${hotel.state}, ${hotel.country}</td>
|
||||
<td>${hotel.zip}</td>
|
||||
<td><a href="show?id=${hotel.id}">View Hotel</a></td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
<c:if test="${empty hotelList}">
|
||||
<tr>
|
||||
<td colspan="5">No hotels found</td>
|
||||
</tr>
|
||||
</c:if>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="buttonGroup">
|
||||
<c:if test="${searchCriteria.page > 0}">
|
||||
<a id="prevResultsLink" href="search?searchString=${searchCriteria.searchString}&pageSize=${searchCriteria.pageSize}&page=${searchCriteria.page - 1}">Previous Results</a>
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({
|
||||
elementId: "prevResultsLink",
|
||||
event: "onclick",
|
||||
params: {fragments: "body"}
|
||||
}));
|
||||
</script>
|
||||
</c:if>
|
||||
<c:if test="${not empty hotelList && fn:length(hotelList) == searchCriteria.pageSize}">
|
||||
<a id="moreResultsLink" href="search?searchString=${searchCriteria.searchString}&pageSize=${searchCriteria.pageSize}&page=${searchCriteria.page + 1}">More Results</a>
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.AjaxEventDecoration({
|
||||
elementId: "moreResultsLink",
|
||||
event: "onclick",
|
||||
params: {fragments: "body"}
|
||||
}));
|
||||
</script>
|
||||
</c:if>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
<tiles:insertAttribute name="hotelSearchForm" />
|
||||
|
||||
<tiles:insertAttribute name="bookingsTable" />
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<form:form id="hotel" modelAttribute="hotel" action="booking" method="post">
|
||||
<form:form id="hotel" modelAttribute="hotel" action="booking" method="get">
|
||||
<fieldset>
|
||||
<div class="field">
|
||||
<div class="label">Name:</div>
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
<tiles-definitions>
|
||||
|
||||
<definition name="hotels/index" extends="standardLayout">
|
||||
<definition name="hotels/search" extends="standardLayout">
|
||||
<put-attribute name="body">
|
||||
<definition template="/WEB-INF/hotels/index.jsp">
|
||||
<definition template="/WEB-INF/hotels/search.jsp">
|
||||
<put-attribute name="hotelSearchForm" value="/WEB-INF/hotels/hotelSearchForm.jsp" />
|
||||
<put-attribute name="bookingsTable" value="/WEB-INF/hotels/bookingsTable.jsp" />
|
||||
</definition>
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
<li>Spring IDE tooling integration, with support for graphical flow modeling and visualization</li>
|
||||
</ul>
|
||||
<p align="right">
|
||||
<a href="hotels/index">Start your Spring Travel experience</a>
|
||||
<a href="hotels/search">Start your Spring Travel experience</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -48,8 +48,6 @@
|
||||
<a href="http://www.thespringexperience.com">
|
||||
<img src="<c:url value="/resources/images/tse.gif"/>" alt="The Spring Experience" />
|
||||
</a>
|
||||
<p>
|
||||
</p>
|
||||
</div>
|
||||
<div id="main">
|
||||
<tiles:insertAttribute name="body" />
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
|
||||
|
||||
<%@ page import="org.springframework.security.web.authentication.AbstractProcessingFilter" %>
|
||||
<%@ page import="org.springframework.security.web.authentication.AuthenticationProcessingFilter" %>
|
||||
<%@ page import="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter" %>
|
||||
<%@ page import="org.springframework.security.core.AuthenticationException" %>
|
||||
|
||||
<h1>Login Required</h1>
|
||||
@@ -11,7 +10,7 @@
|
||||
<c:if test="${not empty param.login_error}">
|
||||
<div class="errors">
|
||||
Your login attempt was not successful, try again.<br /><br />
|
||||
Reason: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>
|
||||
Reason: <%= ((AuthenticationException) session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>
|
||||
</div>
|
||||
</c:if>
|
||||
<p>Valid username/passwords are:</p>
|
||||
@@ -29,7 +28,7 @@
|
||||
<div class="field">
|
||||
<div class="label"><label for="j_username">User:</label></div>
|
||||
<div class="output">
|
||||
<input type="text" name="j_username" id="j_username" <c:if test="${not empty param.login_error}">value="<%= session.getAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY) %>"</c:if> />
|
||||
<input type="text" name="j_username" id="j_username" <c:if test="${not empty param.login_error}">value="<%= session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY) %>"</c:if> />
|
||||
<script type="text/javascript">
|
||||
Spring.addDecoration(new Spring.ElementDecoration({
|
||||
elementId : "j_username",
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
<div class="section">
|
||||
<h1>Logout</h1>
|
||||
<p>You have successfully logged out.</p>
|
||||
<p><a href="<c:url value="hotels/index" />">Continue</a></p>
|
||||
<p><a href="<c:url value="hotels/search" />">Continue</a></p>
|
||||
</div>
|
||||
|
||||
@@ -11,9 +11,20 @@
|
||||
/WEB-INF/config/web-application-config.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<!-- Enables use of HTTP methods PUT and DELETE -->
|
||||
<filter>
|
||||
<filter-name>httpMethodFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>httpMethodFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- Enables Spring Security -->
|
||||
<filter>
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
Reference in New Issue
Block a user