Polishing the new RESTful interface to the petclinic webapp (SPR-5487):
* Eliminated redundant 'clinic' servlet mapping (was: http://localhost:8080/petclinic/clinic/owners; now: http://localhost:8080/petclinic/owners) * A parameterless GET for /owners now returns the list of all owners, rather than an error. * /owners/form is now /owners/search (distinguishes the 'search form' resource from the 'edit owner form' resource) * Eliminated any need for redirects, <welcome-file-list/>, and index.jsp. Deleted all of them. * Updated /owners/{oid}/edit to submit using PUT instead of POST * Updated URI for edit pet form from /owners/{oid}/pets/{pid} to /owners/{oid}/pets/{pid}/edit (the edit form is a distinct resource) * Updated /owners/{oid}/pets/{pid}/edit to submit using PUT instead of POST Changes unrelated to the web interface: * Partitioned up JSPs into new owners, pets, and vets folders. * Renamed those JSPs, e.g. ownerForm.jsp -> owners/form.jsp; findOwners.jsp -> owners/search.jsp; owners.jsp -> owners/list.jsp * Updated various controllers to respect the changes to the URI templates, etc. * Updated .classpath to include all necessary projects and libs to run the webapp successfully in WTP * Updated JSP error checking rules to relax validation of fragments like header.jsp and footer.jsp
This commit is contained in:
parent
da2175c0b7
commit
3ddd08942c
|
@ -4,7 +4,6 @@
|
|||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.test"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.5.0/com.springsource.org.junit-4.5.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.5.0/com.springsource.org.junit-sources-4.5.0.jar"/>
|
||||
|
@ -36,5 +35,7 @@
|
|||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.web.servlet"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.aop"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.orm"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jst.server.core.container/com.springsource.server.ide.server.core.runtime.classpath/SpringSource dm Server (Runtime) v1.0"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.6.0"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#Fri Nov 21 08:19:32 EST 2008
|
||||
#Fri Feb 13 19:16:19 PST 2009
|
||||
classpath.helper/org.eclipse.jdt.launching.JRE_CONTAINER\:\:org.eclipse.jdt.internal.launching.macosx.MacOSXType\:\:JVM\ 1.6.0/owners=jst.java\:5.0
|
||||
classpath.helper/org.eclipse.jst.server.core.container\:\:com.springsource.server.ide.server.core.runtime.classpath\:\:SpringSource\ dm\ Server\ (Runtime)\ v1.0/owners=jst.web\:2.4
|
||||
eclipse.preferences.version=1
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faceted-project>
|
||||
<runtime name="SpringSource dm Server (Runtime) v1.0"/>
|
||||
<fixed facet="jst.java"/>
|
||||
<fixed facet="jst.web"/>
|
||||
<installed facet="jst.java" version="5.0"/>
|
||||
|
|
|
@ -44,19 +44,19 @@ public class AddOwnerForm {
|
|||
public String setupForm(Model model) {
|
||||
Owner owner = new Owner();
|
||||
model.addAttribute(owner);
|
||||
return "ownerForm";
|
||||
return "owners/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public String processSubmit(@ModelAttribute Owner owner, BindingResult result, SessionStatus status) {
|
||||
new OwnerValidator().validate(owner, result);
|
||||
if (result.hasErrors()) {
|
||||
return "ownerForm";
|
||||
return "owners/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storeOwner(owner);
|
||||
status.setComplete();
|
||||
return "redirect:/clinic/owners/" + owner.getId();
|
||||
return "redirect:/owners/" + owner.getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,19 +56,19 @@ public class AddPetForm {
|
|||
Pet pet = new Pet();
|
||||
owner.addPet(pet);
|
||||
model.addAttribute("pet", pet);
|
||||
return "petForm";
|
||||
return "pets/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
|
||||
new PetValidator().validate(pet, result);
|
||||
if (result.hasErrors()) {
|
||||
return "petForm";
|
||||
return "pets/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storePet(pet);
|
||||
status.setComplete();
|
||||
return "redirect:/clinic/owners/" + pet.getOwner().getId();
|
||||
return "redirect:/owners/" + pet.getOwner().getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,19 +48,19 @@ public class AddVisitForm {
|
|||
Visit visit = new Visit();
|
||||
pet.addVisit(visit);
|
||||
model.addAttribute("visit", visit);
|
||||
return "visitForm";
|
||||
return "pets/visitForm";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public String processSubmit(@ModelAttribute("visit") Visit visit, BindingResult result, SessionStatus status) {
|
||||
new VisitValidator().validate(visit, result);
|
||||
if (result.hasErrors()) {
|
||||
return "visitForm";
|
||||
return "pets/visitForm";
|
||||
}
|
||||
else {
|
||||
this.clinic.storeVisit(visit);
|
||||
status.setComplete();
|
||||
return "redirect:/clinic/owners/" + visit.getPet().getOwner().getId();
|
||||
return "redirect:/owners/" + visit.getPet().getOwner().getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.samples.petclinic.Clinic;
|
||||
import org.springframework.samples.petclinic.Vets;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -38,8 +39,9 @@ public class ClinicController {
|
|||
* determine the logical view name based on the request URL: "/welcome.do"
|
||||
* -> "welcome".
|
||||
*/
|
||||
@RequestMapping("/welcome")
|
||||
public void welcomeHandler() {
|
||||
@RequestMapping("/")
|
||||
public String welcomeHandler() {
|
||||
return "welcome";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,10 +55,11 @@ public class ClinicController {
|
|||
* @return a ModelMap with the model attributes for the view
|
||||
*/
|
||||
@RequestMapping("/vets")
|
||||
public ModelMap vetsHandler() {
|
||||
public String vetsHandler(Model model) {
|
||||
Vets vets = new Vets();
|
||||
vets.getVetList().addAll(this.clinic.getVets());
|
||||
return new ModelMap(vets);
|
||||
model.addAttribute(vets);
|
||||
return "vets/list";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,7 +70,7 @@ public class ClinicController {
|
|||
*/
|
||||
@RequestMapping("/owners/{ownerId}")
|
||||
public ModelAndView ownerHandler(@PathVariable("ownerId") int ownerId) {
|
||||
ModelAndView mav = new ModelAndView("owner");
|
||||
ModelAndView mav = new ModelAndView("owners/show");
|
||||
mav.addObject(this.clinic.loadOwner(ownerId));
|
||||
return mav;
|
||||
}
|
||||
|
|
|
@ -44,19 +44,19 @@ public class EditOwnerForm {
|
|||
public String setupForm(@PathVariable("ownerId") int ownerId, Model model) {
|
||||
Owner owner = this.clinic.loadOwner(ownerId);
|
||||
model.addAttribute(owner);
|
||||
return "ownerForm";
|
||||
return "owners/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@RequestMapping(method = RequestMethod.PUT)
|
||||
public String processSubmit(@ModelAttribute Owner owner, BindingResult result, SessionStatus status) {
|
||||
new OwnerValidator().validate(owner, result);
|
||||
if (result.hasErrors()) {
|
||||
return "ownerForm";
|
||||
return "owners/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storeOwner(owner);
|
||||
status.setComplete();
|
||||
return "redirect:/clinic/owners/" + owner.getId();
|
||||
return "redirect:/owners/" + owner.getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.springframework.web.bind.WebDataBinder;
|
|||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/owners/*/pets/{petId}")
|
||||
@RequestMapping("/owners/*/pets/{petId}/edit")
|
||||
@SessionAttributes("pet")
|
||||
public class EditPetForm {
|
||||
|
||||
|
@ -52,19 +52,19 @@ public class EditPetForm {
|
|||
public String setupForm(@PathVariable("petId") int petId, Model model) {
|
||||
Pet pet = this.clinic.loadPet(petId);
|
||||
model.addAttribute("pet", pet);
|
||||
return "petForm";
|
||||
return "pets/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@RequestMapping(method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
|
||||
new PetValidator().validate(pet, result);
|
||||
if (result.hasErrors()) {
|
||||
return "petForm";
|
||||
return "pets/form";
|
||||
}
|
||||
else {
|
||||
this.clinic.storePet(pet);
|
||||
status.setComplete();
|
||||
return "redirect:/clinic/owners/" + pet.getOwner().getId();
|
||||
return "redirect:/owners/" + pet.getOwner().getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class EditPetForm {
|
|||
public String deletePet(@PathVariable int petId) {
|
||||
Pet pet = this.clinic.loadPet(petId);
|
||||
this.clinic.deletePet(petId);
|
||||
return "redirect:/clinic/owners/" + pet.getOwner().getId();
|
||||
return "redirect:/owners/" + pet.getOwner().getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,30 +36,36 @@ public class FindOwnersForm {
|
|||
dataBinder.setDisallowedFields(new String[] {"id"});
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/owners/form", method = RequestMethod.GET)
|
||||
@RequestMapping(value = "/owners/search", method = RequestMethod.GET)
|
||||
public String setupForm(Model model) {
|
||||
model.addAttribute("owner", new Owner());
|
||||
return "findOwners";
|
||||
return "owners/search";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/owners", method = RequestMethod.GET)
|
||||
public String processSubmit(Owner owner, BindingResult result, Model model) {
|
||||
|
||||
// allow parameterless GET request for /owners to return all records
|
||||
if(owner.getLastName() == null) {
|
||||
owner.setLastName(""); // empty string signifies broadest possible search
|
||||
}
|
||||
|
||||
// find owners by last name
|
||||
Collection<Owner> results = this.clinic.findOwners(owner.getLastName());
|
||||
if (results.size() < 1) {
|
||||
// no owners found
|
||||
result.rejectValue("lastName", "notFound", "not found");
|
||||
return "findOwners";
|
||||
return "owners/search";
|
||||
}
|
||||
if (results.size() > 1) {
|
||||
// multiple owners found
|
||||
model.addAttribute("selections", results);
|
||||
return "owners";
|
||||
return "owners/list";
|
||||
}
|
||||
else {
|
||||
// 1 owner found
|
||||
owner = results.iterator().next();
|
||||
return "redirect:/clinic/owners/" + owner.getId();
|
||||
return "redirect:/owners/" + owner.getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,6 @@ ex.printStackTrace(new java.io.PrintWriter(out));
|
|||
|
||||
<p/>
|
||||
<br/>
|
||||
<a href="<spring:url value="/welcome" escapeXml="true" />">Home</a>
|
||||
<a href="<spring:url value="/" escapeXml="true" />">Home</a>
|
||||
|
||||
<%@ include file="/WEB-INF/jsp/footer.jsp" %>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
<table class="footer">
|
||||
<tr>
|
||||
<td><a href="<spring:url value="/clinic/welcome" escapeXml="true" />">Home</a></td>
|
||||
<td><a href="<spring:url value="/" escapeXml="true" />">Home</a></td>
|
||||
<td align="right"><img src="<spring:url value="/images/springsource-logo.png" escapeXml="true" />" alt="Sponsored by SpringSource"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
<%@ include file="/WEB-INF/jsp/includes.jsp" %>
|
||||
<%@ include file="/WEB-INF/jsp/header.jsp" %>
|
||||
<c:choose>
|
||||
<c:when test="${owner.new}"><c:set var="method" value="post"/></c:when>
|
||||
<c:otherwise><c:set var="method" value="put"/></c:otherwise>
|
||||
</c:choose>
|
||||
|
||||
<h2><c:if test="${owner.new}">New </c:if>Owner:</h2>
|
||||
|
||||
<form:form modelAttribute="owner">
|
||||
<form:form modelAttribute="owner" method="${method}">
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
|
@ -4,7 +4,6 @@
|
|||
<h2>Owners:</h2>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<thead>
|
||||
<th>Name</th>
|
||||
<th>Address</th>
|
||||
|
@ -12,7 +11,6 @@
|
|||
<th>Telephone</th>
|
||||
<th>Pets</th>
|
||||
</thead>
|
||||
</tr>
|
||||
<c:forEach var="owner" items="${selections}">
|
||||
<tr>
|
||||
<td>
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<h2>Find Owners:</h2>
|
||||
|
||||
<spring:url value="/clinic/owners" var="formUrl"/>
|
||||
<spring:url value="/owners" var="formUrl"/>
|
||||
<form:form modelAttribute="owner" action="${fn:escapeXml(formUrl)}" method="get">
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -20,6 +20,6 @@
|
|||
</form:form>
|
||||
|
||||
<br/>
|
||||
<a href='<spring:url value="/clinic/owners/new" escapeXml="true"/>'>Add Owner</a>
|
||||
<a href='<spring:url value="/owners/new" escapeXml="true"/>'>Add Owner</a>
|
||||
|
||||
<%@ include file="/WEB-INF/jsp/footer.jsp" %>
|
|
@ -78,7 +78,7 @@
|
|||
<table class="table-buttons">
|
||||
<tr>
|
||||
<td>
|
||||
<spring:url value="{ownerId}/pets/{petId}" var="petUrl">
|
||||
<spring:url value="{ownerId}/pets/{petId}/edit" var="petUrl">
|
||||
<spring:param name="ownerId" value="${owner.id}"/>
|
||||
<spring:param name="petId" value="${pet.id}"/>
|
||||
</spring:url>
|
|
@ -1,12 +1,15 @@
|
|||
<%@ include file="/WEB-INF/jsp/includes.jsp" %>
|
||||
<%@ include file="/WEB-INF/jsp/header.jsp" %>
|
||||
<c:choose>
|
||||
<c:when test="${pet.new}"><c:set var="method" value="post"/></c:when>
|
||||
<c:otherwise><c:set var="method" value="put"/></c:otherwise>
|
||||
</c:choose>
|
||||
|
||||
<h2><c:if test="${pet.new}">New </c:if>Pet</h2>
|
||||
|
||||
<b>Owner:</b> ${pet.owner.firstName} ${pet.owner.lastName}
|
||||
<br/>
|
||||
|
||||
<form:form modelAttribute="pet">
|
||||
<form:form modelAttribute="pet" method="${method}">
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
|
@ -23,7 +23,7 @@
|
|||
<table class="table-buttons">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="<spring:url value="/clinic/vets.xml" escapeXml="true" />">View as XML</a>
|
||||
<a href="<spring:url value="/vets.xml" escapeXml="true" />">View as XML</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
|
@ -5,8 +5,8 @@
|
|||
<h2><fmt:message key="welcome"/></h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="<spring:url value="/clinic/owners/form" escapeXml="true" />">Find owner</a></li>
|
||||
<li><a href="<spring:url value="/clinic/vets" escapeXml="true" />">Display all veterinarians</a></li>
|
||||
<li><a href="<spring:url value="/owners/search" escapeXml="true" />">Find owner</a></li>
|
||||
<li><a href="<spring:url value="/vets" escapeXml="true" />">Display all veterinarians</a></li>
|
||||
<li><a href="<spring:url value="/html/petclinic.html" escapeXml="true" />">Tutorial</a></li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
- DefaultAnnotationHandlerMapping is driven by these annotations and is
|
||||
- enabled by default with Java 5+.
|
||||
-->
|
||||
|
||||
|
||||
<!--
|
||||
- This bean processes annotated handler methods, applying PetClinic-specific PropertyEditors
|
||||
- for request parameter binding. It overrides the default AnnotationMethodHandlerAdapter.
|
||||
|
@ -44,6 +44,7 @@
|
|||
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
|
||||
<property name="exceptionMappings">
|
||||
<props>
|
||||
<prop key="org.springframework.web.servlet.PageNotFound">pageNotFound</prop>
|
||||
<prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop>
|
||||
<prop key="org.springframework.transaction.TransactionException">dataAccessFailure</prop>
|
||||
</props>
|
||||
|
|
|
@ -84,6 +84,29 @@
|
|||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!--
|
||||
- Map static resources to the default servlet
|
||||
- examples:
|
||||
- http://localhost:8080/images/pets.png
|
||||
- http://localhost:8080/styles/petclinic.css
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>*.png</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>*.gif</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>*.css</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>*.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!--
|
||||
- Servlet that dispatches request to registered handlers (Controller implementations).
|
||||
|
@ -110,7 +133,7 @@
|
|||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>petclinic</servlet-name>
|
||||
<url-pattern>/clinic/*</url-pattern>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<filter>
|
||||
|
@ -127,11 +150,6 @@
|
|||
<session-timeout>10</session-timeout>
|
||||
</session-config>
|
||||
|
||||
<welcome-file-list>
|
||||
<!-- Redirects to "welcome.htm" for dispatcher handling -->
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
<error-page>
|
||||
<exception-type>java.lang.Exception</exception-type>
|
||||
<!-- Displays a stack trace -->
|
||||
|
@ -149,5 +167,7 @@
|
|||
<res-auth>Container</res-auth>
|
||||
</resource-ref>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
</web-app>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<%@ include file="/WEB-INF/jsp/includes.jsp" %>
|
||||
|
||||
<%-- Redirected because we can't set the welcome page to a virtual URL. --%>
|
||||
<c:redirect url="/clinic/welcome"/>
|
||||
|
Loading…
Reference in New Issue