javax validation OneOf constraint - bean-validation

Is there an annotation in javax validation, so it should constraint that value is one of predefined values.
Example
#OneOf(values = "12-14m, 16m, 18m")
private String size;

No, there is no such constraint and you have to write it's own.
Here is the example that does mostly the same but opposite #DenyValues:
annotation usage on a class: https://github.com/php-coder/mystamps/blob/66a2254e6d78c03d0b50531752d860efe784a1fd/src/main/java/ru/mystamps/web/controller/dto/AddCountryForm.java#L87
annotation definition: https://github.com/php-coder/mystamps/blob/66a2254e6d78c03d0b50531752d860efe784a1fd/src/main/java/ru/mystamps/web/support/beanvalidation/DenyValues.java#L35-L44
validator implementation: https://github.com/php-coder/mystamps/blob/66a2254e6d78c03d0b50531752d860efe784a1fd/src/main/java/ru/mystamps/web/support/beanvalidation/DenyValuesValidator.java#L26-L51

If you are using hibernate-validator, you can declare new annotation using #ConstraintComposition. This is a good example here.

Related

Haxe Reflection Method to Access a Static Field?

I'm looking for a way to use reflection to get and set static fields of a Class. Is that possible, or is that too dynamic for Haxe?
You mean, if it's too static for Reflection :)? No, it is not
var cl = Type.resolveClass("MyClass");
trace(Reflect.fields(cl));
trace(Reflect.field(cl, "field"));
trace(Reflect.setField(cl, "field", 0));
In addition, you can get all static fields of a class using Type.getClassFields() (or Type.getInstance() for instance ones). Take a look here : https://api.haxe.org/Type.html

Lombok Annotations with DynamoDB annotations

I have a DAO like:
#Getter
#Setter
#DynamoDBTable(tableName="tableName")
public class DAO {
#DynamoDBHashKey
private String field1;
#DynamoDBIndexHashKey(globalSecondaryIndexName="index_name")
#DynamoDBRangeKey
private String field2;
}
Problem is when I am trying to use the DAO to make a load call using DynamoDBMapper with field1 as the hash key to obtain the item, it throws a DynamoDBException saying:
Null key found for public DAO.getField2()
but actually table has value corresponding to field2.
Question, is this because of Lombok annotation instead of the manual mutator code and or in general we use Lombok and DynamoDBAnnotations together?
Here is a little more of an explanation and a TL;DR
You are calling the load method, which is mapped to the GetItem call. The DynamoDBMapper is trying to map that request based on your annotations. Your class has the #DynamoDBRangeKey annotation, and the GetItem call needs the full primary key to get the item, which means that the mapper will build out the primary key for the object.
Since Lombok has already generated your code (before runtime), it is not affecting the annotations you have already placed. And also since your annotations are on the fields rather than applying them to the getters, the mapper it is calling the generated Lombok getter. When it tries to serialize into a request, however, that getter is returning null because you have only set the hashKey.
TL;DR: load() translates to GetItem API which requires both the hashKey and the rangeKey since both annotations are present on your class.

Java bean validation: Optional fields annotation

I would like to treat some fields as Optional, if the value is null or blank don't go with the checks of the other annotated constraints.
There is some way to achieve it!
Reading this tread Java bean validation: Enforce a #Pattern only when the property is not blank don't seems cover my needs.
Below an example to explain what I mean:
public class Test {
#Max(value=100) // <--mandatory
private int parA;
#Optional // <-Custom annotation telling "do not check other if null or blank"
#Range(min=10, max=200)
private int parB;
...
}
Now you can!
https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#example-container-element-constraints-optional
public Optional<#Size(min=1, max=128) String> first_name = Optional.empty();
You cannot do what you want with Bean Validation. You cannot establish a "connection" between two constraints placed on a property. Also, if I understand correctly, your #Optional is not even a constraint annotation, but rather just a marker annotation. Note though, that all default constraints are implemented in a way that a constraint validates for null values. So in most cases you get what you want either way. In your example, you also have the problem that you are dealing with a primitive int. This will always have a value, so the range constraint would be evaluated either way.

