Make the “propertyPath” available via the “HibernateMessageInterpolatorContext”
Description
Attachments
2
Activity
Show:
Fixed
Details
Details
Assignee

Reporter

Components
Fix versions
Priority
Created October 18, 2018 at 1:48 PM
Updated September 28, 2020 at 3:32 PM
Resolved September 28, 2020 at 3:32 PM
We use bean validation intensively for validation of incoming SOAP messages. These SOAP messages contain an (hierarchical) object graph (no backlinks), consisting out of entities (beans) and attributes (bean-properties).
Our failure messages are standardized. They typically start with the failing constraint property and refer to other relevant properties. We have written many custom validators for our domain.
For example, the following
ValidationMessages.properties
entry describes such a message, called by a customnl.bro.dto.common.validation.AssertEmpty
validator.ValidationMessages.properties
nl.bro.dto.common.validation.AssertEmpty.message=${validatedAttribute} is missing: ${refAttribute} = ${indicationYesNoValue} determines that it must be present.
Now, all el-expressions value expressions are populated are resolved via the custom
AssertEmpty
,Constraint
annotated annotation. Their values are asserted by the customAssertEmptyValidator
.The intention is that
${validatedAttribute}
and${refAttribute}
are replaced by a parameter. The parameter reflects their position in the object graph and is used in theValidationMessages.properties
resource bundle as key to find the proper name.So, suppose that we evaluate an object:
Car.java
Car { String hornPresent; Steer steer; }
Steer.java
Steer { Horn horn; }
To achieve this we have written one custom message interpolator. This interpolates the message to:
Intermediate Interpolation Result
nl.bro.dto.common.validation.AssertEmpty.message={Car.steer.horn} is missing: {Car.hornPresent} = ${indicationYesNoValue} determines that it must be present.
However, we can’t fully solve this directly in a custom message interpolator. For this we require the
rootBean
and thepropertyPath
. Both are present on theConstraintViolation
but not on theMessageInterpolator.Context
. TherootBeanType
however can be resolved via unwrapping to theHibernateMessageInterpolatorContext
but thepropertyPath
can’t.The current solution entails:
Having a custom message interpolator, storing the
ConstraintDescriptor
as key and theHibernateMessageInterpolatorContext
as value in aThreadLocal
.We wrap all relevant HV classes (
ValidatorFactory
,Validator
,ConstraintViolation
) to get to thepropertyPath
and apply post-interpolation on the violation message by using theConstraintDescriptor
in theConstraintViolation
to get theMessageInterpolator.Context
belonging to that particularConstraintViolation
. No need to say this is cumbersome and could be far more simple if we have the proper information available in the custom message interpolator.NB: I can see that in the interpolation the
ConstraintViolation
is created almost at the same point as theMessageInterpolator.Context
.