5. Spring MVC – Advanced topics
Annotation driven controllers
@Controller
» Spring stereotype that identify a class as being a Spring
Bean.
» Has an optional ‘value’ property.
// Bean name is ‘loginController’
@Controller
public class LoginController {
}
// Bean name is ‘portal’.
@Controller(‚portal‛)
public class PortalController {
}
6. Spring MVC – Advanced topics
Annotation driven controllers
@RequestMapping
» Define URL mapping for a class and/or method.
// Controller root URL: http://host.com/portal
@Controller
@RequestMapping(‚/portal‛)
public class PortalController {
// Handle [GET] http://host.com/portal
@RequestMapping(method = RequestMethod.GET)
public String enterPortal() { ... }
// Handle [GET] http://host.com/portal/userProfile
@RequestMapping(‚/userProfile‛)
public String processUserProfileRequest() { ... }
}
» Support deterministic and Ant-style mapping
7. Spring MVC – Advanced topics
Annotation driven controllers
@RequestMapping
» Available properties:
method – List of supported HTTP method (GET, POST, ...).
produces/consumes – define expected content types.
GET http://google.com/ HTTP/1.1
Accept: text/html, application/xhtml+xml, */* HTTP
Accept-Language: he-IL request
Accept-Encoding: gzip, deflate
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8 HTTP
Date: Sun, 29 Jan 2012 19:45:21 GMT response
Expires: Tue, 28 Feb 2012 19:45:21 GMT
8. Spring MVC – Advanced topics
Annotation driven controllers
@RequestMapping
@Controller
@RequestMapping(‚/portal‛)
public class UserInfoController {
@RequestMapping(value = ‚/userInfo/xml‚,
consumes = ‚application/json‛,
produces = ‚application/xml‛)
public UserInformation getUserInformationAsXML() { Requires message
}
converters
@RequestMapping(value = ‚/userInfo/yaml‚,
consumes = ‚application/json‛,
produces = ‚application/Json‛)
public UserInformation getUserInformationAsJSon() {
}
}
9. Spring MVC – Advanced topics
Annotation driven controllers
@RequestMapping
» Required parameters.
// URL must in a form of: http://host.com/?userId=...&username=admin
@RequestMapping(value = ‚/‚, params = { ‚userId‛, ‚username!=guest‛, ‚!password‛ })
public UserInformation getUserInformationAsXML() {
}
» Required headers
@RequestMapping(value = ‚/userInfo‚, headers = { ‚Accept-Language=he-IL‛ })
public UserInformation getUserInformationAsXML() {
} GET http://google.com/ HTTP/1.1
Accept-Language: he-IL
Accept-Encoding: gzip, deflate
10. Spring MVC – Advanced topics
Annotation driven controllers
URI templates (@PathVariable)
» Allow us to define part of the URI as a template token.
» Support regular expressions to narrow scope of values.
» Only for simple types, java.lang.String or Date variant.
» Throw TypeMismatchException on failure to convert.
// Handle ‘userId’ with positive numbers only (0 or greater).
@RequestMapping(‚/users/{userId:[0-9]+})
public void processUserRequest(@PathVariable(‚userId‛) int userId) { ... }
// Handle ‘userId’ with negative numbers only.
@RequestMapping(‚/users/{userId:-[0-9]+})
public void processUserRequest(@PathVariable(‚userId‛) int userId) { ... }
11. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Define a new model attribute.
Single attribute approach
Multiple attributes approach
» Access existing model attribute.
12. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Definition of a single model attribute
@Controller
public class PrepareFormController
@Override
public ModelAndView prepareForm() {
ModelAndView mav = new ModelAndView("details");
mav.addObject("userDetails", new UserDetails());
mav.addObject("months", createIntegerList(1, 12));
mav.addObject("years", createIntegerList(1940, 2011));
return mav;
}
}
13. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Definition of a single model attribute
@Controller
public class PrepareFormController
@ModelAttribute("userDetails")
public UserDetails newUserDetails() {
return new UserDetails();
}
@ModelAttribute("months")
public int[] getMonthList() {
return new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
}
}
14. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Definition of a single model attribute
@Controller
public class ValidateUserFormController
@RequestMapping(method = RequestMethod.GET)
public String validateForm(HttpServletRequest request, HttpServletResponse ...) {
String firstName = request.getParameter(‚firstName‛);
String lastName = request.getParameter(‚lastName‛);
// ...
}
}
15. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Definition of a single model attribute
@Controller
public class ValidateUserFormController
@RequestMapping(method = RequestMethod.GET)
public String validateForm(@ModelAttribute("userDetails") UserDetails details) {
// ...
}
@ModelAttribute("userDetails")
public UserDetails getUserDetails(HttpServletRequest request) {
UserDetails user = new UserDetails();
user.setFirstName(request.getParameter("firstName"));
return user;
}
}
16. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Definition of a single model attribute
public class UserFormControllerTest {
@Test
public void testValidateForm() {
UserFormController formController = new UserFormController();
UserDetails userDetails = new UserDetails();
// ...
// Simple way to test a method.
String viewName = formController.validateForm(userDetails);
Assert.assertEquals("OK", viewName);
}
}
17. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Definition of a multiple model attribute
@ModelAttribute("months")
public int[] getMonthList() {
return new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
}
@ModelAttribute("months")
public int[] getYears() {
return new int[] { 1940, 1941, ... };
}
@ModelAttribute
public void populateAllAttributes(Model model, HttpServletRequest ...) {
model.addAttribute(‚years", new int[] { ... });
model.addAttribute(‚months", new int[] { ... });
18. Spring MVC – Advanced topics
Annotation driven controllers
@ModelAttribute
» Session attribute binding
@Controller
@SessionAttributes("userDetails");
public class ValidateUserFormController {
// UserDetails instance is extracted from the session.
@RequestMapping(method = RequestMethod.GET)
public String validateForm(@ModelAttribute("userDetails") UserDetails details) {
// ...
}
}
19. Spring MVC – Advanced topics
Annotation driven controllers
@CookieValue, @HeaderValue
» @CookieValue provide access to client-side cookies.
» @HeaderValue provide access to HTTP request header
values.
20. Spring MVC – Advanced topics
Annotation driven controllers
@DateTimeFormat
» Allow conversion of a string to date-class type.
long/java.lang.Long,
java.util.Date, java.sql.Date,
java.util.Calendar,
Joda time
» Applies to @RequstParam and @PathVariable
» Support various conventions.
21. Spring MVC – Advanced topics
Annotation driven controllers
@DateTimeFormat
@Controller
public class CheckDatesRangeController {
// http://host.com/checkDate?birthDate=1975/02/31
@RequestMapping
public String checkDateRange(
@RequestParam("birthdate")
@DateTimeFormat(pattren = "yyyy/mm/dd") Date birthDate) {
// ...
}
}
22. Spring MVC – Advanced topics
Annotation driven controllers
@RequestBody
» Provide access to HTTP request body.
@Controller
public class PersistCommentController {
@RequestMapping(method = RequestMethod.POST)
public String checkDateRange(@RequestBody String contents) {
// ...
}
}
» Also supported:
Byte array, Form, javax.xml.transform.Source
23. Spring MVC – Advanced topics
Annotation driven controllers
@ResponseBody
» Convert return value to HTTP response body.
@Controller
public class FetchCommentController {
@RequestMapping
@ResponseBody
public String fetchComment(@RequestMapping (‚commentId") int commentId) {
// ...
}
@RequestMapping
@ResponseBody
public byte[] fetchAsBinary(@RequestMapping (‚commentId") int commentId) {
// ...
}
}
25. Spring MVC – Advanced topics
Arguments and return types
@Controller
public class SomeController {
@RequestMapping
public String someMethod(...) { ... }
}
Return Arguments
value
26. Spring MVC – Advanced topics
Arguments and return types
Allowed arguments
» HttpServletRequest, HttpServletResponse, HttpSession
Servlet API
» WebRequest, NativeWebRequest
Spring framework API
» java.util.Locale
» java.io.InputStream, java.io.Reader
» java.io.OutputStream, java.io.Writer
27. Spring MVC – Advanced topics
Arguments and return types
Allowed arguments
» java.security.Principle
» HttpEntity
Spring framework API
» java.util.Map, Model, ModelMap
Allow access to the current model.
» Errors, BindingResult
28. Spring MVC – Advanced topics
Arguments and return types
Allowed return types
» ModelAndView, Model, java.util.Map, View
» String
Represents a view name, if not specified otherwise.
» void
» HttpEntity<?>, ResponseEntity<?>
» Any other type that has a conversion.
30. Spring MVC – Advanced topics
Validation
» Allow us to validate form in a discipline manner.
» Provide a convenient and consistent way to validate
input.
» Support JSR-303 (not covered by this presentation).
31. Spring MVC – Advanced topics
Validation
Declaring binding process
@Controller
public class ValidateFormController {
@RequestMapping
public String validateForm(UserDetails details, Errors errors) {
if (details.getFirstName() == null) {
errors.rejectValue("firstName", null, "Missing first name.");
}
}
}
32. Spring MVC – Advanced topics
Validation
Declaring binding process
@Controller
public class ValidateFormController {
@RequestMapping
public String validateForm(UserDetails details, Errors errors) {
ValidationUtils.rejectIfEmpty(errors,
"firstName",
null,
"Missing first name.");
}
}
33. Spring MVC – Advanced topics
Validation
Declaring binding process
<form:form action="form/validate.do" method="POST" modelAttribute="userDetails">
<!-- Prompt for user input -->
First name: <form:input path="firstName" />
<!-- Display errors related to ‘firstName’ field -->
<form:errors path="firstName"/>
</form:form>
34. Spring MVC – Advanced topics
Validation
JSR-303 based validation
» Spring framework support 3rd-party JSR-303
integration.
» Requires additional artifacts JSR-303 spec artifacts.
» Requires RI (reference implementation)
e.g: Hibernate Validation
35. Spring MVC – Advanced topics
Validation
JSR-303 based validation
@RequestMapping
public String validateForm(@Valid UserDetails details, Errors errors) { ... }
public class UserDetails {
@NotNull // JSR-303 annotation.
private String firstName;
@Size(min = 2, max = 64) // JSR-303 annotations.
private String lastName;
@Min(1) @Max(12) // JSR-303 annotations.
private int birthMonth;
}