Do want to get a better understanding of Spring web application architecture? If so, get started right now!

Spring from the Trenches: Adding Validation to a REST API

Rusty milary helmet

I am a bit ashamed to admit this but until yesterday, I had no idea that I can add validation to a REST API by using the @Valid and the @RequestBody annotations.

This was not working in Spring MVC 3.0 and for some reason I had not noticed that the support for this was added in Spring MVC 3.1.

I never liked the old approach because I had to

  1. Inject the Validator and MessageSource beans to my controller so that I can validate the request and fetch the localized error messages if the validation fails.
  2. Call the validation method in every controller method which input must be validated.
  3. Move the validation logic into a common base class which is extended by the controller classes.

When I noticed that I don’t have to do these things anymore, I decided to write this blog post and share my findings with all of you.

Note: If we want to use the JSR-303 backed validation with Spring Framework, we have to add a JSR-303 provider to our classpath. The example applications of this blog post use Hibernate Validator 4.2.0 which is the reference implementation of the Bean Validation API (JSR-303).

Let’s start by taking a look at the DTO class used in this blog post. The source code of the CommentDTO class looks as follows:

import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;

public class CommentDTO {

    @NotEmpty
    @Length(max = 140)
    private String text;

	//Methods are omitted.
}

Let’s move on and find out how we can add validation to a REST API with Spring MVC 3.1.

Spring MVC 3.1 Is a Good Start

We can add validation to our REST API by following these steps:

  1. Implement a controller method and ensure that its input is validated.
  2. Implement the logic which handles validation errors.

Both of the steps are described in the following subsections.

Implementing the Controller

We can implement our controller by following these steps:

  1. Create a class called CommentController and annotate this class with the @Controller annotation.
  2. Add an add() method to the CommentController class which takes the added comment as a method parameter.
  3. Annotate the method with @RequestMapping and @ResponseBody annotations.
  4. Apply the @Valid and @RequestBody annotations to the method parameter.
  5. Return the added comment.

The source code of the CommentController class looks as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@Controller
public class CommentController {

    @RequestMapping(value = "/api/comment", method = RequestMethod.POST)
    @ResponseBody
    public CommentDTO add(@Valid @RequestBody CommentDTO comment) {
        return comment;
    }
}

We have now added a new method to our controller and added validation to it. When the validation fails, the MethodArgumentNotValidException is thrown. Let’s find out how we can return a meaningful response to the user of our API when the validation fails.

Handling Validation Errors

We can implement the logic which handles the validation errors by following these steps:

  1. Implement the data transfer objects which contains the information returned to the user of our REST API.
  2. Implement the exception handler method.

These steps are described with more details in the following.

Creating the Data Transfer Objects

First, we have to create the data transfer objects which contains the information returned to the user of our REST API. We can do this by following these steps:

  1. Create a DTO which contains the information of a single validation error.
  2. Create a DTO which wraps those validation errors together.

Let’s get started.

The source code of the first DTO looks as follows:

public class FieldErrorDTO {

    private String field;

    private String message;

    public FieldErrorDTO(String field, String message) {
        this.field = field;
        this.message = message;
    }

	//Getters are omitted.
}

The implementation of the second DTO is rather simple. It contains a list of FieldErrorDTO objects and a method which is used to add new field errors to the list. The source code of the ValidationErrorDTO looks as follows:

import java.util.ArrayList;
import java.util.List;

public class ValidationErrorDTO {

    private List<FieldErrorDTO> fieldErrors = new ArrayList<>();

    public ValidationErrorDTO() {

    }

    public void addFieldError(String path, String message) {
        FieldErrorDTO error = new FieldErrorDTO(path, message);
        fieldErrors.add(error);
    }

   	//Getter is omitted.
}

The following listing provides an example Json document which is send back to the user of our API when the validation fails:

{
	"fieldErrors":[
		{
			"field":"text",
			"message":"error message"
		}
	]
}

