Error handling is triggered after the controller adds Global- or FieldErrors (the BindingResult) to the model. There are two ways to change the model in a case of error (or no error). JsonViewCallback and JsonErrorHandler. First the registered JsonViewCallback is triggered. The default implementation provides some useful features to change the error output. Than in a case of error, all registered JsonErrorHandlers are triggered.
First after the controller-binding one of JsonViewCallback methods is executed:
or
The default implementation of the JsonViewCallback is the StandartErrorConverter. It just implements the onPopulateErrors method (see "Source Xref" report).
The standart output is:
{"command":{ "birthday":"08-02-2008", "placeofbirth":"" }, "hasGlobalErrors":"false", "hasFieldErrors":"true", "fielderrors":{ "placeofbirth":"Please enter a a place of birth!" }}
It provides some options to change the error response can set.
KEEP_ALL: No values are deleted from the model
REMOVE_COMMAND_BEAN: Just the Command bean is removed from the model
EEP_ERRORS_ONLY: Just the errors are kept. All other values of the model giong to be removed.
The properties can be set by spring configuration.
bean property | Function | Allowed Values | Default Value |
hasGlobalErrorsKey | changes the hasGlobalErrors property name | A valide JSON Object property name of type java.lang.String |
hasGlobalErrors |
globalErrorsKey | changes the globalErrors property name | A valide JSON Object property name of type java.lang.String |
globalErrorsKey |
hasFieldErrorsKey | changes the hasFieldErrors property name | A valide JSON Object property name of type java.lang.String |
hasFieldErrorsKey |
fieldErrorsKey | changes the fieldErrors property name | A valide JSON Object property name of type java.lang.String |
hasGlobalErrors |
modelCleanUpMode | Mode to cleanup the model in case of an error. | KEEP_ALL REMOVE_COMMAND_BEAN KEEP_ERRORS_ONLY |
KEEP_ALL |
Hier an example:
<beans> <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"> <property name="jsonViewCallback"> <ref bean="jsonViewCallback" /> </property> </bean> <bean name="jsonViewCallback" class="org.springframework.web.servlet.view.json.error.StandartErrorConverter"> <property name="hasGlobalErrorsKey"> <value>hasGlobals</value> </property> <property name="globalErrorsKey"> <value>globals</value> </property> <property name="hasFieldErrorsKey"> <value>hasField</value> </property> <property name="fieldErrorsKey"> <value>field</value> </property> <property name="modelCleanUpMode"> <value>REMOVE_COMMAND_BEAN</value> </property> </bean> </beans> Result: ======= Response-Status : 311 { "hasGlobals":"true", "globals": ["errormessage1","errormessage2"], "hasField":"true", "field":{ "birthday":"Please enter a valid date!" }}
After the onPopulateErrors of the JsonViewCallback is executed, all registered JsonErrorHandlers are triggered in the order they were added.
The following JsonErrorHandlers are implemented:
Sets a new Response-Status by response.setStatus(errorCode); Some Ajax-Frameworks for example prototype.js trigger the onSuccess (200 - 299) or onFailure (>=300) by ResponseStatusCodes
The default code is 311.
Adds a simple key-value-pair to the model. Some Web2.0 GUI frameworks need a flag to validate a success or failure of the server-side action. Ext, for example, needs a failure=true or success=true
The default flag is failure=true
<beans> <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"> <property name="jsonErrors"> <list> <ref bean="statusError" /> <ref bean="modelflagError" /> </list> </property> </bean> <bean name="statusError" class="org.springframework.web.servlet.view.json.error.HttpStatusError"/> <bean name="modelflagError" class="org.springframework.web.servlet.view.json.error.ModelFlagError"/> </beans> Result: ======= Response-Status : 311 {"command":{ "birthday":"30-01-2008", "placeofbirth":"Sydney" }, "failure":"true", "hasGlobalErrors":"true", "globalerrors": ["errormessage1","errormessage2"], "hasFieldErrors":"true", "fielderrors":{ "birthday":"Please enter a valid date!" }}
You can customise the StatusErrorCode added to the response by setting the errorCode property of the HttpStatusError Bean.
<beans> <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"> <property name="jsonErrors"> <list> <ref bean="statusError" /> </list> </property> </bean> <bean name="statusError" class="org.springframework.web.servlet.view.json.error.HttpStatusError"> <property name="errorCode"><value>999</value></property> </bean> </beans> Result: ======= Response-Status : 999 {"command":{ "birthday":"30-01-2008", "placeofbirth":"Sydney" }, "hasGlobalErrors":"true", "globalerrors": ["errormessage1","errormessage2"], "hasFieldErrors":"true", "fielderrors":{ "birthday":"Please enter a valide date!" }}
You can customise the key-value pair added to the model by setting the key and the value property of the ModelFlagError Bean. Now it provides typed value setters as well.
<beans> <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"> <property name="jsonErrors"> <list> <ref bean="statusError" /> <ref bean="modelflagError" /> </list> </property> </bean> <bean name="modelflagError" class="org.springframework.web.servlet.view.json.error.ModelFlagError"> <property name="name"><value>failure</value></property> <property name="value"><value>true</value></property> </bean> </beans> Result: ======= Response-Status : 200 {"command":{ "birthday":"30-01-2008", "placeofbirth":"Sydney" }, "failure":"true", "hasGlobalErrors":"true", "globalerrors": ["errormessage1","errormessage2"], "hasFieldErrors":"true", "fielderrors":{ "birthday":"Please enter a valid date!" }}
Finally you can create your own error / success handling by implementing the JsonViewCallback interface.
public class MyJsonViewCallback implements JsonViewCallback { // either ... triggerd if a Global- or FieldError exists. public void public void onPopulateErrors( Map model, RequestContext rc, BindingResult br) throws Exception{ // Do something ... } // or ... triggered if no Error is added. public void public void onPopulateSuccess( Map model, RequestContext rc, BindingResult br) throws Exception{ // Do something else... } }
Finally you can create your own error handling by implementing the JsonErrorHandler interface.
public class MyErrorHandler implements JsonErrorHandler { public void triggerError(Map model, RequestContext rc, BindingResult br, HttpServletRequest request, HttpServletResponse response) throws Exception{ // Do something ... } }