Search code examples
hibernateosgicxfbean-validationblueprint-osgi

Bean Validation with CXF in OSGI context using Hibernate Implementation


I am trying to use bean validation (using Hibernate implementation) in an OSGI context.

The setup is the following in my blueprint file:

 <jaxrs:server address="/myPath" id="myserverid">
        <jaxrs:serviceBeans>
            <ref component-id="myRestImpl"/>
        </jaxrs:serviceBeans>
        <jaxrs:providers>
        </jaxrs:providers>
        <jaxrs:inInterceptors>
             <ref component-id="validationInInterceptor" />
        </jaxrs:inInterceptors>
    </jaxrs:server>

<bean id="validationInInterceptor" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
    <property name="provider" ref="validationProvider" />
</bean>


<bean id="validationProvider" class="org.apache.cxf.validation.BeanValidationProvider"/>

This way I am getting the following error in Karaf:

Status: Failure
Blueprint
Exception: 
Error when instantiating bean validationProvider of class class org.apache.cxf.validation.BeanValidationProvider
org.osgi.service.blueprint.container.ComponentDefinitionException: Error when instantiating bean validationProvider of class class org.apache.cxf.validation.BeanValidationProvider
        at org.apache.aries.blueprint.container.BeanRecipe.getInstance(BeanRecipe.java:333)
        at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:806)
        at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:787)
        at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:79)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:88)
        at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:245)
        at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:183)
        at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:681)
        at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:378)
        at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:269)
        at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:276)
        at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:245)
        at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:235)
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)
        at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)
        at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1103)
        at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:695)
        at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:483)
        at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4403)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:2092)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:942)
        at org.apache.karaf.features.internal.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:469)
        at org.apache.karaf.features.internal.FeaturesServiceImpl.installFeatures(FeaturesServiceImpl.java:428)
        at org.apache.karaf.features.internal.FeaturesServiceImpl.installFeature(FeaturesServiceImpl.java:363)
        at org.apache.karaf.features.internal.FeaturesServiceImpl.installFeature(FeaturesServiceImpl.java:352)
        at Proxyf683a9dd_0ed3_4f63_a285_89f7c23ba8dc.installFeature(Unknown Source)
        at org.apache.karaf.features.command.InstallFeatureCommand.doExecute(InstallFeatureCommand.java:62)
        at org.apache.karaf.features.command.FeaturesCommandSupport.doExecute(FeaturesCommandSupport.java:38)
        at org.apache.karaf.shell.console.AbstractAction.execute(AbstractAction.java:33)
        at org.apache.karaf.shell.console.OsgiCommandSupport.execute(OsgiCommandSupport.java:39)
        at org.apache.karaf.shell.commands.basic.AbstractCommand.execute(AbstractCommand.java:33)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.apache.aries.proxy.impl.ProxyHandler$1.invoke(ProxyHandler.java:54)
        at org.apache.aries.proxy.impl.ProxyHandler.invoke(ProxyHandler.java:119)
        at org.apache.karaf.shell.console.commands.$BlueprintCommand1653298420.execute(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.apache.aries.proxy.impl.ProxyHandler$1.invoke(ProxyHandler.java:54)
        at org.apache.aries.proxy.impl.ProxyHandler.invoke(ProxyHandler.java:119)
        at org.apache.karaf.shell.console.commands.$BlueprintCommand1653298420.execute(Unknown Source)
        at org.apache.felix.gogo.runtime.CommandProxy.execute(CommandProxy.java:78)
        at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:477)
        at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:403)
        at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)
        at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:183)
        at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:120)
        at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:89)
        at org.apache.karaf.shell.console.impl.jline.ConsoleImpl$DelegateSession.execute(ConsoleImpl.java:497)
        at org.apache.karaf.shell.console.impl.jline.ConsoleImpl.run(ConsoleImpl.java:198)
        at java.lang.Thread.run(Thread.java:745)
        at org.apache.karaf.shell.console.impl.jline.ConsoleFactoryService$3.doRun(ConsoleFactoryService.java:118)
        at org.apache.karaf.shell.console.impl.jline.ConsoleFactoryService$3$1.run(ConsoleFactoryService.java:109)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.apache.karaf.jaas.modules.JaasHelper.doAs(JaasHelper.java:47)
        at org.apache.karaf.shell.console.impl.jline.ConsoleFactoryService$3.run(ConsoleFactoryService.java:107)
Caused by: javax.validation.ValidationException: Unable to create a Configuration, because no Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
        at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:271)
        at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:110)
        at org.apache.cxf.validation.BeanValidationProvider.<init>(BeanValidationProvider.java:45)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at org.apache.aries.blueprint.utils.ReflectionUtils.newInstance(ReflectionUtils.java:329)
        at org.apache.aries.blueprint.container.BeanRecipe.newInstance(BeanRecipe.java:962)
        at org.apache.aries.blueprint.container.BeanRecipe.getInstance(BeanRecipe.java:331)
        ... 64 more

It is known that the BeanValidationProvider is not very OSGI friendly so I am trying to bootstrap a provider directly in my blueprint.

I know I can get a factory doing the following:

Configuration<?> configuration = Validation.byDefaultProvider().providerResolver(
        new HibernateValidationProviderResolver()
    ).configure();
ValidatorFactory instance = configuration.buildValidatorFactory();

The Custom ValidationProviderResolver:

public class HibernateValidationProviderResolver implements ValidationProviderResolver {  

    @Override  
    public List getValidationProviders() {  
        List providers = new ArrayList(1);  
        providers.add(new HibernateValidator());  
        return providers;  
    }  
}  

This way I can get a both a validator and a factory but I am unable to inject it somehow in the InInterceptor like its supposed to in an non-OSGi environment.

So I'm basically looking for a workaround here!

See this link for the documentation of BeanValidation in CXF.


Solution

  • Just found out a working solution:

    My blueprint file:

    <jaxrs:server address="/myPath" id="myserverid">
            <jaxrs:serviceBeans>
                <ref component-id="myRestImpl"/>
            </jaxrs:serviceBeans>
            <jaxrs:providers>
            </jaxrs:providers>
            <jaxrs:inInterceptors>
                 <ref component-id="validationInInterceptor" />
            </jaxrs:inInterceptors>
        </jaxrs:server>
    
    <bean id="validationInInterceptor" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
        <property name="provider" ref="validationProvider" />
    </bean>
    
    
    <bean id="validationProvider" class="foo.bar.mycompany.CustomBeanValidationProvider"/>
    

    My CustomBeanValidationProvider:

    public class CustomBeanValidationProvider extends BeanValidationProvider {
    
        public CustomBeanValidationProvider() {
                super(new HibernateValidationProviderResolver());
        }
    }
    

    And the custom ValidationProviderResolver I'm using:

    public class HibernateValidationProviderResolver implements ValidationProviderResolver {  
    
        @Override  
        public List getValidationProviders() {  
            List providers = new ArrayList(1);  
            providers.add(new HibernateValidator());  
            return providers;  
        }  
    } 
    

    Hope It will help someone !