使用 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 验证的主要内容,如果未能解决你的问题,请参考以下文章
org.osgi.framework.storage.clean=onFirstInit 在 Apache Felix OSGi 实现的上下文中是啥意思?
使用 Hibernate Unmanaged JPA 在 Equinox OSGI 框架中获取 EntityManagerFactory
您可以在不使用 JTA 的情况下在 OSGi 环境(如 Karaf)中使用 Hibernate 5.2 StatelessSession 吗?