问题
Relatively simple probably. The Java 7 documentation for the ConstraintViolationBuilder interface specifies:
addNode
ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name)Deprecated. since 1.1 - replaced by addPropertyNode(String) and addBeanNode()
Adds a node to the path the ConstraintViolation will be associated to. name describes a single property. In particular, dot (.) is not allowed.
"Now" the documentation also includes the methods mentioned.
I had a requirement to validate some data using this, and the code is running on a JBoss AS 7.1.1-Final.
The "Getting Started"-Page of jBoss 7 mentions: "Java SE 7 can be used with JBoss AS 7". Now what I want to achieve is simple:
I have a Validator implements ConstraintValidator<AnnotationType, DomainClass>
, there I want to create a nice-looking ConstraintViolationException, that can be nicely handled by JSF / Primefaces to show a message and mark a field as invalid, but alas:
@Override
public boolean isValid(DomainClass instance, ConstraintValidatorContext context) {
// validation logic
if (valid) {
return true;
} else {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode("locationName").addConstraintViolation();
return false;
}
}
And here's where it gets problematic... As mentioned in the documentation linked above: addPropertyNode()
is only available as of version 1.1 of the Bean Validation. Unfortunately JBoss AS 7 just includes BeanValidation version 1.0 (as visible in Getting Started Page).
I analyzed stacktraces of working validations, and saw, the propertyPath in ConstraintViolationImpl instances (as used by hibernate) uses multiple dots.
The documentation explicitly states: "In particular, dot (.) is not allowed.".
There's two possiblities now:
- Change the application server to Wildfly (or similar, where JSR 349 is implemented)
- Solve the problem using JSR 303 only using the
addNode()
-method.
For the purpose of this question, we rule out possibility 1 (impractical, possible required work).
How would I do this using Bean Validation 1.0?
In particular what is required in the placeholder for this to work properly with JSF Faces-Validation:
@Override
public boolean isValid(DomainClass instance, ConstraintValidatorContext context) {
// validation logic
if (valid) {
return true;
} else {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message)
.addNode(/* Some awesome String */).addConstraintViolation();
return false;
}
}
Or last but not least, I am totally ... and overread a simpler approach to this :(
回答1:
It seems the last option actually is the correct one :( I am dumb I am missing the forest for the trees...
What is not quite obvious from the documentation: The .addNode()
calls are supposed to be chained!
@Override
public boolean isValid (DomainClass instance, ConstraintValidatorContext context) {
//validation logic
if (valid) {
return true;
} else {
context.disableDefaultConstraintViolation();
context.buildConstrainViolationWithTemplate(message)
.addNode("tree").addNode("nodes").addNode("to")
.addNode("property").addConstraintViolation();
return false;
}
}
This solves my problem. Additionally I want to mention here, that the JSR-303 Section 4.2 - Constraint Violation defines the correct rules for building the propertyPath:
Path
is made of Node
s and is built according to the following rules:
- if the failing object is the root object, a Node with name set to null is added to the Path.
- When an association is traversed:
- a Node object whose name equals the name of the association property (field name or Java Bean property name) is added to Path
- if the association is a List or an array, the following Node object added contains the index value in getIndex.
- if the association is a Map, the following Node object added (representing a given map entry) contains the key value in getKey
- for all Iterable or Map, the following Node object added is marked as inIterable (isInIterable)
- For a property level constraint (field and getter)
- a Node object is added to Path whose name equals the name of the property (field name or Java Bean property name)
- the property path is considered complete
- For a class level constraint:
- a Node object is added to Path whose name is null
- the property path is considered complete
来源:https://stackoverflow.com/questions/25997520/addpropertynode-equivalent-in-version-1-0