使用 Hibernate 实现在 OSGI 上下文中使用 CXF 进行 Bean 验证

Posted

技术标签:

【中文标题】使用 Hibernate 实现在 OSGI 上下文中使用 CXF 进行 Bean 验证【英文标题】:Bean Validation with CXF in OSGI context using Hibernate Implementation 【发布时间】:2015-06-18 19:54:12 【问题描述】:

我正在尝试在 OSGI 上下文中使用 bean 验证(使用 Hibernate 实现)。

我的蓝图文件中的设置如下:

 <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"/>

这样我在 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

众所周知,BeanValidationProvider 对 OSGI 不太友好,所以我尝试直接在我的蓝图中引导一个提供程序。

我知道我可以让工厂做以下事情:

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

自定义ValidationProviderResolver:

public class HibernateValidationProviderResolver implements ValidationProviderResolver   

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

这样我可以获得验证器和工厂,但我无法像在非 OSGi 环境中那样将其注入 InInterceptor。

所以我基本上是在这里寻找解决方法!

有关 CXF 中 BeanValidation 的文档,请参见 this 链接。

【问题讨论】:

【参考方案1】:

刚刚找到一个可行的解决方案:

我的蓝图文件:

<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"/>

我的 CustomBeanValidationProvider:

public class CustomBeanValidationProvider extends BeanValidationProvider 

    public CustomBeanValidationProvider() 
            super(new HibernateValidationProviderResolver());
    

还有我正在使用的自定义 ValidationProviderResolver:

public class HibernateValidationProviderResolver implements ValidationProviderResolver   

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

希望对某人有所帮助!

【讨论】:

以上是关于使用 Hibernate 实现在 OSGI 上下文中使用 CXF 进行 Bean 验证的主要内容,如果未能解决你的问题,请参考以下文章

OSGi 和 Hibernate - 不适合的驱动程序

org.osgi.framework.storage.clean=onFirstInit 在 Apache Felix OSGi 实现的上下文中是啥意思?

Hibernate、JDBC 驱动程序和 OSGi 问题

使用 Hibernate Unmanaged JPA 在 Equinox OSGI 框架中获取 EntityManagerFactory

您可以在不使用 JTA 的情况下在 OSGi 环境(如 Karaf)中使用 Hibernate 5.2 StatelessSession 吗?

具有运行时 pojos 的带有 Hibernate 的 OSGi 片段包