Presentation is loading. Please wait.

Presentation is loading. Please wait.

Spring MVC Part 2 Spencer Uresk. Notes This is a training, NOT a presentation Please ask questions This is being recorded https://tech.lds.org/wiki/Java_Stack_Training.

Similar presentations


Presentation on theme: "Spring MVC Part 2 Spencer Uresk. Notes This is a training, NOT a presentation Please ask questions This is being recorded https://tech.lds.org/wiki/Java_Stack_Training."— Presentation transcript:

1 Spring MVC Part 2 Spencer Uresk

2 Notes This is a training, NOT a presentation Please ask questions This is being recorded https://tech.lds.org/wiki/Java_Stack_Training Prerequisites – Beginning Spring MVC (and all of its prerequisites)

3 Overview Last time, we showed how to map requests to handler methods, get information about the request, and how to pass information back to the view We’ll see what an HTTP message looks like This week, we’ll look at some of Spring MVC’s RESTful features, including RequestBody, ResponseBody, HttpMessageConverters, HttpEntity objects, and dealing with exceptions These are useful for RESTful web services and normal form-based interactions

4 HTTP Message What does an HTTP message look like? Sample Requests: GET /view/1 HTTP/1.1 User-Agent: Chrome Accept: application/json [CRLF] POST /save HTTP/1.1 User-Agent: IE Content-Type: application/x-www-form-urlencoded [CRLF] name=x&id=2 Request Line Headers Request Line Headers Request Body

5 HTTP Message (Responses) Sample Responses HTTP/1.1 200 OK Content-Type: text/html Content-Length: 1337 [CRLF] Some HTML Content. HTTP/1.1 500 Internal Server Error HTTP/1.1 201 Created Location: /view/7 [CRLF] Some message goes here. Status Line Headers Response Body Status Line Headers Response Body

6 RequestBody Annotating a handler method parameter with @RequestBody will bind that parameter to the request body @RequestMapping("/echo/string") public void writeString(@RequestBody String input) {} @RequestMapping("/echo/json") public void writeJson(@RequestBody SomeObject input) {}

7 ResponseBody Annotating a return type with @ResponseBody tells Spring MVC that the object returned should be treated as the response body No view is rendered in this case @RequestMapping("/echo/string") public @ResponseBody String readString() {} @RequestMapping("/echo/json") public @ResponseBody SomeObject readJson() {}

8 HttpMessageConverters How does Spring MVC know how to turn a JSON string into SomeObject, or vice-versa? HttpMessageConverters These are responsible for converting a request body to a certain type, or a certain type into a response body Spring MVC figures out which converter to use based on Accept and Content-Type headers, and the Java type Your Accept and Content-Type headers DON’T have to match. For example, you can send in JSON and ask for XML back

9 HttpMessageConverters A number of HttpMessageConverters are already provided You can define your own, but that is outside the scope of this training You don’t specify which ones are used to convert request/response bodies – they are selected based on the Content-Type/Accept headers

10 MIME Types HttpMessageConverters make heavy use of MIME types (RFC 2046) These are the value for Accept and Content-Type headers Two-part identifier for content formats First part is the type. ie, application Second part is the sub-type. ie, json application/json

11 StringHttpMessageConverter Reads and writes Strings. Reads text/* Writes text/plain

12 StringHttpMessageConverter a POST /echo/string HTTP/1.1 Accept: text/plain Content-Type: text/plain Hello! @RequestMapping("/echo/string") public @ResponseBody String echoString(@RequestBody String input) { return “Your Text Was: “ + input; } HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 17 Your Text Was: Hello! REQUEST RESPONSE

13 MappingJacksonHttpMessageConverter Maps to/from JSON objects using the Jackson library Reads application/json Writes application/json

14 MappingJacksonHttpMessageConverter a POST /echo/string HTTP/1.1 Accept: application/json Content-Type: application/json { “name” : “Spencer”, “age” : 5 } public Person { // String name, int age; } @RequestMapping("/echo/json") public @ResponseBody Person echoJson(@RequestBody Person person) { // Upper case name, square age return person; } HTTP/1.1 201 Created Content-Type: application/json { “name” : “SPENCER”, “age” : 25 } REQUEST RESPONSE

15 Jaxb2RootElementHttpMessageConverter Maps to/from XML objects Must have your object at least annotated with @XmlRootElement Reads text/xml, application/xml Writes text/xml, application/xml

16 Jaxb2RootElementHttpMessageConverter a POST /echo/string HTTP/1.1 Accept: application/xml Content-Type: application/xml Spencer 5 @XmlRootElement public Person {// String name, int age;} @RequestMapping("/echo/xml") public @ResponseBody Person echoXml(@RequestBody Person person) { // Upper case name, square age return person; } HTTP/1.1 201 Created Content-Type: application/xml SPENCER 25 REQUEST RESPONSE

17 ByteArrayHttpMessageConverter Can read/write byte arrays (useful for dealing with binary data, such as images) Reads */* Writes application/octet-stream

