How to validate @NotBlank for simple string parameter directly with javax?
Asked Answered
G

1

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')
}
Goatsbeard answered 28/8, 2018 at 12:56 Comment(7)
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.Tingle
@Tingle Good point. I updated the question and tags. Better?Goatsbeard
Yes, better :) Have you seen this link? "Secondly, we have to provide a MethodValidationPostProcessor bean"Tingle
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.Ondrea
@Tingle 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.Goatsbeard
@Ondrea 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)Goatsbeard
I created a minimal working example that also fails as I described above and added it to my question.Goatsbeard
S
3

Did you annotated your class with @Validated?

For example:

@Validated
public class Controller {

   public ResponseEntity registration(@Valid @NotBlank String password) {}
}
Soberminded answered 28/8, 2018 at 13:3 Comment(5)
I didn't but I tested it with @Validated and that doesn't change anything. Should it work this way?Goatsbeard
I have a working example which you can refer, here - github.com/arpitaggarwal/jsr-303/blob/master/src/main/java/com/…Soberminded
@Valid on his custom object works (apparently), so that shouldn't be itOndrea
@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.Goatsbeard
As a extra note keep in mind that in Spring, validation annotations such as '@NotBlank' and '@NotNull' applied to method parameters are processed by Spring’s AOP proxy mechanism. However, this mechanism does not apply to static methods because Spring cannot create a proxy around static methods.Forbore

© 2022 - 2024 — McMap. All rights reserved.