1. Referencing the custom field. I could be wrong (and haven't tested it yet) but it doesn't look like indexed bean notation for collections/maps is supported for either XML or programmatic config. By "indexed bean notation" I mean defining a property name as e.g. customFieldValueMap["InvoiceReferenceNumber"] or myArray. It looks like collections and maps are expected to be homogeneous for validation purposes. Is there any way to do this?
You are correct. The "indexed" notation you are suggesting is not supported. Constraints are configured per collection. You could write your own custom constraint you are placing on your map. You could offer some default implementation and a way for tenants to provide extensions (eg via sub-classing).
2. Scoping a validator by tenant. In everything I have seen, constraint configuration is used to create a ValidatorFactory, but you cannot add additional constraints to a Validator obtained from it. ValidatorFactory.usingContext() allows you switch out the MessageInterpolator, TraversableResolver, and ConstraintValidatorFactory, but it doesn't allow you to load additional constraints. Assuming we could solve #1, I still don't see how you can load config dynamically for each tenant without recreating the ValidatorFactory and thus loading all of the standard/static config again as well.
Normally you would create ValidatorFactory
per tenant. Extending on the idea above, with the custom constraint approach you could even write a custom ConstraintValidatorFactory
which returns a tenant specific constraint validator for your custom constraint and otherwise delegates to the default constraint validator factory. With approach you could indeed use ValidatorFactory#usingContext
To solve #1, I thought about pulling out the custom field values ourselves and using this API call on javax.validation.Validator:
validateValue(java.lang.Class<T> beanType, java.lang.String propertyName, java.lang.Object value, java.lang.Class<?>... groups)
How would you configure the constraints though? I cannot see how validateValue
is going to help you.