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