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]
2012/5/15 Emmanuel Bernard <emmanuel(a)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(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/beanvalidation-dev