Spring boot data starter, @Notnull restriction not working

I am trying to add an @NotNull constraint to my Person object, but I can still @POST a new person with a null email address. I am using Spring boot with MongoDB.

Entity Class:

import javax.validation.constraints.NotNull;

public class Person {
    @Id 
    private String id;
    private String username;
    private String password;
    @NotNull // <-- Not working
    private String email;
    // getters & setters
}

Repository Class:

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends MongoRepository<Person, String> {
}

Application Class:

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

pom.xml

...
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.BUILD-SNAPSHOT</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-rest</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
...

When I @POST a new object through Postman, for example:

{
  "username": "deadpool",
  "email": null
}

I still get STATUS 201created using this payload:

{
    "username": "deadpool",
    "password": null,
    "email": null
     ....
     ....
}
+4
source share
4 answers

, , JPA, MongoDb, - , . , , 400, 500.

build.gradle

    compile('org.hibernate:hibernate-validator:4.2.0.Final')

@Configuration
public class CustomRepositoryRestConfigurerAdapter extends RepositoryRestConfigurerAdapter {


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

   @Override
   public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
       validatingListener.addValidator("afterCreate", validator());
       validatingListener.addValidator("beforeCreate", validator());
       validatingListener.addValidator("afterSave", validator());
       validatingListener.addValidator("beforeSave", validator());
   }
}
+6

, @NotNull, .

@Documented
@Constraint(validatedBy = NotEmptyValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmpty {


    String message() default "{validator.notEmpty}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

public class NotEmptyValidator implements ConstraintValidator<NotEmpty, Object> {

    @Override
    public void initialize(NotEmpty notEmpty) { }

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext cxt) {
        return obj != null && !obj.toString().trim().equals("");
    }

}
+3

@Configuration
@Import(value = MongoAutoConfiguration.class)
public class DatabaseConfiguration extends AbstractMongoConfiguration 
{

  @Resource
  private Mongo mongo;

  @Resource
  private MongoProperties mongoProperties;

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

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

  @Override
  protected String getDatabaseName() {
    return mongoProperties.getDatabase();
  }

  @Override
  public Mongo mongo() throws Exception {
    return mongo;
  }

}
0

Usually @RestRepository converted to the controller, which handles check yourself, except when you override the default behavior and include some @HandleBeforeSave, @HandleBeforeCreate...... in your code.

The solution is to remove @HandleBeforeSave, @HandleBeforeCreate... and then Spring will process the check again.

Or, if you want to save them, you can provide a handler for checking any object, for example:

@Component
@RepositoryEventHandler
public class EntityRepositoryEventHandler {

    @Autowired
    private Validator validator;

    @HandleBeforeSave
    @HandleBeforeCreate
    public void validate(Object o) {
        Set<ConstraintViolation<Object>> violations = this.validator.validate(o);

        if (!violations.isEmpty()) {
            ConstraintViolation<Object> violation = violations.iterator().next();

            // do whatever your want here as you got a constraint violation !

            throw new RuntimeException();
        }
    }
}
0
source

All Articles