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 ...
}
}