I am trying to use javax validations on DTO. But I want these validations to be applied based on the operation for which this DTO is used.
Lets say I have the following DTO:
@Getter @Setter
public class CustomerDTO {
@NotNull
private String id;
@NotNull
private String name;
}
I am using the same DTO for Create, Update and Delete operations. Incase of Update and Delete operation I want "id" to be NotNull, but in Create it has to be null.
But since I am using the same DTO, and on using @Valid annotation at controller level, it applies to all the attributes. And the following API fails as "id" cannot be null
public CustomerDTO createCustomer(@Valid CustomerDTO customer, BindingResults results){
if(results.hasErrors()){
throw IllegalArgumentsException("Required params are mising");
}
customerService.create(customer);
}
Since you are using Spring, you can use its @Validated
annotation and system.
How it works: every validation annotation has a field groups
. This field allows you to determine when the validation should be done, based on a class. What you can do is the following:
ValidationGroups
class with all validation groups you need. Example:import javax.validation.groups.Default;
/**
* Utility classes to distinct CRUD validations.<br>
* <br>
* Used with the
* {@link org.springframework.validation.annotation.Validated @Validated}
* Spring annotation.
*/
public final class ValidationGroups {
private ValidationGroups() {
}
// Standard groups
public interface Create extends Default {};
public interface Replace extends Default {};
public interface Update extends Default {};
public interface Delete extends Default {};
}
id
field like the following:@Null(
groups = Create.class
)
@NotNull(
groups = { Update.class, Delete.class }
)
private String id;
@Validated
annotation rather than the @Valid
one:public CustomerDTO createCustomer(@Validated(Create.class) CustomerDTO customer, BindingResult results) {
if(results.hasErrors()){
throw IllegalArgumentsException("Required params are mising");
}
customerService.create(customer);
}
// Etc. You can put multiple groups like @Validated({ Update.class, Delete.class })
NOTE about the extends javax.validation.groups.Default
in ValidationGroups
:
If you don't extend your Create
class with javax.validation.groups.Default
, the validation rule will not be done if you use the @Validated
annotation without argument.
// @Validated without argument validate every annotation with the "Default" group
public void test(@Validated MyForm form, BindingResult results) {
// ...
}
You can inherit validation. For example if you want your Replace
to validate all your Create
validation rules, make Replace
inherit Create
.
public interface Create extends Default {};
public interface Replace extends Create {};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With