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.
Validate only if the field is not Null
Instead of using @Digit
, I would like to suggest you to use @Pattern(message="YOUR_MESSAGE", regexp="REGULAR_EXPRESSION")
Main reason is that we show message for such set of values for which we want to restrict the user, here in your condition message is displayed for that value which you don't want to restrict.
So You wants to restrict user to enter anything other than blank space and numbers.Make a regular expression for that and use @Pattern with that.
For your case :
@Pattern(message="YOUR_MESSAGE", regexp="^(\\s*|\\d{10,15})$")
How to enable javax annotations when value not null and disabled when value is null?
I found the answer and it's that almost all java validation annotations accepts null so if my value is null it's going to accept it otherwise it will check.
What is point of constraint validation @Null?
You may want to use @Null
in combination with "Validation Group" to validate the null constraint only in certain cases.
Good explanation and example on validation groups provided by Hibernate
You will define validation group as simple interface
public interface FirstSave {}
then use it in constraint
public class MyClass {
@Null(groups = FirstSave.class)
private LocalDate lastUpdate;
}
then if lastUpdate
is not null
, calling validator.validate(myClassInstance)
will not produce constraint violation (Default group was used), but calling validator.validate(myClassInstance, FirstSave.class)
will.
You also have the possibility to provide your own implementation on how to use the annotation, i.e. I've seen validation method being annotated with @Null
where null
returned by the method meant that everything is alright. In the background there was probably custom implementation on what to do if annotated method returned not null result, but I didn't go deep into the code...
Spring Boot validation - one from two not null
I'll try to implement it for you (even if I'm without an IDE).
Inside ConstraintValidator#initialize
you can get a hold of the configured fields' names which cannot be null
.
@Override
public void initialize(final CombinedNotNull combinedNotNull) {
fields = combinedNotNull.fields();
}
Inside ConstraintValidator#isValid
you can use those fields' names to check the Object
fields.
@Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
final BeanWrapperImpl beanWrapper = new BeanWrapperImpl(value);
for (final String f : fields) {
final Object fieldValue = beanWrapper.getPropertyValue(f);
if (fieldValue == null) {
return false;
}
}
return true;
}
Annotation:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = CombinedNotNullValidator.class)
public @interface CombinedNotNull {
String message() default "username or email is required";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* Fields to validate against null.
*/
String[] fields() default {};
}
The annotation could be applied as
@CombinedNotNull(fields = {
"fieldName1",
"fieldName2"
})
public class MyClassToValidate { ... }
To learn how to create a Class-level constraint annotation, refer always to the official documentation. Docs
spring boot component bean validation @Positive not working but @NotNull works fine
It works as it should. The validator associated with @Positive
, the PositiveValidatorForLong
accepts null
values as valid. So it will only validate actual values, not null
.
Basically you need them both to fullfil your requirements, so both @Positive
and @NotNull
to only allow positive values.
pro-tip: As you already have the spring-boot-starter-validation
dependency you don't need the additional validation-api
and hibernate-validator
dependencies, those are added already.
Does the following validation mean that the field cannot be null? ( @Size annotation )
If you look at the documentation of the annotation Size (http://docs.oracle.com/javaee/6/api/javax/validation/constraints/Size.html)
You can read "null elements are considered valid."
Therefore you need to specify @NotNull on the top of your field.
You have two alternatives:
@NotNull
@Size(min = 2, max = 50)
private Integer age;
Or like Riccardo F. suggested:
@NotNull @Min(13) @Max(110)
private Integer age;
Related Topics
How to Bypass Google Recaptcha for Testing Using Selenium
Rounding to the Nearest Hundered-Thousandths
How to Find an Object in an Arraylist by Property
Java Socket Api: How to Tell If a Connection Has Been Closed
How to Convert Minutes to Hours and Minutes (Hh:Mm) in Java
Regular Expression for Excluding Special Characters
Regex to Match a String Not Starting or Ending With a Pattern
Hibernate Error Executing Ddl Via Jdbc Statement
What Is the Most Elegant Way to Check If All Values in a Boolean Array Are True
Dynamically Change Application.Properties Values in Spring Boot
How to Prevent Duplicate Results in Hibernate
@Responsebody , Responseentity Spring Return Object as Json
Spring Junit: How to Mock Autowired Component in Autowired Component
Java.Lang.Illegalargumentexception: Not a Managed Type: Class
How to Have Each Record of Json on a Separate Line
In Firebase After Uploading Image How to Get Url
How to Update Thousands of Records into MySQL Db in Milliseconds