Let’s see how we can implement the exception handler method which creates a new ValidationErrorDTO object and returns created object.

Implementing the Exception Handler Method

We can add the exception handler method to our controller by following these steps:

  1. Add a MessageSource field to the CommentController class. The message source is used to fetch localized error message for validation errors.
  2. Inject the MessageSource bean by using constructor injection.
  3. Add a processValidationError() method to the CommentController class. This method returns ValidationErrorDTO object and takes a MethodArgumentNotValidException object as a method parameter.
  4. Annotate the method with the @ExceptionHandler annotation and ensure that the method is called when the MethodArgumentNotValidException is thrown.
  5. Annotate the method with the @ResponseStatus annotation and ensure that the HTTP status code 400 (bad request) is returned.
  6. Annotate the method with the @ResponseBody annotation.
  7. Implement the method.

Let’s take a closer look at the implementation of the processValidationError() method. We can implement this method by following these steps:

  1. Get a list of FieldError objects and process them.
  2. Process the field errors one field error at the time.
  3. Try to resolve a localized error message by calling the getMessage() method of the MessageSource interface, and pass the processed field error and the current locale as method parameters.
  4. Return the resolved error message. If the error message is not found from the properties file, return the most accurate field error code.
  5. Add a new field error by calling the addFieldError() method of the ValidationErrorDTO class. Pass the name of the field and the resolved error message as method parameters.
  6. Return the created ValidationErrorDTO object after each field error has been processed.

The source code of the CommentController class looks as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.Locale;

@Controller
public class CommentController {

    private MessageSource messageSource;

    @Autowired
    public CommentController(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

	//The add() method is omitted.

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ValidationErrorDTO processValidationError(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();

        return processFieldErrors(fieldErrors);
    }

    private ValidationErrorDTO processFieldErrors(List<FieldError> fieldErrors) {
        ValidationErrorDTO dto = new ValidationErrorDTO();

        for (FieldError fieldError: fieldErrors) {
            String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
            dto.addFieldError(fieldError.getField(), localizedErrorMessage);
        }

        return dto;
    }

    private String resolveLocalizedErrorMessage(FieldError fieldError) {
        Locale currentLocale =  LocaleContextHolder.getLocale();
        String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);

        //If the message was not found, return the most accurate field error code instead.
        //You can remove this check if you prefer to get the default error message.
        if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
            String[] fieldErrorCodes = fieldError.getCodes();
            localizedErrorMessage = fieldErrorCodes[0];
        }

        return localizedErrorMessage;
    }
}

That is it. Let’s spend a moment to evaluate what we have just done.

We Are Almost There

We have now added validation to our REST API with Spring MVC 3.1. This implementation has one major benefit over the old approach:

We can trigger the validation process by using the @Valid annotation.

However, the methods annotated with the @ExceptionHandler annotation will be triggered only when the configured exception is thrown from the controller class which contains the exception handler method. This means that if our application has more than one controller, we have to create a common base class for our controllers and move the logic which handles the validation errors to that class. This might not sound like a big deal but we should prefer composition over inheritance.

Spring MVC 3.2 provides the tools which we can use to remove the need of inheritance from our controllers. Let’s move on and find out how this is done.

Spring MVC 3.2 to the Rescue

Spring MVC 3.2 introduced a new @ControllerAdvice annotation which we can use to implement an exception handler component that processes the exceptions thrown by our controllers. We can implement this component by following these steps:

  1. Remove the logic which handles validation errors from the CommentController class.
  2. Create a new exception handler class and move the logic which processes validation errors to the created class.

These steps are explained with more details in the following subsections.

Removing Exception Handling Logic from Our Controller

We can remove the exception handling logic from our controller by following these steps:

  1. Remove the MessageSource field from the CommentController class.
  2. Remove the constructor from our controller class.
  3. Remove the processValidationError() method and the private methods from our controller class.

The source code of the CommentController class looks as follows:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@Controller
public class CommentController {

