简述
使用Spring boot 与>cassandra-driver-core时启动出现异常。
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.datastax.driver.core.Session]: Factory method 'createCluster' threw exception; nested exception is java.lang.NoClassDefFoundError: com/codahale/metrics/JmxReporter
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
... 38 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/codahale/metrics/JmxReporter
at com.datastax.driver.core.Metrics.<init>(Metrics.java:146)
at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1667)
at com.datastax.driver.core.Cluster.init(Cluster.java:214)
at com.datastax.driver.core.Cluster.connectAsync(Cluster.java:387)
at com.datastax.driver.core.Cluster.connect(Cluster.java:338)
at com.crm.tool.config.CbaseConfig.createCluster(CbaseConfig.java:50)
at com.crm.tool.config.CbaseConfig$$EnhancerBySpringCGLIB$$6bf97e8e.CGLIB$createCluster$0(<generated>)
at com.crm.tool.config.CbaseConfig$$EnhancerBySpringCGLIB$$6bf97e8e$$FastClassBySpringCGLIB$$e91419f0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at com.crm.tool.config.CbaseConfig$$EnhancerBySpringCGLIB$$6bf97e8e.createCluster(<generated>)
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:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 39 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.codahale.metrics.JmxReporter
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 55 common frames omitted
Spring boot 版本:2.2.6.RELEASE
cassandra-driver-core:3.9.0
cassandra配置
@Bean
public Session createCluster(@Autowired CbaseProperty cbaseProperty) {
PoolingOptions poolingOptions = new PoolingOptions();
poolingOptions.setConnectionsPerHost(HostDistance.LOCAL, 4, 10)
.setConnectionsPerHost(HostDistance.REMOTE, 2, 4);
String[] hosts = cbaseProperty.getAddresses().split(",");
poolingOptions.setPoolTimeoutMillis(300000);
Cluster cluster = Cluster.builder()
.addContactPoints(hosts).
.withCredentials(cbaseProperty.getUsername(), cbaseProperty.getPassword())
.withPoolingOptions(poolingOptions).build();
log.info("------>>连接Cbase成功");
return cluster.connect("tt");
}
问题分析
当Spring Boot自动配置Cassandra Cluster bean 时使用spring.data.cassandra.jmx-enabled该属性。通过扩展AbstractReactiveCassandraConfiguration,关闭此自动配置,而使用Cluster所创建的bean AbstractClusterConfiguration的超类AbstractReactiveCassandraConfiguration。结果,该属性无效。
有两种方法可以解决问题:
- 删除您的AbstractReactiveCassandraConfiguration子类,并使用各种spring.data.cassandra.*属性来配置。
- 重写cluster上AbstractClusterConfiguration的CassandraConfig,使用super.cluster()拿到CassandraClusterFactoryBean,然后调用setJmxReportingEnabled(false)返回之前在工厂bean。
解决方案
创建连接时加入withoutJMXReporting,上面的连接代码调整如下
Cluster cluster = Cluster.builder()
.addContactPoints(hosts).withoutJMXReporting()
.withCredentials(cbaseProperty.getUsername(), cbaseProperty.getPassword())
.withPoolingOptions(poolingOptions).build();