How would I specify a Hibernate "@Pattern" annotation using a regular expression from a .properties file or database

Code Jockey picture Code Jockey · Jan 24, 2012 · Viewed 14.9k times · Source

Situation: I would like to perform Hibernate Validation based upon user properties (to allow different validation rules for input based upon a user's account data) - I think it must be possible to use a .properties file to specify a particular regular expression, but I can't figure out what is wrong:

My current method of specifying a validation regex pulls that regex from a constant in a particular interface file (to keep everything together) and plugs it in as a constant in an @Pattern() annotation for each variable - e.g. for the variable workPhone:

@Column(name = "WORK_PHONE")
@NotEmpty(message = "{ContactInfo.workPhone.notEmpty}")
@Pattern(regexp = PHONE_NUMBER_PATTERN_SL, message = "{ContactInfo.workPhone.regexp.msg}")
@Size(max = 10, message = "{ContactInfo.workPhone.size}")
protected String                workPhone;

...where the regex is stored in the static final String PHONE_NUMBER_PATTERN_SL and all the {ContactInfo.workPhone...} calls come from a .properties file:

ContactInfo.workPhone.notEmpty=Please enter your phone number.
ContactInfo.workPhone.regexp.msg=Invalid characters entered in phone. Use this format XXX-XXX-XXXX.
ContactInfo.workPhone.size=Phone can not be longer than 10 digits.

Unfortunately, this arrangement makes the validation pattern application-wide (compiled), as I can't figure a way to change it for a different user in a different company, location, employment position, etc. To make it possible to differentiate based upon this info, I'd like to also store the regex in the properties file, and I try to include it this way:

ContactInfo.workPhone.regexp=\d{3}-\d{3}-\d{4}

while including the reference in the annotation from the third line in the first code listing:

@Pattern(regexp = "{ContactInfo.workPhone.regexp}", message = "{ContactInfo.workPhone.regexp.msg}")

I would then switch out the properties files for different occasions, such as to allow/require a non-U.S. telephone number format.

Question: Is it possible to do what I want to do? Is there a better way to specify the pattern (which might allow even a database call instead of a properties file)?

Additionally, I'm not the best at this (as I'm taking over from another developer), so if someone could merely point me to a focused resource concerning the use of the @Pattern annotation or other Hibernate regex validation markup, then that might give me all the info I need.

TL;DR: Is it possible to use a dynamically-set or modified value for the expression used in Hibernate Pattern Validation rather than a predefined and precompiled constant?

Answer

Gunnar picture Gunnar · Jan 27, 2012

Within annotations you can only refer to constant expressions, so loading values from a property file or database wouldn't work here.

You could use the API for dynamic constraint declaration introduced in Hibernate Validator 4.2 which allows to define constraints at runtime. Your example might look like that:

String dynamicPattern = ...;

ConstraintMapping mapping = new ConstraintMapping();
mapping.type( ContactInfo.class )
    .property( "workPhone", FIELD )
    .constraint( new PatternDef().regexp( dynamicPattern ) );

HibernateValidatorConfiguration config = 
    Validation.byProvider( HibernateValidator.class ).configure();
config.addMapping( mapping );

Validator validator = config.buildValidatorFactory().getValidator();