Spring 在 Groovy 中使用 ElasticSearch 启动:WebClient 不存在异常
Spring Boot with ElasticSearch in Groovy: WebClient not present Exception
我是 运行 一个小型演示 spring-boot 应用程序,我想将我的 url 路由与 elasticsearch 查询连接起来。该应用程序在这些 gradle 依赖项下启动得很好:
implementation('org.springframework.data:spring-data-elasticsearch')
implementation('org.elasticsearch:elasticsearch')
implementation('org.elasticsearch.client:elasticsearch-rest-high-level-client')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.codehaus.groovy:groovy')
只要我添加 class ElasticsearchClientConfig(我还没有使用,刚刚加载):
package me.spring.GroovyDemo.store
import me.spring.GroovyDemo.AppConstants
import org.elasticsearch.client.RestHighLevelClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.data.elasticsearch.client.ClientConfiguration
import org.springframework.data.elasticsearch.client.RestClients
import org.springframework.data.elasticsearch.core.ElasticsearchOperations
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories
@Configuration
@EnableElasticsearchRepositories(basePackages = "me.spring.GroovyDemo")
@ComponentScan(basePackages = ["me.spring.GroovyDemo"])
class ElasticsearchClientConfig {
@Bean
RestHighLevelClient client() {
ClientConfiguration clientConfiguration
= ClientConfiguration.builder()
.connectedTo(AppConstants.ELASTIC_SERVER)
.build()
return RestClients.create(clientConfiguration).rest()
}
@Bean
ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client())
}
}
应用启动失败。
我发现了很多类似的问题。但其中 none 似乎因缺少 Webclient 而失败。我真的不明白我首先需要一个 WebClient 。
异常情况如下:
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.0)
2021-05-27 12:02:32.598 INFO 4462 --- [ main] m.s.GroovyDemo.GroovyDemoApplication : Starting GroovyDemoApplication using Java 1.8.0_292 on vagrant-VirtualBox with PID 4462 (/home/vagrant/GroovyOpenApi/out/production/classes started by vagrant in /home/vagrant/GroovyOpenApi)
2021-05-27 12:02:32.600 INFO 4462 --- [ main] m.s.GroovyDemo.GroovyDemoApplication : No active profile set, falling back to default profiles: default
2021-05-27 12:02:32.890 WARN 4462 --- [kground-preinit] o.s.h.c.j.Jackson2ObjectMapperBuilder : For Jackson Kotlin classes support please add "com.fasterxml.jackson.module:jackson-module-kotlin" to the classpath
2021-05-27 12:02:33.230 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2021-05-27 12:02:33.240 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 Elasticsearch repository interfaces.
2021-05-27 12:02:33.402 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2021-05-27 12:02:33.404 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1 ms. Found 0 Elasticsearch repository interfaces.
2021-05-27 12:02:33.407 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
2021-05-27 12:02:33.409 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1 ms. Found 0 Reactive Elasticsearch repository interfaces.
2021-05-27 12:02:33.799 INFO 4462 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-05-27 12:02:33.807 INFO 4462 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-05-27 12:02:33.807 INFO 4462 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46]
2021-05-27 12:02:33.861 INFO 4462 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-05-27 12:02:33.861 INFO 4462 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1065 ms
2021-05-27 12:02:34.035 WARN 4462 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'client' defined in class path resource [me/spring/GroovyDemo/store/ElasticsearchClientConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.RestHighLevelClient]: Factory method 'client' threw exception; nested exception is java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
2021-05-27 12:02:34.038 INFO 4462 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-05-27 12:02:34.054 INFO 4462 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-27 12:02:34.078 ERROR 4462 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'client' defined in class path resource [me/spring/GroovyDemo/store/ElasticsearchClientConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.RestHighLevelClient]: Factory method 'client' threw exception; nested exception is java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=14=](AbstractBeanFactory.java:335) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.7.jar:5.3.7]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.7.jar:5.3.7]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:337) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1336) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1325) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication$run.call(Unknown Source) [spring-boot-2.5.0.jar:2.5.0]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148) [groovy-3.0.8.jar:3.0.8]
at me.spring.GroovyDemo.GroovyDemoApplication.main(GroovyDemoApplication.groovy:10) [classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.RestHighLevelClient]: Factory method 'client' threw exception; nested exception is java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.7.jar:5.3.7]
... 23 common frames omitted
Caused by: java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:117) ~[na:1.8.0_292]
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125) ~[na:1.8.0_292]
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[na:1.8.0_292]
at sun.reflect.generics.visitor.Reifier.reifyTypeArguments(Reifier.java:68) ~[na:1.8.0_292]
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:138) ~[na:1.8.0_292]
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[na:1.8.0_292]
at sun.reflect.generics.repository.MethodRepository.getReturnType(MethodRepository.java:68) ~[na:1.8.0_292]
at java.lang.reflect.Method.getGenericReturnType(Method.java:255) ~[na:1.8.0_292]
at java.beans.FeatureDescriptor.getReturnType(FeatureDescriptor.java:370) ~[na:1.8.0_292]
at java.beans.Introspector.getTargetEventInfo(Introspector.java:1052) ~[na:1.8.0_292]
at java.beans.Introspector.getBeanInfo(Introspector.java:427) ~[na:1.8.0_292]
at java.beans.Introspector.getBeanInfo(Introspector.java:173) ~[na:1.8.0_292]
at groovy.lang.MetaClassImpl.lambda$addProperties(MetaClassImpl.java:3460) ~[groovy-3.0.8.jar:3.0.8]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_292]
at groovy.lang.MetaClassImpl.addProperties(MetaClassImpl.java:3460) ~[groovy-3.0.8.jar:3.0.8]
at groovy.lang.MetaClassImpl.reinitialize(MetaClassImpl.java:3442) ~[groovy-3.0.8.jar:3.0.8]
at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:3435) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:273) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:315) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:258) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:987) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallStaticSite(CallSiteArray.java:71) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:156) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130) [groovy-3.0.8.jar:3.0.8]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig.client(ElasticsearchClientConfig.groovy:21) ~[classes/:na]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig$$EnhancerBySpringCGLIB$$a214165c.CGLIB$client[=14=](<generated>) ~[classes/:na]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig$$EnhancerBySpringCGLIB$$a214165c$$FastClassBySpringCGLIB$$c29866d5.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.7.jar:5.3.7]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig$$EnhancerBySpringCGLIB$$a214165c.client(<generated>) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_292]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_292]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_292]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_292]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.7.jar:5.3.7]
... 24 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.web.reactive.function.client.WebClient
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_292]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_292]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) ~[na:1.8.0_292]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_292]
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_292]
at java.lang.Class.forName(Class.java:348) ~[na:1.8.0_292]
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114) ~[na:1.8.0_292]
... 60 common frames omitted
Process finished with exit code 1
不知何故我无法创建 ES 客户端 bean。
我的应用程序在包 me.spring.GroovyDemo 中,其他所有内容都在下面。
我尝试添加一些依赖项,例如 webflux 以获取 WebClient,但并没有真正帮助。
启动失败是什么原因?
从堆栈跟踪可以看出,您应该将 spring-web-reactive 缺少的依赖项添加到 Gradle 配置中:
dependencies {
//...
implementation 'org.springframework:spring-web-reactive:5.0.0.M4'
}
我通过添加
得到了你的例子运行
implementation('org.springframework:spring-webflux')
对 WebClient
class 的引用从何而来? Spring 数据 Elasticsearch 构建时具有对 org.springframework:spring-webflux
的 可选 依赖性,因为它包含命令式和反应式设置的代码。 可选 因为我们需要它来构建库,但是当 运行 - 在命令模式下你不需要它。
现在 ClientConfiguration
class 及其构建器有一个方法 withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer)
。此函数编译入库
当 运行 一个命令式、非反应性应用程序在 Java 或 Kotlin 中的 class 路径中没有 webflux 时,一切都很好 - 应用程序本身从未被编译为使用此函数,因此不需要它,并且传递可选依赖项永远不会被解析。只要不使用这些可选依赖项,它们是否在加载的 class 中并不重要 - 否则编译器会抱怨。
在Groovy中这似乎有所不同。这里有一些 Java-bean inspection 运行 on the ClientConfiguration
class 找到上述方法但找不到 WebClient
class,因为那不在 class 路径上。
因此,通过将依赖项添加到 class 路径,此错误会因在 class 路径中具有具有反应性代码的库的成本而消失 - 现在一些 Spring 引导自动配置可能会想从那里捡点东西。
我不知道什么是更好的解决方案,或者如果 groovy 可以更好地处理可选依赖项,我不会使用 groovy。有更多见解的人可能会有更好的答案。
我是 运行 一个小型演示 spring-boot 应用程序,我想将我的 url 路由与 elasticsearch 查询连接起来。该应用程序在这些 gradle 依赖项下启动得很好:
implementation('org.springframework.data:spring-data-elasticsearch')
implementation('org.elasticsearch:elasticsearch')
implementation('org.elasticsearch.client:elasticsearch-rest-high-level-client')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.codehaus.groovy:groovy')
只要我添加 class ElasticsearchClientConfig(我还没有使用,刚刚加载):
package me.spring.GroovyDemo.store
import me.spring.GroovyDemo.AppConstants
import org.elasticsearch.client.RestHighLevelClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.data.elasticsearch.client.ClientConfiguration
import org.springframework.data.elasticsearch.client.RestClients
import org.springframework.data.elasticsearch.core.ElasticsearchOperations
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories
@Configuration
@EnableElasticsearchRepositories(basePackages = "me.spring.GroovyDemo")
@ComponentScan(basePackages = ["me.spring.GroovyDemo"])
class ElasticsearchClientConfig {
@Bean
RestHighLevelClient client() {
ClientConfiguration clientConfiguration
= ClientConfiguration.builder()
.connectedTo(AppConstants.ELASTIC_SERVER)
.build()
return RestClients.create(clientConfiguration).rest()
}
@Bean
ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client())
}
}
应用启动失败。 我发现了很多类似的问题。但其中 none 似乎因缺少 Webclient 而失败。我真的不明白我首先需要一个 WebClient 。 异常情况如下:
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.0)
2021-05-27 12:02:32.598 INFO 4462 --- [ main] m.s.GroovyDemo.GroovyDemoApplication : Starting GroovyDemoApplication using Java 1.8.0_292 on vagrant-VirtualBox with PID 4462 (/home/vagrant/GroovyOpenApi/out/production/classes started by vagrant in /home/vagrant/GroovyOpenApi)
2021-05-27 12:02:32.600 INFO 4462 --- [ main] m.s.GroovyDemo.GroovyDemoApplication : No active profile set, falling back to default profiles: default
2021-05-27 12:02:32.890 WARN 4462 --- [kground-preinit] o.s.h.c.j.Jackson2ObjectMapperBuilder : For Jackson Kotlin classes support please add "com.fasterxml.jackson.module:jackson-module-kotlin" to the classpath
2021-05-27 12:02:33.230 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2021-05-27 12:02:33.240 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 Elasticsearch repository interfaces.
2021-05-27 12:02:33.402 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2021-05-27 12:02:33.404 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1 ms. Found 0 Elasticsearch repository interfaces.
2021-05-27 12:02:33.407 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
2021-05-27 12:02:33.409 INFO 4462 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1 ms. Found 0 Reactive Elasticsearch repository interfaces.
2021-05-27 12:02:33.799 INFO 4462 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-05-27 12:02:33.807 INFO 4462 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-05-27 12:02:33.807 INFO 4462 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46]
2021-05-27 12:02:33.861 INFO 4462 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-05-27 12:02:33.861 INFO 4462 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1065 ms
2021-05-27 12:02:34.035 WARN 4462 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'client' defined in class path resource [me/spring/GroovyDemo/store/ElasticsearchClientConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.RestHighLevelClient]: Factory method 'client' threw exception; nested exception is java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
2021-05-27 12:02:34.038 INFO 4462 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-05-27 12:02:34.054 INFO 4462 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-27 12:02:34.078 ERROR 4462 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'client' defined in class path resource [me/spring/GroovyDemo/store/ElasticsearchClientConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.RestHighLevelClient]: Factory method 'client' threw exception; nested exception is java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=14=](AbstractBeanFactory.java:335) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.7.jar:5.3.7]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.7.jar:5.3.7]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:337) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1336) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1325) [spring-boot-2.5.0.jar:2.5.0]
at org.springframework.boot.SpringApplication$run.call(Unknown Source) [spring-boot-2.5.0.jar:2.5.0]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148) [groovy-3.0.8.jar:3.0.8]
at me.spring.GroovyDemo.GroovyDemoApplication.main(GroovyDemoApplication.groovy:10) [classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.RestHighLevelClient]: Factory method 'client' threw exception; nested exception is java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.7.jar:5.3.7]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.7.jar:5.3.7]
... 23 common frames omitted
Caused by: java.lang.TypeNotPresentException: Type org.springframework.web.reactive.function.client.WebClient not present
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:117) ~[na:1.8.0_292]
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125) ~[na:1.8.0_292]
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[na:1.8.0_292]
at sun.reflect.generics.visitor.Reifier.reifyTypeArguments(Reifier.java:68) ~[na:1.8.0_292]
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:138) ~[na:1.8.0_292]
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[na:1.8.0_292]
at sun.reflect.generics.repository.MethodRepository.getReturnType(MethodRepository.java:68) ~[na:1.8.0_292]
at java.lang.reflect.Method.getGenericReturnType(Method.java:255) ~[na:1.8.0_292]
at java.beans.FeatureDescriptor.getReturnType(FeatureDescriptor.java:370) ~[na:1.8.0_292]
at java.beans.Introspector.getTargetEventInfo(Introspector.java:1052) ~[na:1.8.0_292]
at java.beans.Introspector.getBeanInfo(Introspector.java:427) ~[na:1.8.0_292]
at java.beans.Introspector.getBeanInfo(Introspector.java:173) ~[na:1.8.0_292]
at groovy.lang.MetaClassImpl.lambda$addProperties(MetaClassImpl.java:3460) ~[groovy-3.0.8.jar:3.0.8]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_292]
at groovy.lang.MetaClassImpl.addProperties(MetaClassImpl.java:3460) ~[groovy-3.0.8.jar:3.0.8]
at groovy.lang.MetaClassImpl.reinitialize(MetaClassImpl.java:3442) ~[groovy-3.0.8.jar:3.0.8]
at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:3435) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:273) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:315) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:258) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:987) ~[groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallStaticSite(CallSiteArray.java:71) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:156) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-3.0.8.jar:3.0.8]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130) [groovy-3.0.8.jar:3.0.8]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig.client(ElasticsearchClientConfig.groovy:21) ~[classes/:na]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig$$EnhancerBySpringCGLIB$$a214165c.CGLIB$client[=14=](<generated>) ~[classes/:na]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig$$EnhancerBySpringCGLIB$$a214165c$$FastClassBySpringCGLIB$$c29866d5.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.7.jar:5.3.7]
at me.spring.GroovyDemo.store.ElasticsearchClientConfig$$EnhancerBySpringCGLIB$$a214165c.client(<generated>) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_292]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_292]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_292]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_292]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.7.jar:5.3.7]
... 24 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.web.reactive.function.client.WebClient
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_292]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_292]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) ~[na:1.8.0_292]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_292]
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_292]
at java.lang.Class.forName(Class.java:348) ~[na:1.8.0_292]
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114) ~[na:1.8.0_292]
... 60 common frames omitted
Process finished with exit code 1
不知何故我无法创建 ES 客户端 bean。 我的应用程序在包 me.spring.GroovyDemo 中,其他所有内容都在下面。 我尝试添加一些依赖项,例如 webflux 以获取 WebClient,但并没有真正帮助。
启动失败是什么原因?
从堆栈跟踪可以看出,您应该将 spring-web-reactive 缺少的依赖项添加到 Gradle 配置中:
dependencies {
//...
implementation 'org.springframework:spring-web-reactive:5.0.0.M4'
}
我通过添加
得到了你的例子运行implementation('org.springframework:spring-webflux')
对 WebClient
class 的引用从何而来? Spring 数据 Elasticsearch 构建时具有对 org.springframework:spring-webflux
的 可选 依赖性,因为它包含命令式和反应式设置的代码。 可选 因为我们需要它来构建库,但是当 运行 - 在命令模式下你不需要它。
现在 ClientConfiguration
class 及其构建器有一个方法 withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer)
。此函数编译入库
当 运行 一个命令式、非反应性应用程序在 Java 或 Kotlin 中的 class 路径中没有 webflux 时,一切都很好 - 应用程序本身从未被编译为使用此函数,因此不需要它,并且传递可选依赖项永远不会被解析。只要不使用这些可选依赖项,它们是否在加载的 class 中并不重要 - 否则编译器会抱怨。
在Groovy中这似乎有所不同。这里有一些 Java-bean inspection 运行 on the ClientConfiguration
class 找到上述方法但找不到 WebClient
class,因为那不在 class 路径上。
因此,通过将依赖项添加到 class 路径,此错误会因在 class 路径中具有具有反应性代码的库的成本而消失 - 现在一些 Spring 引导自动配置可能会想从那里捡点东西。
我不知道什么是更好的解决方案,或者如果 groovy 可以更好地处理可选依赖项,我不会使用 groovy。有更多见解的人可能会有更好的答案。