How to add additional attributes to validator in jsr 303? - java

While writing my custom annotation and validator I faced with problem:
My code for annotation:
#Documented
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
#Constraint(validatedBy = NumericValidator.class)
public #interface Numeric {
String message() default "{constraint.postcode}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int digitCount();
}
So that as you can see I need the addition parameter "digitCount". But this parameter is not mandatory so that I can use validation without, but according to this annotation I have to specify it anyway. I'd like to provide some default value for this parameter, and actually I have no idea how to do this.

Just provide a magic number for the default and ignore any annotation with the magic number. I used -1 as the magic number in this example:
#Documented
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
#Constraint(validatedBy = NumericValidator.class)
public #interface Numeric {
String message() default "{constraint.postcode}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int digitCount() default -1;
}

Related

Can I create custom validation annotation that inherits from javax.constrains annotations

I'm wondering if it's possible to do something like:
#Min(1)
#Max(100)
public #interface ValidationForX {}
and then
#ValidationForX
int X;
For some reason #Min and #Max are applicable on annotations so I'm assuming it should be possible
I want to hide this validation behind one annotation because I want to reuse it
Thanks for your help!
You annotation must look like this:
#Min(1)
#Max(100)
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
#Retention(RUNTIME)
#Documented
#Constraint(validatedBy = {})
public #interface ValidationForX {
String message() default "value should be greater or equal than 1 and less or equal than 100.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Read more about composing constraints here: https://www.baeldung.com/java-bean-validation-constraint-composition
You can directly use #Min and #Max annotation on top of the field which you want to validate.
Something like this:
#Max(value=100)
#Min(value=1)
int X;

Changing default group in custom constraint annotations

I have a working custom class level constraint that validates all annotations that do not belong in a group. How can I change that to validate a specific group with that constraint?
This is the annotation class I have:
#Target({TYPE, ANNOTATION_TYPE})
#Retention(RUNTIME)
#Constraint(validatedBy = CheckCase.class)
#Documented
public #interface ValidName {
String message() default "{message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
#Target({TYPE, ANNOTATION_TYPE})
#Retention(RUNTIME)
#Documented
#interface List {
ValidName[] value();
}
}
Right now, the validation works only if I use:
#CheckCase(message = "Error message")
I would like to use this:
#CheckCase(message = "Error message", groups = CheckCaseGroup.class)
Do I have to change something in the following line?
Class<?>[] groups() default {};
Separate question:
If I run the validator without passing in a group, will it go through all validations including the ones that have a group, or will it go only through the ones that don't have a specified group? For example:
will running this:
validator.validate(inputData);
go through this annotations:
#NotBlank(groups = CheckCaseGroup.class)
or only this:
#NotBlank()

Combining custom constraint validator annotation

So I have created a custom constraint validator annotation like so:
#Documented
#Constraint(validatedBy = PostcodeValidator.class)
#Target( { ElementType.METHOD, ElementType.FIELD })
#Retention(RetentionPolicy.RUNTIME)
public #interface Postcode {
String message() default "not a well-formed postcode";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
and I wanted to use it in combination with others like so:
#NotEmpty
#Postcode
private final String postcode;
But when attempting to test this I get the following:
java.lang.IllegalStateException: Duplicate key not a well-formed postcode
I was expecting it to fail the #NotEmpty constraint.
I know I can use composition to include one constraint within the other, but my question is, is it possible to use them as I am? And if so, what am I doing wrong?
Cheers,

Can I add a bean validation annotation with group?

I want to build a NotNull check that only work on Create group, so I can write like this
#Data
public static class TestDto {
#NotNullOnCreate
// #NotNull(groups = Create.class) // instead of this
private String id;
}
I create the NotNullOnCreate like this
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
#Retention(RUNTIME)
#Documented
#Repeatable(NotNullOnCreate.List.class)
#ReportAsSingleViolation
#Constraint(validatedBy = {})
#NotNull(groups = Create.class)
#interface NotNullOnCreate {
String message() default "{javax.validation.constraints.NotNull.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
#Retention(RUNTIME)
#Documented
#interface List {
NotNullOnCreate[] value();
}
}
This doesn't work, because composing constraint annotation's (see ConstraintDescriptorImpl#createComposingConstraintDescriptor) group will be set to host annotation's group('Default').
I also tried this Class<?>[] groups() default {Create.class};, but this is not allowed, the default group must empty.
How can I achieve this ? I don't want to write the group everywhere.
EDIT
Create HV-1355 Constraint annotation with explicit groups
Wrote a workable demo project hv-annotation-with-group
This is not possible at the moment. If you like, open an issue in the Hibernate Validator issue tracker and we can explore this feature.

Java Constraint Annotations: Passing Parameter Value To Composite Constraint

I'm trying to create my own composite validation annotation to validate a String - so far it is made up of the annotations #NotNull, #NotBlank and #Size
However, I do not want to leave these at default values and want to be able to pass in a parameter value, for example if I do #ValidString (min = 1, max = 50), then the #Size annotation can read these values - is this possible?
My constraint -
#NotNull()
#NotBlank()
#Size()
#Constraint(validatedBy = ValidStringValidator.class)
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
#Retention(RUNTIME)
public #interface ValidString {
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int min() default 1;
int max() default 255;
}
You may use OverridesAttribute
#Size(min=1, max=255)
#Retention(RUNTIME)
#Target({ TYPE, FIELD })
#Constraint(validatedBy={})
public #interface ValidString {
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
#OverridesAttribute(constraint=Size.class, name="min")
int min() default 1;
#OverridesAttribute(constraint=Size.class, name="max")
int max() default 255;
}
No, but your annotation can contain other annotations, e.g.
#NotNull()
#NotBlank()
#Constraint(validatedBy = ValidStringValidator.class)
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
#Retention(RUNTIME)
public #interface ValidString {
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Size size() default #Size(/*enter default size arguments here*/);
}

Categories

Resources