4.13. Ajax¶
Caution
This version is already obsolete. Please check the latest guideline.
Table of contents
4.13.1. Overview¶
This section explains how to implement applications that use Ajax.
Todo
TBD
Details regarding client side implementation etc. will follow in subsequent versions.
Ajax is the generic term used for group of techniques that perform the following asynchronous processes.
- Screen operations performed on the browser
- HTTP communication with the server triggered by a screen operation and reflecting back the communication results to the user interface
4.13.2. How to use¶
4.13.2.1. Application settings¶
Application settings for Ajax are explained below.
Warning
DoS attack measures at the time of StAX(Streaming API for XML) use
If the StAX is used to parse the XML format data, protect DoS attack. For details, refer to CVE-2015-3192 - DoS Attack with XML Input.
4.13.2.1.1. Settings to enable the Ajax functionality in Spring MVC¶
Content-Type (such as "application/xml", "application/json" etc.) used in Ajax communication is set such that it can be handled by the handler method of Controller.
spring-mvc.xml
<mvc:annotation-driven /> <!-- (1) -->
Sr. No. Description (1) If<mvc:annotation-driven>element is specified, the functionality required for Ajax communication is enabled.Therefore, special settings are not necessary for Ajax communication.Note
Functionalities required for Ajax communication specifically refer to the ones provided by
org.springframework.http.converter.HttpMessageConverterclass.
HttpMessageConverterperforms the following roles.
- Creating Java object from data stored in the request body.
- Creating the data to be written to the response Body from Java object.
The HttpMessageConverter which is enabled by default on specifying <mvc:annotation-driven>, is as follows.
Sr. No. Class name TargetFormat Description
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter JSONHttpMessageConverterto handle JSON as request body or response body.Jackson system is included in the blank project. Hence, it can be used in its default state.
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter XMLHttpMessageConverterto handle XML as request body or response body.JAXB2.0 is included as standard from JavaSE6. Hence it can be used in its default state.Note
Notice If you change from jackson version 1.xx to jackson version 2.xx, refer to here.
Warning
XXE (XML External Entity) Injection measures
When handling XML format data in Ajax communication, it is necessary to implement XXE(XML External Entity) Injection measure. Subsequent versions above terasoluna-gfw-web 1.0.1.RELEASE are Spring MVC (above 3.2.10.RELEASE) version dependent. As these Spring MVC versions implement XXE Injection measures, it is not necessary to implement them independently.
When using terasoluna-gfw-web 1.0.0.RELEASE, since it is dependent on the Spring MVC version (3.2.4.RELEASE) that does not implement XXE Injection, a class provided by Spring-oxm should be used.
spring-mvc.xml<!-- (1) --> <bean id="xmlMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="packagesToScan" value="com.examples.app" /> <!-- (2) --> </bean> <!-- ... --> <mvc:annotation-driven> <mvc:message-converters> <!-- (3) --> <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <property name="marshaller" ref="xmlMarshaller" /> <!-- (4) --> <property name="unmarshaller" ref="xmlMarshaller" /> <!-- (5) --> </bean> </mvc:message-converters> <!-- ... --> </mvc:annotation-driven> <!-- ... -->
Sr. No. Description (1) Perform the bean definition ofJaxb2Marshallerprovided by Spring-oxm.Jaxb2Marshallerimplements the XXE Injection measures in default state. (2) Specify the package name where the JAXB JavaBean (JavaBean assigned withjavax.xml.bind.annotation.XmlRootElementannotation ) is stored in thepackagesToScanproperty.JAXB JavaBean stored under the specified package is scanned and registered for marshalling or unmarshalling the JavaBean.It is scanned in the same way as the base-package attribute of<context:component-scan>. (3) Add bean definition ofMarshallingHttpMessageConverterto the<mvc:message-converters>element that is the child element of<mvc:annotation-driven>. (4) Specify the bean ofJaxb2Marshallerdefined in (1) inmarshallerproperty. (5) Specify the bean ofJaxb2Marshallerdefined in (1) inunmarshallerproperty.Adding Spring-oxm as dependent artifact.
pom.xml<!-- omitted --> <!-- (1) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${org.springframework-version}</version> <!-- (2) --> </dependency> <!-- omitted -->
Sr. No. Description (1) Add Spring-oxm as dependent artifact. (2) Spring version should be fetched from the placeholder (${org.springframework-version}) that controls the Spring version number defined inpom.xmlof terasoluna-gfw-parent.
4.13.2.2. Implementing Controller¶
Prerequisites for the sample code explained hereafter, are as follows.
- Response data should be in JSON format.
- JQuery should be used at client side. It should be the latest version of 1.x series (1.10.2), which is used while writing this document.
Warning
Measures to circular reference
When you serialize a JavaBean in JSON or XML format using HttpMessageConverter and
if property holds an object of cross reference relationship,
the StackOverflowError and OutOfMemoryError occur due to circular reference, hence it is necessary to exercise caution.
In order to avoid a circular reference,
@com.fasterxml.jackson.annotation.JsonIgnoreannotation to exclude the property from serialization in case of serialized in JSON format using the Jackson@javax.xml.bind.annotation.XmlTransientannotation to exclude the property from serialization in case of serialized in XML format using the JAXB
can be added.
Below is the example of how to exclude specific field from serialization while serializing in JSON format using the Jackson.
public class Order { private String orderId; private List<OrderLine> orderLines; // ... }public class OrderLine { @JsonIgnore private Order order; private String itemCode; private int quantity; // ... }
Sr. No. Description (1)The @JsonIgnoreannotation is added to exclude the property from serialization.
4.13.2.2.1. Fetching data¶
How to fetch data using Ajax is explained here.
Following example serves as the Ajax communication that returns a list matching with the search word.
- JavaBean for receiving request data
// (1) public class SearchCriteria implements Serializable { // omitted private String freeWord; // (2) // omitted setter/getter }
Sr. No. Description (1) Create the JavaBean that receives request data. (2) Match property name with parameter name of request parameter.
- JavaBean for storing the data to be returned
// (3) public class SearchResult implements Serializable { // omitted private List<XxxEntity> list; // omitted setter/getter }
Sr. No. Description (3) Create the JavaBean for storing the data to be returned.
- Controller
@RequestMapping(value = "search", method = RequestMethod.GET) // (4) @ResponseBody // (5) public SearchResult search(@Validated SearchCriteria criteria) { // (6) SearchResult searchResult = new SearchResult(); // (7) // (8) // omitted return searchResult; // (9) }
Sr. No. Description (4) SpecifyRequestMethod.GETin the method attribute of@RequestMappingannotation. (5) Assign@org.springframework.web.bind.annotation.ResponseBodyannotation.By assigning this annotation, the returned object is marshalled in JSON format and set in response body. (6) Specify the JavaBean that receives request data, as an argument.If input validation is required, specify@Validated. For error handling of input validation, refer to “Input error handling”.For details on input validation, refer to “Input Validation”. (7) Create the JavaBean object to store the data to be returned. (8) Search data and store the search result in the object created in (7).In the above example, implementation is omitted. (9) Return the object to be marshalled in response body.
- HTML(JSP)
<!-- omitted --> <meta name="contextPath" content="${pageContext.request.contextPath}" /> <!-- omitted --> <!-- (10) --> <form id="searchForm"> <input name="freeWord" type="text"> <button onclick="return searchByFreeWord()">Search</button> </form>
Sr. No. Description (10) Form to enter the search condition.In the above example, it has a text box to enter the search condition and a search button.<!-- (11) --> <script type="text/javascript" src="${pageContext.request.contextPath}/resources/vendor/jquery/jquery-1.10.2.js"> </script>
Sr. No. Description (11) Read the JQuery JavaScript file.In the above example, request is sent to the/resources/vendor/jquery/jquery-1.10.2.jspath, to read the JQuery JavaScript file.Note
Refer to the settings below to read JQuery JavaScript file. Setting values provided in the blank project are as follows.
spring-mvc.xml<!-- (12) --> <mvc:resources mapping="/resources/**" location="/resources/,classpath:META-INF/resources/" cache-period="#{60 * 60}" />
Sr. No. Description (12) Settings for releasing resource files (JavaScript files, Stylesheet files, image files etc.).In the above setting example, when there is a request for path starting with/resources/, the files in/resources/directory of war file or the/META-INF/resources/directory of class path are sent as a response.In the above settings, the JQuery JavaScript file needs to be placed under any one of the following paths.
/resources/vendor/jquery/jquery-1.10.2.jsin war fileIt issrc/main/webapp/resources/vendor/jquery/jquery-1.10.2.jswhen indicated by the path in the project./META-INF/resources/vendor/jquery/jquery-1.10.2.jsin class pathIt issrc/main/resources/META-INF/resources/vendor/jquery/jquery-1.10.2.jswhen indicated by the path in the project.
- JavaScript
var contextPath = $("meta[name='contextPath']").attr("content"); // (13) function searchByFreeWord() { $.ajax(contextPath + "/ajax/search", { type : "GET", data : $("#searchForm").serialize(), dataType : "json", // (14) }).done(function(json) { // (15) // render search result // omitted }).fail(function(xhr) { // (16) // render error message // omitted }); return false; }
Sr. No. Description (13) Ajax function that converts search criteria specified in the form to request parameter and sends the request for /ajax/search using GET method.In the above example, clicking the button acts as the trigger for Ajax communication. However, by setting key down or key up of text box as the trigger, real time search can be performed. (14) Specify the data format to be received as a response.In the above example, as"json"is specified,"application/json"is set in Accept header. (15) Implement the process when Ajax communication ends normally (when Http status code is"200").In the above example, implementation is omitted. (16) Implement the process when Ajax communication does not end normally (when Http status code is"4xx"and"5xx").In the above example, implementation is omitted.For error process implementation, refer to Posting form data.Tip
In the above example, by setting context path (
${pageContext.request.contextPath}) of Web application in HTML``<meta>`` element. JSP code is deleted from JavaScript code.
- Request data
GET /terasoluna-gfw-web-blank/ajax/search?freeWord= HTTP/1.1 Host: localhost:9999 Connection: keep-alive Accept: application/json, text/javascript, */*; q=0.01 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 Referer: http://localhost:9999/terasoluna-gfw-web-blank/ajax/xxe Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,ja;q=0.6 Cookie: JSESSIONID=3A486604D7DEE62032BA6C073FC6BE9F
- Response data
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Track: a8fb8fefaaf64ee2bffc2b0f77050226 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Fri, 25 Oct 2013 13:52:55 GMT {"list":[]}
4.13.2.2.2. Posting form data¶
How to post form data and fetch processing result using Ajax, is explained here.
Following example is about the Ajax communication of receiving two numbers and returning the calculation result.
- JavaBean to receive form data
// (1) public class CalculationParameters implements Serializable { // omitted private Integer number1; private Integer number2; // omitted setter/getter }
Sr. No. Description (1) Create the JavaBean for receiving form data.
- JavaBean that stores processing result
// (2) public class CalculationResult implements Serializable { // omitted private int resultNumber; // omitted setter/getter }
Sr. No. Description (2) Create the JavaBean that stores processing result.
- Controller
@RequestMapping("xxx") @Controller public class XxxController { @RequestMapping(value = "plusForForm", method = RequestMethod.POST) // (3) @ResponseBody public CalculationResult plusForForm( @Validated CalculationParameters params) { // (4) CalculationResult result = new CalculationResult(); int sum = params.getNumber1() + params.getNumber2(); result.setResultNumber(sum); // (5) return result; // (6) } // omitted }
Sr. No. Description (3) SpecifyRequestMethod.POSTin the method attribute of@RequestMappingannotation. (4) Specify the JavaBean for receiving form data as an argument.Specify@Validatedwhen input validation is required. For handling input validation errors, refer to “Input error handling”.For details on input validation, refer to “Input Validation”. (5) Store the processing result in the object created for the same.In the above example, calculation result of the two numbers fetched from form object, is stored. (6) Return the object to perform marshalling in response body.
- HTML (JSP)
<!-- omitted --> <meta name="contextPath" content="${pageContext.request.contextPath}" /> <sec:csrfMetaTags /> <!-- omitted --> <!-- (7) --> <form id="calculationForm"> <input name="number1" type="text">+ <input name="number2" type="text"> <button onclick="return plus()">=</button> <span id="calculationResult"></span> <!-- (8) --> </form>
Sr. No. Description (7) Form to enter the numerical value to be calculated. (8) Area to display calculation result.In the above example, calculation result is displayed when communication is successful and it is cleared when the communication fails.
- JavaScript
var contextPath = $("meta[name='contextPath']").attr("content"); // (9) var csrfToken = $("meta[name='_csrf']").attr("content"); var csrfHeaderName = $("meta[name='_csrf_header']").attr("content"); $(document).ajaxSend(function(event, xhr, options) { xhr.setRequestHeader(csrfHeaderName, csrfToken); }); // (10) function plus() { $.ajax(contextPath + "/ajax/plusForForm", { type : "POST", data : $("#calculationForm").serialize(), dataType : "json" }).done(function(json) { $("#calculationResult").text(json.resultNumber); }).fail(function(xhr) { // (11) var messages = ""; // (12) if(400 <= xhr.status && xhr.status <= 499){ // (13) var contentType = xhr.getResponseHeader('Content-Type'); if (contentType != null && contentType.indexOf("json") != -1) { // (14) json = $.parseJSON(xhr.responseText); $(json.errorResults).each(function(i, errorResult) { messages += ("<div>" + errorResult.message + "</div>"); }); } else { // (15) messages = ("<div>" + xhr.statusText + "</div>"); } }else{ // (16) messages = ("<div>" + "System error occurred." + "</div>"); } // (17) $("#calculationResult").html(messages); }); return false; }
Sr. No. Description (9) To send the request using POST method, CSRF token needs to be set to HTTP header.In the above example, the header name and token value are set in the<meta>element of HTML and value is fetched by JavaScript.For details on CSRF measures, refer to CSRF Countermeasures. (10) Ajax function that converts the numerical value specified in form, to request parameter and sends the request for/ajax/plusForFormusing POST method.In the above example, clicking the button acts as the trigger for Ajax communication however, real time calculation can be implemented by setting lost focus of the text box as the trigger. (11) Implementation of error handling is shown below.For server side implementation of error handling, refer to Input error handling. (12) Determine the HTTP status code and type of error.HTTP status code is stored in thestatusfield of XMLHttpRequest object. (13) Check whether the response data is in JSON format.In the above example, response data format is checked by referring to the value set in the Content-Type of response header.If the format is not checked and if it a format other than JSON, an error occurs while deserializing to JSON object.If error handling is performed easily at the server side, page may be returned in HTML format. (14) Deserialize the response data in JSON object.Response data is stored in theresponseTextfield of XMLHttpRequest object.In the above example, error information is fetched from the deserialized JSON object and error message is created. (15) Perform the process when the response data is not in JSON format.In the above example, HTTP status text is stored in the error message.HTTP status text is stored in thestatusTextfield of XMLHttpRequest object. (16) Perform the process when there is a server error.In the above example, message notifying it as a system error is stored in error message. (17) Perform rendering process when there is an error.In the above example, error message is displayed in the area for displaying calculation result.Warning
In the above example, processes namely, Ajax communication, DOM operation (rendering) and error handling are performed by the same function. It is recommended to split and implement these processes.
Todo
TBD
Implementation at client side will be explained in detail, in subsequent versions.
Tip
In the above example, JSP code is deleted from JavaScript code by setting CSRF token value and CSRF token header name, in the
<meta>element of HTML using<sec:csrfMetaTags />. Please refer, Coordination while using Ajax.Please note that, CSRF token value and name of CSRF token header can also be fetched by using
${_csrf.token}and${_csrf.headerName}respectively.
- Request data
POST /terasoluna-gfw-web-blank/ajax/plusForForm HTTP/1.1 Host: localhost:9999 Connection: keep-alive Content-Length: 19 Accept: application/json, text/javascript, */*; q=0.01 Origin: http://localhost:9999 X-CSRF-TOKEN: a5dd1858-8a4f-4ecc-88bd-a326388ab5c9 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Referer: http://localhost:9999/terasoluna-gfw-web-blank/ajax/xxe Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,ja;q=0.6 Cookie: JSESSIONID=3A486604D7DEE62032BA6C073FC6BE9F number1=1&number2=2
- Response data
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Track: c2d5066d0fa946f584536775f07d1900 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Fri, 25 Oct 2013 14:27:55 GMT {"resultNumber":3}
- Response data in case of an input error
HTTP/1.1 400 Bad Request Server: Apache-Coyote/1.1 X-Track: cecd7b4d746249178643b7110b0eaa74 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 04 Dec 2013 15:06:01 GMT Connection: close {"errorResults":[{"code":"NotNull","message":"\"number2\"maynotbenull.","itemPath":"number2"},{"code":"NotNull","message":"\"number1\"maynotbenull.","itemPath":"number1"}]}
4.13.2.2.3. Posting form data in JSON format¶
How to fetch processing result by converting form data to JSON format and subsequently posting it using Ajax, is explained here.
Difference between this method and “Posting form data” method, is explained.
- Controller
@RequestMapping("xxx") @Controller public class XxxController { @RequestMapping(value = "plusForJson", method = RequestMethod.POST) @ResponseBody public CalculationResult plusForJson( @Validated @RequestBody CalculationParameters params) { // (1) CalculationResult result = new CalculationResult(); int sum = params.getNumber1() + params.getNumber2(); result.setResultNumber(sum); return result; } // omitted }
Sr. No. Description (1) Assign@org.springframework.web.bind.annotation.RequestBodyas the argument annotation of JavaBean for receiving form data.By assigning this annotation, data in JSON format stored in the request body is unmarshalled and converted to object.Specify@Validatedwhen input validation is required. For error handling of input validation, refer to “Input error handling”.For details on input validation, refer to Input Validation.
- JavaScript/HTML (JSP)
// (2) function toJson($form) { var data = {}; $($form.serializeArray()).each(function(i, v) { data[v.name] = v.value; }); return JSON.stringify(data); } function plus() { $.ajax(contextPath + "/ajax/plusForJson", { type : "POST", contentType : "application/json;charset=utf-8", // (3) data : toJson($("#calculationForm")), // (2) dataType : "json", beforeSend : function(xhr) { xhr.setRequestHeader(csrfHeaderName, csrfToken); } }).done(function(json) { $("#calculationResult").text(json.resultNumber); }).fail(function(xhr) { $("#calculationResult").text(""); }); return false; }
Sr. No. Description (2) Function to change form input field to JSON string format. (3) Change the media type of Content-Type to"application/json"as the data stored in request body is in JSON format.
- Request data
POST /terasoluna-gfw-web-blank/ajax/plusForJson HTTP/1.1 Host: localhost:9999 Connection: keep-alive Content-Length: 31 Accept: application/json, text/javascript, */*; q=0.01 Origin: http://localhost:9999 X-CSRF-TOKEN: 9d4f1e0c-c500-43f3-9125-a7a131ff88fa X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 Content-Type: application/json;charset=UTF-8 Referer: http://localhost:9999/terasoluna-gfw-web-blank/ajax/xxe? Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,ja;q=0.6 Cookie: JSESSIONID=CECD7A6CB0431266B8D1173CCFA66B95 {"number1":"34","number2":"56"}
4.13.2.3. Input error handling¶
How to perform error handling when an incorrect input value is specified, is explained here.
Input error handling methods are widely classified into the following.
- Method that performs error handling by providing an exception handling method.
- Method that performs error handling by receiving
org.springframework.validation.BindingResultas an argument of Controller handler method.
4.13.2.3.1. Handling BindException¶
org.springframework.validation.BindException is an exception class generated when an incorrect input value is specified while sending the data as request parameter for binding to JavaBean."application/x-www-form-urlencoded" format, exception handling of BindException class needs to be performed.- Controller
@RequestMapping("xxx") @Controller public class XxxController { // omitted @ExceptionHandler(BindException.class) // (1) @ResponseStatus(value = HttpStatus.BAD_REQUEST) // (2) @ResponseBody // (3) public ErrorResults handleBindException(BindException e, Locale locale) { // (4) // (5) ErrorResults errorResults = new ErrorResults(); for (FieldError fieldError : e.getBindingResult().getFieldErrors()) { errorResults.add(fieldError.getCode(), messageSource.getMessage(fieldError, locale), fieldError.getField()); } for (ObjectError objectError : e.getBindingResult().getGlobalErrors()) { errorResults.add(objectError.getCode(), messageSource.getMessage(objectError, locale), objectError.getObjectName()); } return errorResults; } // omitted }
Sr. No. Description (1) Define the error handling method in Controller.Assign@org.springframework.web.bind.annotation.ExceptionHandlerannotation to the error handling method and specify the exception type to be handled in the value attribute.In the above example,BindException.classis specified as the exception for binding. (2) Specify the HTTP status information sent as response.In the above example,400(Bad Request) is specified. (3) Assign@ResponseBodyannotation to write the returned object in response body. (4) Declare the exception class to be handled as an argument of the error handling method. (5) Implement error handling.In the above example, a JavaBean is created to return the error information.Tip
Locale object can be received as an argument while creating a message for error handling by considering internationalization.
- JavaBean storing the error information
// (6) public class ErrorResult implements Serializable { private static final long serialVersionUID = 1L; private String code; private String message; private String itemPath; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getItemPath() { return itemPath; } public void setItemPath(String itemPath) { this.itemPath = itemPath; } }// (7) public class ErrorResults implements Serializable { private static final long serialVersionUID = 1L; private List<ErrorResult> errorResults = new ArrayList<ErrorResult>(); public List<ErrorResult> getErrorResults() { return errorResults; } public void setErrorResults(List<ErrorResult> errorResults) { this.errorResults = errorResults; } public ErrorResults add(String code, String message) { ErrorResult errorResult = new ErrorResult(); errorResult.setCode(code); errorResult.setMessage(message); errorResults.add(errorResult); return this; } public ErrorResults add(String code, String message, String itemPath) { ErrorResult errorResult = new ErrorResult(); errorResult.setCode(code); errorResult.setMessage(message); errorResult.setItemPath(itemPath); errorResults.add(errorResult); return this; } }
Sr. No. Description (6) JavaBean to store one record of error information. (7) JavaBean to store multiple JavaBeans, each of which stores one record of error information.JavaBeans mentioned in (6) are stored as a list.
4.13.2.3.2. Handling MethodArgumentNotValidException¶
org.springframework.web.bind.MethodArgumentNotValidException is the exception class generated when an incorrect input value is specified while binding the data stored in the request body to JavaBean using @RequestBody annotation."application/json" or "application/xml" etc., exception handling of MethodArgumentNotValidException needs to be performed.- Controller
@ExceptionHandler(MethodArgumentNotValidException.class) // (1) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public ErrorResults handleMethodArgumentNotValidException( MethodArgumentNotValidException e, Locale locale) { // (1) ErrorResults errorResults = new ErrorResults(); // implement error handling. // omitted return errorResults; }
Sr. No. Description (1) SpecifyMethodArgumentNotValidException.classas an exception for error handling.Other than this, it is same asBindException.
4.13.2.3.3. Handling HttpMessageNotReadableException¶
org.springframework.http.converter.HttpMessageNotReadableException is the exception class generated when a JavaBean could not be created from the data stored in Body, while binding the data stored in the request body to JavaBean, using @RequestBody annotation."application/json" or "application/xml" etc., exception handling of MethodArgumentNotValidException needs to be performed.Note
Causes of specific errors differ depending on the implementation of
HttpMessageConverteror library to be used.In
MappingJackson2HttpMessageConverterimplementation, wherein data in JSON format is to be converted to JavaBean using Jackson, if a string is specified in the Integer field instead of number,HttpMessageNotReadableExceptionoccurs.
- Controller
@ExceptionHandler(HttpMessageNotReadableException.class) // (1) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public ErrorResults handleHttpMessageNotReadableException( HttpMessageNotReadableException e, Locale locale) { // (1) ErrorResults errorResults = new ErrorResults(); // implement error handling. // omitted return errorResults; }
Sr. No. Description (1) SpecifyHttpMessageNotReadableException.classas the exception of error handling object.Other than this, it is same asBindException.
4.13.2.3.4. Handling by using BindingResult¶
BindingResult as the handler method argument.BindingResult is not to be specified as handler method argument, it is necessary to implement error handling by the exception handling method mentioned earlier.- Controller
@RequestMapping(value = "plus", method = RequestMethod.POST) @ResponseBody public CalculationResult plus( @Validated @RequestBody CalculationParameters params, BindingResult bResult) { // (1) CalculationResult result = new CalculationResult(); if (bResult.hasErrors()) { // (2) // (3) // implement error handling. // omitted return result; // (4) } int sum = params.getNumber1() + params.getNumber2(); result.setResultNumber(sum); return result; }
Sr. No. Description (1) DeclareBindingResultas a handler method argument.BindingResultneeds to be declared immediately after the JavaBean for input validation. (2) Check whether there is any input value error. (3) If so, perform error handling for input error.In the above example, although error handling is omitted, it is assumed that settings for error message etc. are performed. (4) Return processing result.Note
In the above example, HTTP status code
200(OK) is returned as response for both normal process as well as error. When it is necessary to classify HTTP status codes as per processing results, it can be implemented by settingorg.springframework.http.ResponseEntityas the return value. As another approach, error handling can be implemented by the exception handling method mentioned earlier, without specifyingBindingResultas the handler method argument.@RequestMapping(value = "plus", method = RequestMethod.POST) @ResponseBody public ResponseEntity<CalculationResult> plus( @Validated @RequestBody CalculationParameters params, BindingResult bResult) { CalculationResult result = new CalculationResult(); if (bResult.hasErrors()) { // implement error handling. // omitted // (1) return ResponseEntity.badRequest().body(result); } // omitted // (2) return ResponseEntity.ok().body(result); }
Sr. No. Description (1) Return response data and HTTP status in case of input error. (2) Return response data and HTTP status in case of normal termination.
4.13.2.4. Business error handling¶
How to handle business errors is explained here.
Methods that handle business errors are widely classified as follows.
- Method that performs error handling by providing a business exception handling method.
- Method that catches business exception in the handler method of Controller and performs error handling.
4.13.2.4.1. Handling business exception by exception handling method¶
- Controller
@ExceptionHandler(BusinessException.class) // (1) @ResponseStatus(value = HttpStatus.CONFLICT) // (2) @ResponseBody public ErrorResults handleHttpBusinessException(BusinessException e, // (1) Locale locale) { ErrorResults errorResults = new ErrorResults(); // implement error handling. // omitted return errorResults; }
Sr. No. Description (1) SpecifyBusinessException.classas an exception for error handling.Other than this, it is similar to the input error handling forBindException. (2) Specify the HTTP status information sent as response.In the above example,409(Conflict) is specified.
4.13.2.4.2. Handling business exception in handler method¶
- Controller
@RequestMapping(value = "plus", method = RequestMethod.POST) @ResponseBody public ResponseEntity<CalculationResult> plusForJson( @Validated @RequestBody CalculationParameters params) { CalculationResult result = new CalculationResult(); // omitted // (1) try { // call service method. // omitted // (2) } catch (BusinessException e) { // (3) // implement error handling. // omitted return ResponseEntity.status(HttpStatus.CONFLICT).body(result); } // omitted return ResponseEntity.ok().body(result); }
Sr. No. Description (1) Enclose the method call where business exception occurs, in try clause. (2) Catch business exception. (3) Perform the error handling intended for business exception error.In the above example, although error handling is omitted, it is assumed that settings for error message etc. are performed.