26

I have a very simple Spring Boot application that uses Spring-Data-Mongodb

All I want to do is set a JSR-303 validation rule that says the object I'm saving must have a username. I read that JSR-303 was added to spring-data-mongodb in version 1.1 so I assumed that when I save an object it's validated but this isn't the case.

Does anyone have a simple example setup that shows how this works?

My User pojo looks like

public class User {

    @Id
    private String id;

    @NotNull(message = "User Name is compulsory")
    private String userName;
    private String password;

    public User() {}

    public String getId() {
      return id;
    }
    public void setId(String id) {
      this.id = id;
    }

    public String getUserName() {
      return userName;
    }
    public void setUserName(String userName) {
      this.userName = userName;
    }


    public String getPassword() {
      return password;
    }
    public void setPassword(String password) {
      this.password = PasswordAuthService.hash(password);
    }
}

I saw somewhere that validation only kicks in if you have a validator created in the context so I tried updating my Application class (which contains all the configuration, to look like

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    @Bean
    public Validator getValidator() {
      LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
      return validator;
    }

    public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
    }

}
Zac Tolley
  • 2,340
  • 4
  • 19
  • 22

4 Answers4

41

First make sure that you have JSR-303 validator on classpath, for example:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>

If you use Java config, the way to go is to create 2 beans:

@Bean
public ValidatingMongoEventListener validatingMongoEventListener() {
    return new ValidatingMongoEventListener(validator());
}

@Bean
public LocalValidatorFactoryBean validator() {
    return new LocalValidatorFactoryBean();
}

Voilà! Validation is working now.

Maciej Walkowiak
  • 12,372
  • 59
  • 63
5

Starting with Spring Boot 2.3 the spring-boot-starter-validation dependency has to be added in pom.xml (for Maven):

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-validation</artifactId> 
</dependency>

Declaring a validator bean is not necessary.

Jochen Haßfurter
  • 875
  • 2
  • 13
  • 27
1

Adding a Validator to the context is a good first step, but I don't think it will interact with anything unless you ask it to. The Spring Data guys can probably say for sure but I think you need to explicitly declare some listeners as well. There's an old blog on the feature, but you can find that by googling as easily as I can.

If you think there would be a useful autoconfig feature in Spring Boot, feel free to make a detailed proposal on github.

Dave Syer
  • 56,583
  • 10
  • 155
  • 143
  • I saw that blog entry, but I also saw that the guy who wrote that then was asked by the Spring team to merge the work he did back into the core Spring-Data-Mongodb project. – Zac Tolley Mar 22 '14 at 08:50
  • I see that. But don't you still need to add a bean of type `ValidatingMongoEventListener`? – Dave Syer Mar 22 '14 at 09:16
  • 1
    I am the guy. Indeed this change was integrated in version 1.1.0 and at that time, using xml configuration for Spring Data MongoDB, validation worked out of the box. @DaveSyer - I think it should be actually a feature in Spring Data MongoDB project rather than Spring Boot - in similar way as EnableMongoRepositories and EnableMongoAuditing are implemented – Maciej Walkowiak Mar 22 '14 at 21:03
  • That sounds about right. Maybe we can discuss that in [github](https://github.com/spring-projects/spring-data-mongodb)? – Dave Syer Mar 23 '14 at 06:51
1

I found that if I add

public User addUser(@RequestBody  @Valid User newUser, 
                   BindingResult bindingResult) throws Exception {

  if (bindingResult.hasErrors()) {
    throw new Exception("Validation Error");
  }

To my controller this validates the incoming json against my rules, though I should still try and setup the validatingMongoEventListener to intercept any other parts of my code that attempt to update the model with invalid data.

Zac Tolley
  • 2,340
  • 4
  • 19
  • 22