Tuesday, October 16, 2012

Customise error message for missing parameter exception (400) when using Spring @Controller and @RequestParam.

I am working on a project which needs a REST resource to accept client request for sending emails.

The parameters required by this Resource are:
1) from: a valid email address to send mails.
2) subject: the subject of mail.
3) to: a valid email address the mail send to.
4) text: the content of mail.

Because our project is using Spring to do everything we need and it can do. So Spring Rest Controller is my best option to implement this Resource.

the declaration of my resource is:

 @RequestMapping ( method = { RequestMethod.POST, RequestMethod.GET } )  
 @ResponseStatus ( HttpStatus.OK )  
 public void sendEmail( @RequestParam ( value = "from" ) String from,  
                    @RequestParam ( value = "subject" ) String subject,  
                    @RequestParam ( value = "to" ) String to,  
                    @RequestParam ( value = "text" ) String text,  
                    final HttpServletResponse response ) throws Exception  

And I test it by using following url.


Because the parameter from is missing and the system should return a 400 exception with the right error message:

 HTTP Status 400 - Required String parameter 'from' is not present  
 type Status report  
 message Required String parameter 'from' is not present  
 description The request sent by the client was syntactically incorrect (Required String parameter 'from' is not present).  
 Apache Tomcat/7.0.23  

however, what I get is:

 HTTP Status 400 -   
 type Status report  
 description The request sent by the client was syntactically incorrect ().  

So what I need is how to customise the error message.

Actually, Spring does provide an exception for this case, it called
MissingServletRequestParameterException and returned the correct error message that what exact we want. But for some reason, the client side did not get the correct error message, but only the right status code which is 400.

My Solution (Also the solution shared by people online already):

Create my own AnnotationMethodHandlerAdapter and override the method invokeHandlerMethod.

 public class AnnotationMethodExceptionHandlerAdapter extends  
     protected ModelAndView invokeHandlerMethod( HttpServletRequest request,  
                           HttpServletResponse response, Object handler ) throws Exception  
             return super.invokeHandlerMethod( request, response, handler );  
         catch ( MissingServletRequestParameterException e )  
             request.setAttribute( "EXCEPTION_NAME", e.getClass().getName() );  
             response.sendError( HttpServletResponse.SC_BAD_REQUEST, e.getMessage() );  
             return null;  
         catch ( Exception e )  
             request.setAttribute( "EXCEPTION_NAME", e.getClass().getName() );  
             response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage() );  
             return null;  

I am not sure is there any exception which is not a MissingServletRequestParameterException can be thrown by  super.invokeHandlerMethod( request, response, handler ); and I do know what status should return in that case. So at here I just return 500.

And modify my servlet config.

 <!--To enable @RequestMapping process on type (class) level -->  
     <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>  
     <!--To enable @RequestMapping process on method level -->  
   <bean class="YourProjectPath.AnnotationMethodExceptionHandlerAdapter"/>  

Do not need use

Then you will get the correct error message.

As I mentioned before and you can seen below, Spring does return the correct error message, but I do not know why client can not get it.

Hope this is helpful to you if you are struggling with the same problem with I got.

No comments:

Post a Comment