8

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?

Code Jockey
  • 6,611
  • 6
  • 33
  • 45

1 Answers1

6

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();
Gunnar
  • 18,095
  • 1
  • 53
  • 73
  • My impression was that the 3 'messages' in my example were being called in a way that would allow them to be changed without recompiling - perhaps that is not the case (I haven't tested it) - this looks promising, but is based on several things I don't quite understand just yet - I'll have to try it out with crossed fingers - Thanks! – Code Jockey Jan 30 '12 at 20:24
  • I hesitate to mark as answer because I have not yet had a chance to test anything - I've been told we are proceeding with only using annotations (I guess because they're pretty??)... looks very promising, though, so at least a +1 - Thanks for your time! perhaps I'll have time to come back at some point and actually test it, or maybe I'll just want my "accepted answers" count up (who knows?) and I'll come back and accept it :D – Code Jockey Feb 10 '12 at 16:32
  • @Gunnar After 10 years, do you know, now, if we can something like this ? @Pattern(regexp = "${my.regex.charOrNumber}") https://stackoverflow.com/questions/59581979/how-to-read-the-regex-pattern-from-property-file-in-spring-boot – DonFabiolas May 10 '22 at 14:51