Javax.Validation - Allow Null But Validate If the Value Is Not

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



Leave a reply



Submit