    @RequestMapping(value = "/api/comment", method = RequestMethod.POST)
    @ResponseBody
    public CommentDTO add(@Valid @RequestBody CommentDTO comment) {
        return comment;
    }
}

Our is next step is to create the exception handler component. Let’s see how this is done.

Creating the Exception Handler Component

We can create the exception handler component by following these steps:

  1. Create a class called RestErrorHandler and annotate it with the @ControllerAdvice annotation.
  2. Add a MessageSource field to the RestErrorHandler class.
  3. Inject the MessageSource bean by using constructor injection.
  4. Add the processValidationError() method and the required private methods to the RestErrorHandler class.

The source code of the RestErrorHandler class looks as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.List;
import java.util.Locale;

@ControllerAdvice
public class RestErrorHandler {

    private MessageSource messageSource;

    @Autowired
    public RestErrorHandler(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ValidationErrorDTO processValidationError(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();

        return processFieldErrors(fieldErrors);
    }

    private ValidationErrorDTO processFieldErrors(List<FieldError> fieldErrors) {
        ValidationErrorDTO dto = new ValidationErrorDTO();

        for (FieldError fieldError: fieldErrors) {
            String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
            dto.addFieldError(fieldError.getField(), localizedErrorMessage);
        }

        return dto;
    }

    private String resolveLocalizedErrorMessage(FieldError fieldError) {
        Locale currentLocale =  LocaleContextHolder.getLocale();
        String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);

        //If the message was not found, return the most accurate field error code instead.
        //You can remove this check if you prefer to get the default error message.
        if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
            String[] fieldErrorCodes = fieldError.getCodes();
            localizedErrorMessage = fieldErrorCodes[0];
        }

        return localizedErrorMessage;
    }
}

We Are Finally There

Thanks to Spring MVC 3.2, we have now implemented an elegant solution where the validation is triggered by the @Valid annotation, and the exception handling logic is moved to a separate class. I think that we can call it a day and enjoy the results of our work.

Summary

This blog post has taught us that

  • If we want to add validation to a REST API when we are using Spring 3.0, we have to implement the validation logic ourself.
  • Spring 3.1 made it possible to add validation to a REST API by using the @Valid annotation. However, we have to create a common base class which contains the exception handling logic. Each controller which requires validation must extend this base class.
  • When we are using Spring 3.2, we can trigger the validation process by using the @Valid annotation and extract the exception handling logic into a separate class.

The example application of this blog are available at Github (Spring 3.1 and Spring 3.2)

About the Author

Petri Kainulainen is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.

About Petri Kainulainen →

