0

为了在 CDI 环境中使用 Elasticsearch 存储库,我遵循了有关 CDI 集成的 Spring Data Elasticsearch文档。

简而言之,我已经使用 Maven 导入了相关依赖项,并尝试将 ElasticsearchOperations 作为 bean 提供。

结果是 ElasticsearchRepositoryExtension 在尝试初始化潜在的 Elasticsearch 存储库时抛出 UnsatisfiedResolutionException。在执行 ElasticsearchRepositoryExtension 之前,可能没有初始化 ElasticsearchOperations bean。

这是错误还是配置错误?

  • JDK 8
  • Java EE 7
  • 野蝇 8.1.0

Maven依赖

   <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-elasticsearch</artifactId>
        <version>1.1.0.RELEASE</version>
   </dependency>

Java 代码

    @Produces
    @ApplicationScoped
    public ElasticsearchOperations createElasticsearchTemplate() {
        return new ElasticsearchTemplate(NodeBuilder.nodeBuilder().local(true).node().client());
    }

堆栈跟踪

11:13:32,658 ERROR [org.jboss.as.server] (management-handler-thread - 1) JBAS015860: Redeploy of deployment "application.war" was rolled back with the following failure message:
{"JBAS014671: Failed services" => {"jboss.deployment.unit.\"application.war\".WeldStartService" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"application.war\".WeldStartService: Failed to start service
    Caused by: org.jboss.weld.exceptions.DefinitionException: Exception List with 1 exceptions:
Exception 0 :
javax.enterprise.inject.UnsatisfiedResolutionException: Unable to resolve a bean for 'org.springframework.data.elasticsearch.core.ElasticsearchOperations' with qualifiers [@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()].
        at org.springframework.data.elasticsearch.repository.cdi.ElasticsearchRepositoryExtension.createRepositoryBean(ElasticsearchRepositoryExtension.java:76)
        at org.springframework.data.elasticsearch.repository.cdi.ElasticsearchRepositoryExtension.afterBeanDiscovery(ElasticsearchRepositoryExtension.java:63)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstanceWithSpecialValue(MethodInjectionPoint.java:93)
        at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:266)
        at org.jboss.weld.event.ExtensionObserverMethodImpl.sendEvent(ExtensionObserverMethodImpl.java:125)
        at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:253)
        at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:232)
        at org.jboss.weld.event.ObserverNotifier.notifyObserver(ObserverNotifier.java:169)
        at org.jboss.weld.event.ObserverNotifier.notifyObservers(ObserverNotifier.java:128)
        at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:102)
        at org.jboss.weld.bootstrap.events.AbstractContainerEvent.fire(AbstractContainerEvent.java:63)
        at org.jboss.weld.bootstrap.events.AbstractDefinitionContainerEvent.fire(AbstractDefinitionContainerEvent.java:35)
        at org.jboss.weld.bootstrap.events.AfterBeanDiscoveryImpl.fire(AfterBeanDiscoveryImpl.java:55)
        at org.jboss.weld.bootstrap.WeldStartup.deployBeans(WeldStartup.java:372)
        at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:79)
        at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:92)
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948)
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
4

3 回答 3

0

我自己做了一些研究,发现出了什么问题。

bean 是从 CDI 中挑选出来的(实际上是从 Elasticsearch CDI 扩展中挑选出来的ElasticsearchOperations),并放入一个带有 bean 限定符键的映射(默认情况下是@Any@Default)。这里的问题是toString()在设置密钥之前调用该方法,这使得限定符的顺序被硬编码在密钥中。

在稍后阶段,发现存储库 bean 具有不同顺序(@Default@Any)的相同限定符。因此,不可能ElasticsearchOperations从地图中获取以将其与存储库相关联。

ElasticsearchOperations通过在存储库和生产者方法中设置自定义限定符,我设法克服了这个问题。通过这样做,预选赛的顺序现在是相同的。但随后又出现了一个问题……

是时候提一下我还使用了 Spring Data JPA 和相应的 CDI 扩展。现在的问题是,两个扩展程序都会处理每个存储库 bean(无论它们实现什么 Repostiory 接口)导致两次注册同一个 bean,这是不可接受的。

于 2014-11-21T09:11:31.650 回答
0

包含您的生产者方法的类是否具有定义 bean 的注释(例如@Dependent)?如果没有,生产者方法将被 CDI 1.1 忽略。

于 2014-11-18T20:14:56.090 回答
0

由于焊接错误,Spring Data CDI 扩展全部损坏:https ://issues.jboss.org/browse/WELD-2185

Weld 使用 ArraySet 将限定符存储在 Bean 中。将限定符存储到 Bean 并基于带有限定符的 ProcessAnnotatedType 注册自定义 Bean 实例的扩展不再能够使用简单的匹配来通过其限定符获取 Bean。

我通过更改在 CdiRepositoryExtension 类中设置所有限定符的方式临时修复了它。

                Set<Annotation> qualifiers = bean.getQualifiers().stream()
                    .sorted((e1, e2) -> Integer.compare(e1.hashCode(),
                            e2.hashCode())).collect(Collectors.toSet());

对于 Spring Data Couchbase,完整代码可在此处获得:https ://github.com/ldoguin/wildfly-quickstart-spring-data/blob/master/src/main/java/org/springframework/data/couchbase/repository/cdi /CouchbaseRepositoryExtension.java

于 2016-06-24T09:02:59.720 回答