Javax validation - constraint composition

i have a little problem with implementing properly my own validation annotation.
Here is sample code:
#Pattern(regexp="[0-9]*")
#Size(min=3, max=10)
#Constraint(validatedBy = SampleValidator.class)
#Documented
#Target({ANNOTATION_TYPE, METHOD, FIELD, CONSTRUCTOR, PARAMETER})
#Retention(RUNTIME)
public #interface MyAnnotation {
String message() default "Wrong!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
#Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
#Retention(RUNTIME)
#Documented
#interface List {
MyAnnotation[] value();
}
}
My problem is, I want my annotation to work in the way, that #Size and #Pattern annotation run first and if they're valid then (and only then) run validator provided by #Constraint annotation (SampleValidator.class).
Put it simple:
I want to run SampleValidator only if #Pattern and #Size are valid
(I implementes SampleValidator just as additional validator that should be called only in some specific circumstances)
How can I obtain such behaviour?
Thanks in advance!
Obviously, I can't do anything like that:
#GroupSequence({ Step1.class, Step2.class })
#Constraint(validatedBy = SampleValidator.class, groups = Step1.class) // no 'groups' attribute
#Size(min=3, max=10, groups = Step2.class)
#Pattern(regexp="[0-9]*", groups = Step2.class)
#Documented
#Target({ANNOTATION_TYPE, METHOD, FIELD, CONSTRUCTOR, PARAMETER})
#Retention(RUNTIME)
public #interface MyAnnotation {
...
}
Try adding the #ReportAsSingleViolation annotation. According to the specification:
"More specifically, if a composed constraint is marked as #ReportAsSingleViolation, the evaluation of the composing constraints stops at the first failing constraint and the error report corresponding to the composed constraint is generated and returned."
http://beanvalidation.org/1.1/spec/#constraintsdefinitionimplementation-constraintcomposition
The answer is only partly correct. Yes #ReportAsSingleViolation that only one single violations will be generated and validation will stop after first failure in this case. However, the specification gives no guarantee in which order constraints are evaluated. It could be the composing constraints first or the validator specified via #Constraint. If anything you would rely on some implementation detail which could change any time. Also there is no order defined in which #Size and #Pattern are evaluated. Bottom line, you cannot achieve your wanted behaviour with constraint composition.
If you want to guarantee a sequenced execution you need to look at the GroupSequence feature.

Adding annotations with javassist removes previous code

I'm trying to add some annotations to classes while they are loaded.
For that I've wrote a java agent transformer which gets the class bytecode upon loading and can change it.
When I run the following code the new annotation apears on the class but all previous annotation and fields / methods are removed.
CtClass ctClass = classPool.makeClass(new java.io.ByteArrayInputStream(classFileBuffer));
ClassFile classFile = clazz.getClassFile();
ConstPool constPool = classFile.getConstPool();
AnnotationsAttribute attr= new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
javassist.bytecode.annotation.Annotation annotation = new javassist.bytecode.annotation.Annotation(type, constPool);
attr.setAnnotation(annotation);
classFile.addAttribute(attr);
classFileBuffer = ctClass.toBytecode();
Where classFileBuffer is the byte array which is returned to the class loader.
If anyone has an idea why the previous class annotations and code are removed it will be very helpful.
Thanks,
Avner
setAnnotation takes only one parameter which is of type Annotation, and it erases all the others annotations. If you want to add an annotation to the existing ones, use setAnnotations instead. It takes an array of Annotation so you have first to build the array by gathering all the existing annotations (using getAnnotations) then add the Annotation at the end, then call the method.
a setAnnotation(annotation) call is equivalent to setAnnotations(new Annotation[] { annotation })

Resources