Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Validator for custom fields with dynamic config?
PostPosted: Wed May 02, 2012 7:59 pm 
Newbie

Joined: Wed May 02, 2012 5:17 pm
Posts: 2
Any tips on how to approach this would be much appreciated: We are building a multi-tenant B2B application, and part of the requirements include custom fields. That means a customer can define additional custom fields for a domain object, with meta-data about how each field should be handled. One of those pieces of meta-data is validation rules. We would really like to standardize on JSR303 and Hibernate Validator for all of our standard fields, but we would like to use the same validation framework for both standard and custom fields. The trick here is how to use Hibernate Validator for custom fields.

We already have an approach for persistence/mapping of these custom fields with Hibernate ORM. The tables don't really matter for discussing the validation, but for clarity the custom fields would be exposed on a given entity pojo something like this:
Map<String, String> customFieldValueMap;

...where the custom field definition's logical name is the map key (e.g. "InvoiceReferenceNumber"), and the custom field value associated with that particular entity record is the map value (e.g. "INV-5005").

The fact that Hibernate Validator supports XML and programmatic configuration seemed promising at first. I thought perhaps we could either A) store an XML snippet for the custom fields' validation or B) use our own schema to persist the config along with the programmatic configuration API to configure a per-tenant validator. There appear to be a couple of problems here:

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[5]. It looks like collections and maps are expected to be homogeneous for validation purposes. Is there any way to do this?

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.

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)

However we still need to solve #2, also I'm not sure if using our own convention for propertyName will work or if Hibernate Validator will consider it not a valid object property.

I'm going to start testing out these scenarios, but if anyone has any experience in this area or suggestions as to approach, that would be great.


Top
 Profile  
 
 Post subject: Re: Validator for custom fields with dynamic config?
PostPosted: Thu May 03, 2012 5:14 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
barefoot wrote:
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[5]. 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).

barefoot wrote:
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.


barefoot wrote:
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.

--Hardy


Top
 Profile  
 
 Post subject: Re: Validator for custom fields with dynamic config?
PostPosted: Thu May 03, 2012 2:09 pm 
Newbie

Joined: Wed May 02, 2012 5:17 pm
Posts: 2
Thank you very much for your reply. I think perhaps I wasn't as clear as I could have been. My primary concern isn't with creating custom constraints/validators--that I have done before and it is perfectly straightforward. Even creating validators with different behavior for different tenants is possible, like you said. My concern is with configuring the standard constraints/validators for use on custom fields for different tenants.

Quote:
You could offer some default implementation and a way for tenants to provide extensions (eg via sub-classing).

The idea here isn't for tenants to be able to create their own custom validators with java code, just that they can configure usage of the standard ones via a UI that we will implement. All we want to do is specify existing standard constraints/validators on custom/dynamic fields from config they select in our UI.

Quote:
Normally you would create ValidatorFactory per tenant.

That seems prohibitively expensive. Wouldn't it mean reloading all of the constraints for all of our standard objects and fields for every tenant? Imagine many customers/tenants in the same multi-tenant web application. You might get e.g. 50 requests in a row, each for a different tenant. Unless the ValidatorFactory instances would use cached versions of config and constraint validators....I guess this is something I could just test out.

Quote:
How would you configure the constraints though? I cannot see how validateValue is going to help you.

Sorry I should have been more specific, and again this still wouldn't solve the scoping per tenant problem. What I meant was that this: Supposed I configured, either via XML or programmatically, a constraint and gave it a property name like "customFieldValueMap["InvoiceReferenceNumber"]" (or similar). Then I use my own utility to extract the value (e.g. Spring's bean utilities). What I was wondering is if Hibernate Validator will immediately complain that this is an invalid property, or will it it only throw an exception if you actually ask it to extract the property value. Obviously this is something I could easily test out but got busy with something else. Apologies for that, I'll post back after I've tested this and other scenarios.

Thanks again for the feedback.


Top
 Profile  
 
 Post subject: Re: Validator for custom fields with dynamic config?
PostPosted: Fri May 04, 2012 4:30 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
barefoot wrote:
Thank you very much for your reply. I think perhaps I wasn't as clear as I could have been. My primary concern isn't with creating custom constraints/validators--that I have done before and it is perfectly straightforward. Even creating validators with different behavior for different tenants is possible, like you said. My concern is with configuring the standard constraints/validators for use on custom fields for different tenants.

Sure, and I am just trying to see things from a different angle and potentially give you some ideas on how to approach the issue differently. The problem afaiu is that you don't want to apply constraints on properties (entity fields or getters), but on elements of a collection or map. The latter is NOT supported by Bean Validation and not configurable.

Quote:
Quote:
How would you configure the constraints though? I cannot see how validateValue is going to help you.

Sorry I should have been more specific, and again this still wouldn't solve the scoping per tenant problem. What I meant was that this: Supposed I configured, either via XML or programmatically, a constraint and gave it a property name like "customFieldValueMap["InvoiceReferenceNumber"]" (or similar). Then I use my own utility to extract the value (e.g. Spring's bean utilities). What I was wondering is if Hibernate Validator will immediately complain that this is an invalid property, or will it it only throw an exception if you actually ask it to extract the property value. Obviously this is something I could easily test out but got busy with something else. Apologies for that, I'll post back after I've tested this and other scenarios.

It seems you see the scoping per tenant as biggest problem whereas my point is that adding a constraints only for "customFieldValueMap["InvoiceReferenceNumber"]" is just not possible. Multiple tenants or not.

--Hardy


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.