1 / 30

Spencer Uresk

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 Prerequisites Beginning Spring MVC (and all of its prerequisites). Overview.

veata
Download Presentation

Spencer Uresk

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

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: Request Line GET /view/1 HTTP/1.1 User-Agent: Chrome Accept: application/json [CRLF] Headers POST /save HTTP/1.1 User-Agent: IE Content-Type: application/x-www-form-urlencoded [CRLF] name=x&id=2 Request Line Headers Request Body

  5. HTTP Message (Responses) • Sample Responses HTTP/1.1 200 OK Content-Type: text/html Content-Length: 1337 [CRLF] <html> Some HTML Content. </html> Status Line Headers Response Body HTTP/1.1 500 Internal Server Error Status Line HTTP/1.1 201 Created Location: /view/7 [CRLF] Some message goes here. 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(@RequestBodySomeObject 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 @ResponseBodyStringreadString() {} @RequestMapping("/echo/json") public @ResponseBodySomeObjectreadJson() {}

  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-Typeheaders • 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 @RequestMapping("/echo/string") public @ResponseBody String echoString(@RequestBody String input) { return “Your Text Was: “ + input; } • a POST /echo/string HTTP/1.1 Accept: text/plain Content-Type: text/plain Hello! REQUEST HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 17 Your Text Was: Hello! RESPONSE

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

  14. MappingJacksonHttpMessageConverter public Person { // String name, int age; } @RequestMapping("/echo/json") public @ResponseBodyPerson echoJson(@RequestBodyPerson person) { // Upper case name, square age return person; } • a POST /echo/string HTTP/1.1 Accept: application/json Content-Type: application/json { “name” : “Spencer”, “age” : 5 } REQUEST HTTP/1.1 201 Created Content-Type: application/json { “name” : “SPENCER”, “age” : 25 } 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 @XmlRootElement public Person {// String name, int age;} @RequestMapping("/echo/xml") public @ResponseBodyPerson echoXml(@RequestBodyPerson person) { // Upper case name, square age return person; } • a POST /echo/string HTTP/1.1 Accept: application/xml Content-Type: application/xml <thing><name>Spencer</name><age>5</age></thing> REQUEST HTTP/1.1 201 Created Content-Type: application/xml <thing><name>SPENCER</name><age>25</age></thing> RESPONSE

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

  18. ByteArrayHttpMessageConverter @RequestMapping("/echo/string") public @ResponseBody String echoString(@RequestBody byte[] input) { return new String(input); } • a POST /echo/string HTTP/1.1 Accept: text/plain Content-Type: text/plain Hello! REQUEST HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: 6 Hello! 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(@RequestBodyString 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<String> upload(HttpEntity<byte[]> rEntity) { String t = rEntity.getHeaders().getFirst(“Content-Type”); byte[] data = rEntity.getBody(); // Save the file HttpHeadersresponseHeaders = new HttpHeaders(); responseHeaders.set(“Location”, “/image/1”); return new ResponseEntity<String>(“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 AnExceptionHandlerextends AbstractHandlerExceptionResolver{ protected ModelAndViewdoResolveException( 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 <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key=".DataAccessException">errors/dataAccessFailure</prop> <prop key=".AccessDeniedException">errors/dataAccessFailure</prop> <prop key=".TypeMismatchException">errors/resourceNotFound</prop> </props> </property> <property name="defaultErrorView" value="errors/generalError"/> <property name="warnLogCategory" value="org.lds.stack"/> </bean>

  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(DataAccessExceptionex) {} @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

More Related