18 ByteArrayHttpMessageConverter a POST /echo/string HTTP/1.1 Accept: text/plain Content-Type: text/plain Hello! @RequestMapping("/echo/string") public @ResponseBody String echoString(@RequestBody byte[] input) { return new String(input); } HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: 6 Hello! REQUEST RESPONSE

19 Lab 1 Create a handler that takes a request body and echoes it back. Create a handler that takes a request body, creates an object with it, and returns it as JSON. Create a handler that takes an XML input and echoes it back as JSON. Test all of these with your HttpClient

20 Other parts of the HTTP Message What if you need to get/set headers? Or set the status code? @RequestMapping("/echo/string") public @ResponseBody String echoString(@RequestBody String input, HttpServletRequest request, HttpServletResponse response) { String requestType = request.getHeader(“Content-Type”); response.setHeader(“Content-Type”, “text/plain”); response.setStatus(200); return input }

21 @ResponseStatus There is a convenient way to set what the default status for a particular handler should be @ResponseStatus @RequestMapping("/create") @ResponseStatus(HttpStatus.CREATED) // CREATED == 201 public void echoString(String input) { }

22 HttpEntity Convenience class for dealing with bodies, headers, and status Converts messages with HttpMessageConverters @RequestMapping("/image/upload") public ResponseEntity upload(HttpEntity rEntity) { String t = rEntity.getHeaders().getFirst(“Content-Type”); byte[] data = rEntity.getBody(); // Save the file HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set(“Location”, “/image/1”); return new ResponseEntity (“Created”, responseHeaders, HttpStatus.CREATED); }

23 Lab 2 Convert all your String controller method to use HttpEntity Convert the Create Person controller method to use an HttpEntity. Also, return a Location header and a 201 (Created) response code.

24 Dealing with exceptions By default, Spring MVC will map certain exceptions to status codes You can implement your own HandlerExceptionResolver, which takes an exception and returns a ModelAndView You can register a SimpleMappingExceptionResolver to map exceptions to views You can annotate methods in the controller to handle specific exceptions

25 Default Exception Mappings These take effect if you have no other configuration ConversionNotSupportedException => 500 NoSuchMethodHandlingException => 404 MissingServletRequestParameterException => 400 HttpRequestMethodNotSupportedException => 405 TypeMismatchException => 400 HttpMediaTypeNotSupportedException => 415 HttpMediaTypeNotAcceptableException => 406

26 HandlerExceptionResolver Allows you to control how exceptions are resolved Implement HandlerExceptionResolver (but you’ll probably extend AbstractHandlerExceptionResolver) class AnExceptionHandler extends AbstractHandlerExceptionResolver { protected ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("I got an error."); return new ModelAndView("errors/someError"); }

27 SimpleMappingExceptionResolver Allows you to simply map exceptions to views This is how the Stack comes configured errors/dataAccessFailure errors/resourceNotFound

28 @ExceptionHandler Create a method to handle the exception, annotate it with @ExceptionHandler, and pass in the exception(s) that method can handle ExceptionHandler methods look a lot like normal handler methods @RequestMapping("/error") public void doSomething() { throw new RecoverableDataAccessException("Unable to access that database."); } @ExceptionHandler(DataAccessException.class) public @ResponseBody String handleDataAccessError(DataAccessException ex) { return ex.getMessage(); }

29 @ResponseStatus We saw this annotation earlier It can also be placed on Exception classes or @ExeptionHandler methods to return a specific status code for a particular exception @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(DataAccessException.class) public void handleDataAccessError(DataAccessException ex) {} @ResponseStatus(value = HttpStatus.PAYMENT_REQUIRED, message = “I need money.”) public class PaymentRequiredException {}

30 Lab 3 Look at the SimpleMappingExceptionResolver already configured in your project Create a controller that throws one of those exceptions and verify that your request gets redirected to the corresponding view Remove the config, and change your exception to HttpMediaTypeNotSupportedException. Verify that you get a 415 using your Http Client Implement an @ExceptionHandler method


Download ppt "Spring MVC Part 2 Spencer Uresk. Notes This is a training, NOT a presentation Please ask questions This is being recorded https://tech.lds.org/wiki/Java_Stack_Training."

Similar presentations


Ads by Google