62 comments… add one

  • Great post, but I believe you can make it even more simple. The FieldError is an instance of MessageCodeResolvable which you can directly pass to the MessageSource. That should save you the codes lookup and iterating over them. That only leaves you with a check if the message and code are the same.

    Reply
    • Marten,

      Thank you for your comment. Your suggestion is great and makes the code much cleaner. I will update the blog post and the example projects by using the approach you suggested.

      Update: I updated the example projects and the blog post. It seems that if the error message is resolved by using the String getMessage(MessageSourceResolvable resolvable, Locale locale) method of the MessageSource interface, the AbstractMessageSource class ignores the value of the useCodeAsDefaultMessage property and always returns the default message if the message is not found. I wonder if there is a way to get rid of the if clause found from the resolveLocalizedErrorMessage(FieldError fieldError, Locale locale) method. If you know a way, let me know. :)

      Reply
  • Any idea why I’m getting this exception?

    java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.bind.MethodArgumentNotValidException]

    My method is similar to your processValidationError.

    Reply
    • Actually I had no idea.

      Then I found this document from the secret archives of MI6.

      It seems that the IllegalStateException exception is thrown if you have more than one method which is annotated to handle the MethodArgumentNotValidException.

      Reply
      • Thanks to your reply I have found the solution. My RestErrorHandler class extended ResponseEntityExceptionHandler class which has handleMethodArgumentNotValid method, and that was causing the exception. I no longer extend ResponseEntityExceptionHandler and it’s working now.

        Reply
        • You are welcome! Also, it is great to hear that you solved your problem.

          Reply
        • When you extend from ResponseEntityExceptionHandler, you have already an method annotated with @ExceptionHandler and the value MethodArgumentNotValidException.

          So if you wan to have an specific behaviour for this exception and extend from ResponseEntityExceptionHandler you should override the method:

          
          @Override
          protected ResponseEntity handleMethodArgumentNotValid(
          	MethodArgumentNotValidException ex, 
          	HttpHeaders headers, 
          	HttpStatus status, 
          	WebRequest request)
          
          
          Reply
          • Rafa,

            Thanks for pointing that option out!

  • Thank you for the article. It really helped me.

    Reply
    • You are welcome. I am happy to hear that this blog post was useful to you!

      Reply
  • This article was really helpful. What is especially great about it is that you show solutions for different Spring versions, not just the latest one.

    The comment about omitting getters confused me a bit though. I didn’t include any getters and this resulted in a HttpMediaTypeNotAcceptableException exception. Maybe that’s just me though.

    Reply
    • Hi José,

      I am happy to hear that this tutorial was useful to you.

      The comment which I made about omitting getter methods means that the actual code has getter methods but I left them out from the code listing as irrelevant. Do you think that I should mention this in the sample code?

      The getter methods are required because the default configuration of Jackson requires that the DTO either has public fields or public getter methods. Since I didn’t want to make the fields of my DTO class public, I had to use public getter methods.

      Were you able to solve your problem (HttpMediaTypeNotAcceptableException is thrown) or do you need some help with that?

      Reply
  • I guess it doesn’t harm to be more specific about the getter to avoid confusions.

    Yes, the problem was solved by adding the getters. Thank you for your answer!

    Reply
  • Hi Petri,

    I am trying same thing with XML configuration but its not working for me. It catches all my custom exception but its not catching @valid errors. It throws bad request which I can see in my browser console.

    @ControllerAdvice
    public class BaseExceptionResolver {

    public static final Logger LOGGER = LoggerFactory.getLogger(BaseExceptionResolver.class);

    private MessageSource messageSource;

    @Autowired
    public BaseExceptionResolver(final MessageSource messageSource) {
    LOGGER.info(“entering BaseExceptionResolver constructor”);
    this.messageSource = messageSource;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseEntity handleValidationException(MethodArgumentNotValidException pe) {
    LOGGER.info(“Catched MethodArgumentNotValidException “);
    return new ResponseEntity(pe.getMessage(), HttpStatus.BAD_REQUEST);
    }
    }

    Reply
    • Hi Usair,

      The both example applications (Spring 3.1 and Spring 3.2) have a working XML configuration but it is not active by default. You can switch to XML configuration by modifying the ExampleApplicationConfig class (the required modifications should be pretty obvious).

      One thing which you could do is to compare your application configuration file to the XML configuration files of the example applications. Here are direct links to the configuration files of those applications:

      By the way, what did you mean by “it throws a bad request”?

      Your exception handler method is configured to return the HTTP status code bad request when the MethodArgumentNotValidException is thrown. That explains why you see that in your browser console.

      Reply
  • Hi Petri,

    Thanks for your quick reply. “It throws a bad request” means control is not going inside “handleValidationException” method. I saw you XML configuration files also my files are quite similar and my ControllerAdvice is working for my custom made exception but its not calling “handleValidationException” which is there to handle @Valid validations. Here is my simple controller’s method

    @RequestMapping(value = “register”, method = RequestMethod.POST)
    public String registerUser(@Valid UserDTO user) {
    LOGGER.info(“User : “+ user.toString());
    return “user/confirm”;
    }

    my DTO

    public class UserDTO implements Serializable{

    @NotNull
    @NotEmpty
    @Length(max=2)
    private String name;

    @NotNull
    private Integer age;

    public UserDTO () {

    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public Integer getAge() {
    return age;
    }

    public void setAge(Integer age) {
    this.age = age;
    }

    @Override
    public String toString() {
    return “UserDTO [name=" + name + ", age=" + age + "]“;
    }
    }

    Reply
    • Are you trying to implement a REST API method or a “regular” Spring MVC controller method?

      If you are trying to implement a regular Spring MVC controller method, you have to add a @ModelAttribute annotation before the @Valid annotation and specify the name of your form object.

      Reply
  • I am fairly new to Spring and have been using you site a guide. I started off with a Spring Roo project, but removed it after getting to a point it was no longer of little value. I used the Roo project as a basic template on how to set up a Spring project. I have Rest and Spring web controllers in the same project. In addition, the REST controllers were configured by Roo. So, they use domain objects to pass between the server and the client. However, I notice you use DTOs, which I assume is not your domain objects. If this is the case, I think the DTO method might be a bit more secure. Do you have any advice on DTOs and domain objects for REST controllers? Also, can the above controller advice work with REST and web controllers in the same project or should I move my controllers to separate projects?

    Reply
    • I think have a way to use your controller advice solution without impacting my web controllers. My web controllers use @validated and the method gets the BindingResult, which I think would prevent it from throwing the exception and not make it to the controller advice. Would you agree?

      Reply
    • Hi Joe,

      About your first question:

      I use DTOs in REST controllers for two reasons:

      1. It gives me an easy way to control which information is returned to the client. If you return domain objects, all information is returned to the client by default. This can have have dramatic effects to the performance of the application and/or it can lead into a situation where you are “leaking” sensitive information to the client. You can of course override this by using Jackson annotations but this means that your code becomes a mess.
      2. I think that the clients of my API “should not be aware” of my domain model for two reasons:
        • This provides a nice separation between the API and the inner workings of my application.
        • The domain model can be a quite complex beast. When I use DTOs, I can simplify the API in a such way that it is easier to use.

      About your second question:

      The Javadoc of the of the MethodArgumentNotValidException states that that it is thrown when validation on an argument annotated with @Valid fails.

      I assume that this means that you have to change the implementation of the method annotated with the @ExceptionHandler annotation to provide different handling logic for REST and web controllers.

      I have to admit that I haven’t tested this. I guess your best option is to test this yourself (by the way, this is a good idea for a blog post).

      Reply
      • Petri,

        I appreciate the quick response. I agree with your statement using the DTO. I had the same concern about using the domain model. I was afraid of someone figuring out how to navigate the object graph and do some damage. Putting in the DTOs provides a clean break. Prior to that I was using Flex JSON annotations to exclude data I wanted to share with the client, but it was getting messy.

        As for your example, I had to add jackson-core-asl and jackson-mapper-asl to my POM to get it to work. Before adding the POM changes I would get a HTTP 415. I used the the answer on StackOverflow to work out the problem.

        http://stackoverflow.com/questions/13772146/ajax-json-post-to-spring-controller-returns-http-415

        Now the code creating the the object in the REST method, but I need to test the code further for the controller advice.

        Thanks,
        Joe

        Reply
  • Petri,

    Good news! I was able to use your example with my REST controllers without impacting my web controllers. So, my existing controller advice for my web controllers works as normal. The web controller method gets the binding results and makes decisions based off if it has errors or not. Therefore, the two can coexist without any issues.

    As for a blog post, I would like to get your thoughts on DTO and domain objects. How do you handle merging DTO changes back into the domain objects? Do you create them by hand per client/server interaction? I am thinking of creating some annotations to help create DTOs automatically from the domain objects, so the validation remains in-sync, among other things. I am working a one man project after hours, so anything I can do to reduce my workload will help.

    Thanks again,
    Joe

    Reply
    • Joe,

      It is good to know that using this technique for REST controllers doesn’t cause problems with “normal” controllers. Thank you for the information!

      There are a few libraries which can be used to transform model objects into DTOs and vice versa. These libraries are:

      I have personally used a forked version version of jTransfo (I should create a pull request and see if my changes are useful to others) to transform model objects into DTOs and I have been very happy with it. However, you might want to check them all out and see which one is the best fit for you.

      I transform DTOs into model objects manually because my model objects often have domain logic in them, and copying field values from DTOs bypasses this logic. Also, I try to not have any setters in domain classes (I fail in this though). However, if your domain objects do not have any logic in them, using one of the mentioned libraries is probably a good idea.

      Reply
      • Petri,

        I am glad you sent me those links! Those are going to save me a lot of time. When I get off work, I was going to create code to do what these libraries do. Now, I am going to do some research.

        Thanks for the time saver!
        Joe

        Reply
        • Hi Joe,

          you are welcome!

          Reply
  • Hi Petri,

    I use your example to build a rest service. But I don´t understand why running the tests I have the JSON response when the validation is not correct, but when I do the calls from the SoapUI I have a 400 error and without the JSON response. If the request has a JSON object @Valid then returns a normal response but when is not valid not. As I understand is doing the validation but running with Debug is not going to the Handler code.

    Do you know why? And how I could test it outside the unit tests as for example with SoapUI?

    Reply
    • Hi Javier,

      The HTTP status code 400 (Bad request) means that the request was malformed and it could not be processed. This can be a bit confusing because the handler method returns the same status code. However, since you were able to verify that the handler method was not called, I would ensure that:

      • The value of the Content-Type request header is ‘application/json’
      • The field names of the JSON send in the request body matches with the field names of the DTO object.

      These are the mistakes which I have made when I have encountered this problem. Do you see any error messages on the log?

      Also, it would be helpful if you could add the invalid JSON document here so that I could debug the example application.

      About your last question:

      It should be possible to test REST APIs by using external tools as long as the request is constructed properly (although I have no experience from SoapUI).

      Reply
      • Hi Petri,

        Thanks for answer so quick. Well my RestErrorHandler is exactly as yours. The problem is that with the test the checks are right about the message and the json response. But when I call it from SoapUI but also with rest console from chrome or whatever tool I am having a 400 error.

        So as I understand if would be some error when return the object to be mapped to JSON should go to the handle error code and after throw the error but it is not happening.

        I am not sure why is happening it. Maybe I am missing some configuration but is really strange that the test check correctly but after the rest service doesn’t work in the same way.

        I would check what happens with your code and if works then I should check configuration.

        Yesterday I spent around 2h trying to fix it but I failed.
        If you have any idea let me know, tonight or tomorrow if I could fix it I will let you know as well.

        Thanks,

        Reply
        • Is your controller method called when you try to call it by using REST console or SoapUI? The HTTP status code 400 can also mean that Spring didn’t find a controller method which can process your request.

          If your controller method isn’t called, it would be helpful to see the request mapping of your controller method.

          Reply
          • Hi Petri,

            When the Object is valid the method is working, the problem is when the object is not valid then is not handle by the HandlerController.

            I continue looking on it, is like the @EnableMVC is not working?

  • Well I didn’t find the error but should be something in configuration. So I fork your project and it works fine.

    Finally I used your project and add my files there ;)

    Reply
    • Just realized one possible cause of this problem:

      Was the error handler class in a package which is scanned by Spring (check the @ComponentScan annotation)?

      Anyway, it is good to hear that you found at least some solution for your problem!

      Reply
  • sorry I have a Exception:

    //JSON
    {
    “username” : “”
    }

    org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

    Reply
    • You could start by verifying that

      1. Your request has an a request header called ‘Accept’, and its value is ‘application/json’.
      2. The Jackson jar files are found from the classpath.

      I hope that this answered to your question. If this doesn’t solve your problem, please let me know.

      Reply
  • Hi, great tutorial.
    Eventually you may add a comment that it is required to configure your validator, e.g. as described in http://docs.spring.io/spring/docs/3.0.0.RC3/reference/html/ch05s07.html (section 5.7.4.2). I did not have configured one … ;-)

    Best,
    Thomas

    Reply
    • Hi Thomas,

      I am happy to hear that you liked this tutorial!

      If you use Spring 3.1 or newer, you don’t have to configure the validator bean (unless you don’t want to use the default one). As long as you annotate your configuration class (class which is annotated with the @Configuration annotation) with the @EnableWebMvc annotation, or add the <mvc:annotation-driven/> element to your XML configuration file, the validator bean is configured automatically. You have to add a JSR-303 provider to your classpath though.

      If you want to get more information about this, check out the reference manual of Spring Framework 3.1. It has a really nice section which describes what happens when you enable Spring MVC.

      Reply
  • Hi Petry,
    your are absolutely right, that’s exactly what I did:
    However, the reference was wrong, actually it is described in the link above in section 5.7.4.3.
    But maybe it is of interest for any other non Spring expert as me ;-)

    Best,
    Thomas

    Reply
  • Thanks alot man. This was really helpful.

    Reply
    • You are welcome. I am happy to hear that this tutorial was useful to you.

      Reply
  • Hi Petri,
    I’m also using a ControllerAdvice annotation and my custom exceptions are triggered fine on my REST controller. Except for the MethodArgumentNotValidException one even though I use a Valid annotation in my controller. I must be missing something. I posted on Stack http://stackoverflow.com/questions/23590763/valid-hibernate-validation-in-a-spring-rest-controller in case you find the issue interesting.
    Kind Regards,
    Stephane Eybert

    Reply
    • Have you tried using Hibernate Validator 4.2.0.Final? Hibernate Validator 5 is the reference implementation of the bean validation API 1.1 (JSR 349) which isn’t the same specification than JSR 303.

      I assume that Spring Framework 3.2 supports only JSR 303 because I couldn’t find any information about the bean validation API 1.1 from its reference manual.

      Reply
  • Hi Petri,

    Do you know if it is possible to override @ControllerAdvice @ModelAttribute in a controller?

    Let’s say I have a list of states. For 99% of my customers they will see all the states in their select box on a form. So for this scenario I created a class and annotated it with @ControllerAdvice. I then created a method that return @ResponseBody list of states and annotated it with @ModelAttribute(value=”states”).

    In one of my controllers I check for a path variable and if present the states field should only display a subset of the states. I tried overriding the method in the controller with the same annotation but I get the full list each time.

    I saw this article about @ControllerAdvice in Spring 4.
    http://www.javacodegeeks.com/2013/11/controlleradvice-improvements-in-spring-4.html
    Seems like you can now specify which controllers should use the @ControlelrAdvice.

    Just wondering if you had any suggestions.

    Thanks
    Billy

    Reply
    • Hi Billy,

      The Javadoc of the @ControllerAdvice annotation states that it is possible to configure the controller classes which are assisted by the class annotated with the @ControllerAdvice annotation.

      If I understood correctly, you can implement your requirement by following these steps:

      1. Move the controller which displays subset of states in a package which doesn’t contain other controller classes.
      2. Configure the @ControllerAdvice class to assist all other controllers except the one you moved in the first step. One way to do this is to configure the packages which contains the other controller classes by setting the value of the basePackages attribute of the @ControllerAdvice annotation.

      That is it. Remember that the class which is moved to a separate package is “on its own”, and it cannot rely on the functionality provided by the @ControllerAdvice class.

      Reply
  • I have a very bad confusion In spring MVC I use println method in every statement of command class setter and getter method I have a home page where I have use a link to go to login page when I click on link then control forward to login page and there is only two fileld I have declared so why getter method of user name and password called 4-4 times ..pls help me out.

    Reply
    • If you used the Spring form taglib, the getters of your form object (aka command object) are called by Spring because it retrieves the values bound to each input field.

      You can get more information about forms and Spring MVC by reading a blog post titled Spring MVC Form Tutorial.

      It is hard to say why the getters of your form object are called more than once without seeing the source code of your controller and the login page. If you want, you can add these files to pastebin so that I can take a look at them.

      Reply
  • Hi ,
    I am using Rest web service same as you and trying to add field validation same as you have mentioned here.
    I am getting successful response but when filed error comes i am getting following exception & 400 Bad request. Below only change i did because i was getting compile error. change: new ArrayList(); instead of new ArrayList();
    public class ValidationErrorDTO {
    private List fieldErrors = new ArrayList();

    14:10:37,045 ERROR [org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver] (http-/0.0.0.0:8080-1) Failed to invoke @ExceptionHandler method: public com.csam.pps.merchant.services.ValidationErrorDTO com.csam.pps.merchant.services.RestErrorHandler.processValidationError(org.springframework.web.bind.MethodArgumentNotValidException): org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:157) [spring-webmvc-3.2.8.RELEASE.jar:3.2.8.RELEASE]

    Update: I removed the non relevant part of the stacktrace – Petri

    Reply
  • Hi Petri,

    I found this to be a great tutorial. Thanks a lot!

    I was able to implement the validation for POST methods when the parameter is a @RequestBody. However, I am trying to do the validations for GET methods as well for the query parameters. The validation just doesn’t happen. No errors are thrown. Any idea what I might be missing in here?

    I annotated my controller class with @Validated, and my method’s query param with @Range(min=1) @RequestParam xyz. Could you please help me out here?

    Thanks a lot in advance!

    Reply
    • As far as I know, it is not possible to validate individual request parameters by using the technique described in this blog post.

      Are you trying to implement a search function which validates the search conditions? If so, I would probably validate the search conditions manually in the controller method and handle “validation errors” in the error handler class (a class that is annotated with the @ControllerAdvice annotation).

      I know that this is a bit clumsy approach. If you figure out a better way to do this, I would want to hear about it!

      Reply
      • Hi Petri,

        Thanks a lot for your quick response.

        What I wanted was this:
        http://techblogs4u.blogspot.com/2012/09/method-parameter-validation-in-spring-3.html
        That link helped me.

        Also, I like most of your blogs. They are really helpful.
        Are you planning to write anything on how to setup access control and authorization in spring?
        Looking forward to that.

        Reply
        • It is nice to hear that you were able to solve your problem!

          Are you planning to write anything on how to setup access control and authorization in spring?

          I haven’t made any plans to write about Spring Security anytime soon. Eugen Paraschiv has written a very comprehensive Spring Security tutorial. If you want to learn more about Spring Security, you should take a look at that tutorial.

          Reply
          • Thanks a lot for the link!

          • You are welcome. I hope that the tutorial is useful to you.

  • Hi Petri,

    I wonder if there is a way to handle a request aiming at an unknown mapping.

    Spring doesn’t seem to send an exception in that case.

    Being able to handle the “No mapping found for HTTP request with URI” would allow us to respond with a JSON payload instead of a 404 page.

    Kind Regards,

    Stephane Eybert

    Reply
    • Hi Stephane,

      You should check out this StackOverflow answer. It should answer to your question.

      Reply
      • That’s the one :-) Awesome Petri !

        Reply
  • Hi Petri,

    I’m looking for guidelines into validating a parent admin resource (AdminResource extending the Spring ResourceSupport class) as not being empty (@NotEmpty) in a child admin module resource (AdminModuleResource extending the Spring ResourceSupport class). I understand the
    AdminResource class should also implement the Serializable interface ? Is that the way to go with Spring ResourceSupport-ed resources ? Thanks for any directions tips !

    Kind Regards,

    Stephane Eybert

    Reply
    • I assume that you are talking about Spring HATEOAS?

      I have experience from it but you should be able to validate your DTOs by using either JSR 303 or JSR 349.

      Also, the README of Spring HATEOAS doesn’t state that a class that extends the ResourceSupport class must implement the Serializable interface.

      Hmmh. Maybe I didn’t understand your question. If you feel this way too, let me know.

      Reply

Leave a Comment