Javax.Validation - allow null but validate if the value is not

This works out of the box as you would expect e.g. in Spring Boot, 2.1.0 (and also with Quarkus FWIW).

Here is the full version of the POJO (please notice, that I promote an immutable class):

package sk.ygor.stackoverflow.q53207105;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class SomePOJO {

    @NotNull
    @Size(min =2, max=50)
    @Pattern(regexp="^[A-Za-z \\s\\-]*$")
    private final String country;

    @Size(min =2,max=50)
    @Pattern(regexp="^[A-Za-z \\s\\-]*$")
    private final String state;

    public SomePOJO(String country, String state) {
        this.country = country;
        this.state = state;
    }

    public String getCountry() {
        return country;
    }

    public String getState() {
        return state;
    }

}

If you are concerned with empty strings you can accept them by adding a trailing pipe to the regular expression (which will mean "this expression OR empty string"), although this will break the Size() requirement:

@Pattern(regexp="^[A-Za-z \\s\\-]*$|")

Full version of the controller:

package sk.ygor.stackoverflow.q53207105;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
public class ExampleController {

    @RequestMapping(path = "/q53207105", method = RequestMethod.POST)
    public void test(@Valid @RequestBody SomePOJO somePOJO) {
        System.out.println("somePOJO.getCountry() = " + somePOJO.getCountry());
        System.out.println("somePOJO.getState() = " + somePOJO.getState());
    }

}

Calling http://localhost:8080/q53207105 with:

{
    "country": "USA",
    "state": "California" 
}

Prints:

somePOJO.getCountry() = USA
somePOJO.getState() = California

Calling http://localhost:8080/q53207105 with:

{
    "country": "USA",
}

Prints:

somePOJO.getCountry() = USA
somePOJO.getState() = null

If you tell me your Spring boot version, I might help more.


You can use Alternation Constructs in regular expressions to separate multiple patterns. Just separate patterns using pipe '|' i.e. append regex for null/empty string based on your requirement to your existing regex. Sample below:

^(?:[A-Za-z \\s\\-]*|)$

May not be exact, but hope you got the idea.


Your POJP will work as expected when there is a StringTrimmerEditor is set in an InitBinder.

You can have an application wide InitBinder, having a class like below in your project.

@ControllerAdvice
public class CustomControllerAdvice {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }
}