Chengyu Sun California State University, Los Angeles CS5220 Advanced Topics in Web Programming Spring – RESTful Web Service Implementation Chengyu Sun California State University, Los Angeles
The SpringREST Example REST API Using Spring and Hibernate https://csns.calstatela.edu/wiki/content/cysun/course_materials/cs5220/spring-rest/
Comparison with Spring MVC No more views @RestControler = @Controller + @ResponseBody Message Converter using Jackson Many many other things stay the same Beans, data access, @RequestMapping, @PathVariable …
Serialization/Marshalling and Deserialization/Unmarshalling Java Object XML/JSON De-serialization/ Un-marshalling
Serialization/Deserialization in Spring @RequestBody @ResponseBody void: empty response body + Status 200 Message converters Java object request/response body When multiple converters are configured, Spring automatically choose which one to use based on Accept and/or Content-Type headers
HTTP Request Example POST /users HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 ... Accept: application/xml Accept-Encoding: gzip,deflate Accept-Charset: utf-8 Content-Type: application/json Content-Length: … {“firstName”: “John”, “lastName”: “Doe”, “email”: “jdoe@localhost”} Request Line Headers Body (Optional)
HTTP Response Example HTTP/1.1 200 OK Status Line Content-Type: application/json Content-Length: … Date: Sun, 03 Oct 2017 18:26:57 GMT Server: Apache-Coyote/1.1 { “id”: 100, “firstName”: “John”, “lastName”: “Doe”, “email”: “jdoe@localhost”, “enabled”: true} Status Line Headers Body (Optional)
More About @RequestMapping Be careful with the URL pattern Additional attributes method headers consumes produces
@RequestMapping Examples @RequestMapping(value=“/users” consumes=“application/json”) Map the request to the method if the request’s Content-Type header is “application/json” @RequestMapping(value=“/users” produces=“application/json”) Map the request to the method if the request’s Accept header is “application/json”. Set the Content-Type header of the response to “application/json”.
More About REST API Implementation Customize serialization/deserialization using Jackson annotations Handling errors and exceptions Testing
Serialization/Deserialization: Excluding Fields Example: excluding password field from JSON response
Jackson Annotations (I) @JsonIgnore @JsonIgnoreProperties value, e.g. {“password”, “enabled”} allowGetters allowSetters ignoreUnknown @JsonProperty value access, e.g. Access.WRITE_ONLY
Serialization/Deserialization: Handling Object Reference Example: bi-directional association between User and Role
Adapt Model Design to Application Needs Is bi-directional mapping necessary? Determine the right amount of data included in a response Example: User, Role, Ticket, Update
Jackson Annotations (II) @JsonManagedReference and @JsonBackReference for bidirectional association @JsonIdentityInfo handles multiple references to the same object generator = ObjectIdGenerators.PropertyGenerator.class property, e.g. id
Serialization/Deserialization: Value Object Example: add a User with the ADMIN role
Jackson Annotations (III) @JsonValue indicates the property that will be used as the “value” of the object during serialization. @JsonCreator creates an object from a value during deserialization.
Errors and Exceptions Expected errors, e.g. login failure, missing required fields, … need to inform client to correct the error Unexpected errors, i.e. exceptions need to log problems for analysis and fix Error pages and redirects are not suitable for RESTful web services
Error Information for the Client Status code, e.g. 401 Error message (Optional) application-specific error code
How to Send Back Error Information? @RequestMapping(value = "/users", method = RequestMethod.POST) public User addUser( @RequestBody User user ) { if( user.username == null || user.password == null ) { ?? } return userDao.saveUser( user ); // database exception??
Problem with Java Exceptions Too many checked exceptions Checked vs. Runtime exceptions Require lots of boilerplate exception handling code
Spring’s Solution to the Exception Problem Use primarily runtime exceptions Separate exception handling code into exception handlers using AOP
Per-Controller Exception Handler Methods public class SomeController { … … @ExceptionHandler(RestException.class) public ResponseEntity<Object> handleRestExceptions( RestException ex ) { … } @ExceptionHandler(Exception.class) handleOtherExceptions( Exception ex ) { … } }
Global Exception Handling Using @ControllerAdvice public class SomeControllerAdvice { @ExceptionHandler(RestException.class) public ResponseEntity<Object> handleRestExceptions( RestException ex ) { … } @ExceptionHandler(Exception.class) handleOtherExceptions( Exception ex ) { … } }
Putting It Together Error Exception Response Exception Handler An Error class that contains the information to be sent back to client. Additional exception classes can be created for different types of errors. Response Exception Handler A response to client is created using ResponseEntity Different exceptions can be mapped to different exception handlers
Logging Record events happened during software execution During development During production
Requirements of Good Logging Tools Support different message levels Fatal, error, warn, info, debug, trace Minimize performance penalty Support different log output Console, file, database, … Easy configuration
Java Logging Libraries Logging implementations Log4j - http://logging.apache.org/log4j/ java.util.logging in JDK Logging API Apache Commons Logging (JCL) - http://commons.apache.org/logging/ Simple Logging Façade for Java (SLF4J) - http://www.slf4j.org/
Log4j Examples Log4j 1 with SLF4J – Logging Examples Log4j 2 – Spring REST
Appender and Logger Apender Logger Output type, e.g. console, file, database … Ouput format, i.e. layout Logger Package and/or class selection Message level
Testing REST API Manual testing with Postman Automated testing with an application server and an HTTP client (e.g. HttpClient) Automated testing without an application server
Dependencies for MockMvc org.springframework:spring-test A unit testing framework like JUnit or TestNG Additional JSON response testing JsonPath for traversing a JSON object Hamcrest for matchers
Example: UserControllerTest Create a MockMvc Build requests using MockMvcRequestBuilders Use ResultMatchers to check the response Basic Spring ResultMatchers Additional JSON response testing using JsonPath and Hamcrest Matchers