[bv-dev] bv-dev] [BVAL-251] Improve Bean Validation support for modularized environments

Gunnar Morling gunnar.morling at googlemail.com
Thu May 17 18:39:01 EDT 2012


Hi,

a friend of mine pointed me to another approach for bootstrapping a
validator factory under OSGi, the "extender pattern" [1].

In that pattern an OSGi bundle can react upon lifecycle events from
other bundles (starting, stopping etc.) and while doing so, also
examine the started/stopped bundle's manifest headers, check for
certain resources etc.

So one could imagine such an extender within a BV provider bundle, which

* examines started application bundles for existence of
META-INF/validation.xml or a custom manifest header marking a bundle
as validation client and
* bootstraps a validation factory when such a bundle is loaded (using
that bundle's class loader).

This significantly reduces the work to be done by the application developer.

I've played with that idea by extending the RI a little bit [2]. I've
defined a custom manifest header,
"Hibernate-Validator-Resource-Bundle" which specifies the names of the
resource bundles to be used by the message interpolator. The extender
within the HV bundle watches for this header and registers a VF if a
bundle is started whose manifest contains that header.

There are also some tests which show the general idea (two OSGi
modules and a test project) [3].

--Gunnar

[1] http://eclipse.dzone.com/articles/osgi-42-extender-pattern-and
[2] https://github.com/gunnarmorling/hibernate-validator/compare/BVAL-251
[3] https://github.com/gunnarmorling/hibernate-validator/compare/BVAL-251#diff-33


2012/5/15 Gunnar Morling <gunnar.morling at googlemail.com>:
> 2012/5/15 Emmanuel Bernard <emmanuel at hibernate.org>:
>>
>> On 15 mai 2012, at 10:51, Hardy Ferentschik wrote:
>>
>>>>>
>>>>> If the application is made up of several modules, the activator of
>>>>> some application module (having dependencies to all other modules and
>>>>> thus seeing all their exported resources) should be in charge of
>>>>> bootstrapping the factory.
>>>>
>>>> Can you detail what you mean by that?
>>>> Should the application developer write a module that will bootstrap Bean Validation? That the thing I want to avoid, having the user do useless heavy lifting.
>>>
>>> I think this is what it all comes down to in a modular environment. Once upon a time I thought you would have one ValidatorFactory within a container and all
>>> modules/apps. But due to class loading and encapsulation of modules/app you effectively need to create a ValidatorFactory for each module/app.
>>>
>>> Is this not also what JBoss AS does? If you deploy an app using for example JPA as per J2EE spec Bean Validation gets enabled and a ValiatorFactory
>>> gets created.
>>
>> s/J2EE/Java EE/
>>
>> But that's the thing, this EG worked his butt off to make the Java EE integration 100% transparent for the application developer. And it was up to us
>> to achieve that and propose things to other EGs.
>>
>> I am already not certain of what modularity gains you (as user), if on top of that the development model is subpar to what Java EE can offer, that would be a big drawback.
>>
>>> In the end it is up to the framework providers to make it as simple as possible to use Bean Validation for modules/apps running within the framework.
>>> All Bean Validation needs to provide is a way to set the class loader.
>>
>> Sure in the end, we will have a very simple ClassloaderService interface of sort, but I'd like to understand fully how that will be used to be sure things will be as good as possible
>> in a modular environment.
>
> As Hardy says, in the end the user needs to provide BV with a class
> loader. Thinking of OSGi, I see two ways atm.:
>
> a) The user indeed bootstraps BV (passing the class loader) and
> registers VF as OSGi service. This would be done using a bundle
> activator roughly like that:
>
> public class Activator implements BundleActivator {
>
>  public void start(BundleContext context) throws Exception {
>
>    ValidatorFactory factory = Validation
>      .byDefaultProvider()
>      .providerResolver( new OsgiProviderResolver() )
>      .configure()
>      .userClassLoader( Activator.class.getClassLoader() )
>      .buildValidatorFactory();
>
>    context.registerService( ValidatorFactory.class.getName(), factory, null );
>  }
>
>  public void stop(BundleContext context) throws Exception {}
> }
>
> AFAICS this would have to be done in the activator of one bundle
> (which can "see" all other bundles of the application).
>
> b) The BV provider's OSGi bundle performs the registration of the VF.
> The required class loader would be provided via a ClassLoaderService,
> for which the user has to register an implementation in his activator:
>
> public class Activator implements BundleActivator {
>
>  public void start(BundleContext context) throws Exception {
>
>      ClassLoaderService cls = new ClassLoaderServiceImpl (
> Activator.class.getClassLoader() );
>      context.registerService( ClassLoaderService.class.getName(), cls, null );
>  }
>
>  public void stop(BundleContext context) throws Exception {}
> }
>
> Judging from the lines of code, to me b) looks simpler. As you say
> it's not zero-config like in JEE, but - based on my limited knowledge
> of the matter - I'm not aware of another (clean) way. In OSGi,
> probably there would be some other approaches possible (using
> fragments etc.), but AFAIK these are more considered hacks by the
> experts.
>
> In both approaches a ValidatorFactory would be available as OSGi
> service to be used in application modules, so the complexity would be
> restricted to one activator. I don't know how it would work in other
> environments (e.g. JBoss modules), but would expect it to be similar.
>
> --Gunnar
>
>> _______________________________________________
>> beanvalidation-dev mailing list
>> beanvalidation-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev



More information about the beanvalidation-dev mailing list