7

I want to validate GET / POST request for spring-boot controller classes with the javax.validation-api annotations.

For classes @Valid and @NotBlank for attributes of that class work perfectly.

The following works as expected:

public class Registration {
    @NotBlank
    private String name;
}

public ResponseEntity registration(@Valid @RequestBody Registration registration) {}

So now I only have a single string as parameter and would like to validate it.

Ist this possible?

The following doesn't work as expected (doesn't validate anything):

public ResponseEntity registration(@Valid @NotBlank String password) {}

It seems like such a simple requirement but I couldn't find anything on the internet or on Stackoverflow.


For reproduction I created a MWE (java 10, gradle project):

After starting the project call localhost:8080/registration?test= with POST for example with Postman. The parameter "test" will be empty but the method despite @NotBlank will be entered.

A POST call to localhost:8080/container fails as expected.

MweController.java

import javax.validation.constraints.*;

import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

@RestController
public class MweController {

    @CrossOrigin(origins = "http://localhost:3000")
    @PostMapping(value = "/registration")
    public ResponseEntity registration(@NotNull @NotBlank @NotEmpty String test) {
        System.out.println("Parameter: " + test);
        // This should return Bad Request but doesn't!
        return new ResponseEntity(HttpStatus.OK);
    }

    @CrossOrigin(origins = "http://localhost:3000")
    @PostMapping(value = "/container")
    public ResponseEntity container(@Valid Container test) {
        System.out.println("Parameter: " + test);
        // This returns Bad Request as expected
        return new ResponseEntity(HttpStatus.OK);
    }

    class Container {
        public Container(String test){
            this.test = test;
        }

        @NotBlank
        private String test;
    }

}

MweApplication.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MweApplication {

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

build.gradle

buildscript {
    ext {
        springBootVersion = '2.1.0.M2'
    }
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.mwe'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 10

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
    maven { url "https://repo.spring.io/milestone" }
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-webflux')
}
Arpit Aggarwal
  • 27,626
  • 16
  • 90
  • 108
Spenhouet
  • 6,556
  • 12
  • 51
  • 76
  • Maybe it would help if you could write that you are trying to use your code in EJB environment or with Spring, the solution can be different. The type of the planned application server would be good to know too. – m4gic Aug 28 '18 at 13:04
  • @m4gic Good point. I updated the question and tags. Better? – Spenhouet Aug 28 '18 at 13:08
  • Yes, better :) Have you seen [this](https://www.baeldung.com/javax-validation-method-constraints) link? "Secondly, we have to provide a MethodValidationPostProcessor bean" – m4gic Aug 28 '18 at 13:10
  • It feels weird to use `@Valid` on a built-in object - I think it does nothing, as it would just trigger validation of it's insides (and there are no validation annotations inside). Also, do other validators work, like `@NotNull`? You could lack implementation for `@NotBlank` (though you should have some exceptions in the log if that were the case) on your classpath. – Deltharis Aug 28 '18 at 13:12
  • @m4gic No I didn't see that before. The "Single Parameter Constraints" sounds like exactly what I'm looking for. From their example it seems like a simple NotNull in front of the parameter is all I need but it doesn't work. I just tested it. So now I'm not sure if it is a bug related to my setup. – Spenhouet Aug 28 '18 at 13:17
  • @Deltharis NotBlank works for custom classes so there should be a existing implementation. Also NotNull and other constraints work for custom classes. Just for single parameters nothing works. No exceptions in the log (all logs on debug mode) – Spenhouet Aug 28 '18 at 13:19
  • I created a minimal working example that also fails as I described above and added it to my question. – Spenhouet Aug 28 '18 at 13:45

1 Answers1

3

Did you annotated your class with @Validated?

For example:

@Validated
public class Controller {

   public ResponseEntity registration(@Valid @NotBlank String password) {}
}
Arpit Aggarwal
  • 27,626
  • 16
  • 90
  • 108
  • I didn't but I tested it with @Validated and that doesn't change anything. Should it work this way? – Spenhouet Aug 28 '18 at 13:10
  • I have a working example which you can refer, here - https://github.com/arpitaggarwal/jsr-303/blob/master/src/main/java/com/arpit/jsr/controller/CalculationController.java – Arpit Aggarwal Aug 28 '18 at 13:11
  • `@Valid` on his custom object works (apparently), so that shouldn't be it – Deltharis Aug 28 '18 at 13:13
  • 1
    @Arpit I don't know why `@Validated` didn't work in my first test. I just created a MWE and tested `@Validated` again and it worked this time. Then tried it again with my application and it also worked. So it was the solution after all. I also found that `@Valid` is not necessary for single parameter constraints. – Spenhouet Aug 28 '18 at 14:02