Error handling

  1. Instruction
  2. JsonViewCallback
  3. JsonErrorHandlers
  4. CustomImplementaton of JsonViewCallback
  5. CustomImplementaton of JsonErrorHandler

Instruction

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.

Diagram
Errorhandling Process

JsonViewCallback

First after the controller-binding one of JsonViewCallback methods is executed:

  • onPopulateErrors is triggerd if a Global- or FieldError exists.

or

  • onPopulateSuccess is triggered if no Error is added.

StandartErrorConverter

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.

  • custom error key names
  • choose a model clean up mode:

    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!"
}}

JsonErrorHandlers

After the onPopulateErrors of the JsonViewCallback is executed, all registered JsonErrorHandlers are triggered in the order they were added.

The following JsonErrorHandlers are implemented:

  • HttpStatusError

    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.

  • ModelFlagError

    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!"
}}

HttpStatusError

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!"
}}

ModelFlagError

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.

  • setBooleanValue
  • setIntegerValue
  • setLongValue
  • setFloatValue
  • setDoubleValue
  • setStringValue
Attention :
To get the values in the "json typed string format" please don't forget to set the keepValueTypesMode property in case you are using the XStreamJsonStringWriter or the SojoJsonStringWriter
<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!"
}}

Custom implementation of JsonViewCallback

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

Custom implementation of JsonErrorHandler

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