21

I updated my project to spring-boot Version 2.1.0.RELEASE.
Now i get the following error:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.cassandra.ReactiveSession]: Factory method 'reactiveSession' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'session' defined in class path resource [ch/sbb/kat/fc/config/CassandraConfig.class]: Invocation of init method failed; 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.lambda$instantiate$2(ConstructorResolver.java:615)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:614)
    ... 120 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'session' defined in class path resource [ch/sbb/kat/fc/config/CassandraConfig.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: com/codahale/metrics/JmxReporter
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:339)
    at ch.sbb.kat.fc.config.CassandraConfig$$EnhancerBySpringCGLIB$$a22674d7.session(<generated>)
    at org.springframework.data.cassandra.config.AbstractCassandraConfiguration.getRequiredSession(AbstractCassandraConfiguration.java:66)
    at org.springframework.data.cassandra.config.AbstractReactiveCassandraConfiguration.reactiveSession(AbstractReactiveCassandraConfiguration.java:47)
    at ch.sbb.kat.fc.config.CassandraConfig$$EnhancerBySpringCGLIB$$a22674d7.CGLIB$reactiveSession$7(<generated>)
    at ch.sbb.kat.fc.config.CassandraConfig$$EnhancerBySpringCGLIB$$a22674d7$$FastClassBySpringCGLIB$$7973a63.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
    at ch.sbb.kat.fc.config.CassandraConfig$$EnhancerBySpringCGLIB$$a22674d7.reactiveSession(<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)
    ... 123 more
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:1501)
    at com.datastax.driver.core.Cluster.init(Cluster.java:208)
    at com.datastax.driver.core.Cluster.connectAsync(Cluster.java:376)
    at com.datastax.driver.core.Cluster.connect(Cluster.java:332)
    at org.springframework.data.cassandra.config.CassandraCqlSessionFactoryBean.connect(CassandraCqlSessionFactoryBean.java:89)
    at org.springframework.data.cassandra.config.CassandraCqlSessionFactoryBean.afterPropertiesSet(CassandraCqlSessionFactoryBean.java:82)
    at org.springframework.data.cassandra.config.CassandraSessionFactoryBean.afterPropertiesSet(CassandraSessionFactoryBean.java:59)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.lambda$invokeInitMethods$5(AbstractAutowireCapableBeanFactory.java:1795)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1794)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741)
    ... 143 more
Caused by: java.lang.ClassNotFoundException: com.codahale.metrics.JmxReporter
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 155 more

Using the property introduced in this issue https://github.com/spring-projects/spring-boot/issues/14778 seems to have no effect to solve my issue.

How can i disable jmx for cassandra?

My current cassandra config looks like this:

@Configuration
@EnableReactiveCassandraRepositories({"repository"})
public class CassandraConfig extends AbstractReactiveCassandraConfiguration {

    @Value("${cassandra.host}")
    private String host;

    @Override
    protected String getKeyspaceName() {
        return "keyspace";
    }

    @Override
    public String[] getEntityBasePackages() {
        return new String[]{"model"};
    }

    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.CREATE_IF_NOT_EXISTS;
    }

    @Override
    public String getContactPoints() {
        return host;
    }
}
locohost
  • 308
  • 1
  • 2
  • 8
  • What is `ch.sbb.kat.fc.config.CassandraConfig` doing? Judging by its name, I would guess that you're configuring Cassandra manually. As a result, Boot's auto-configuration will have backed off and, therefore, the property will have no effect. – Andy Wilkinson Nov 01 '18 at 14:55
  • @AndyWilkinson CassandraConfig extends AbstractReactiveCassandraConfiguration I overwrite keyspace, contactpoints, entitybasepackage and schema action. The cluster bean is created by spring. – locohost Nov 02 '18 at 09:49

5 Answers5

33

The spring.data.cassandra.jmx-enabled property is used when Spring Boot is auto-configuring a Cassandra Cluster bean. By extending AbstractReactiveCassandraConfiguration, you are switching off this auto-configuration in favour of the Cluster bean that's created by AbstractClusterConfiguration which is a super-class of AbstractReactiveCassandraConfiguration. As a result, the property has no effect.

There are two ways that you can fix your problem:

  1. Remove your AbstractReactiveCassandraConfiguration sub-class and use the various spring.data.cassandra.* properties to configure things instead.
  2. Override cluster on AbstractClusterConfiguration in CassandraConfig, call super.cluster() to get the CassandraClusterFactoryBean and then call setJmxReportingEnabled(false) on the factory bean before returning it.

Alternatively, if you are not using Dropwizard elsewhere in your application, you may be able to downgrade to an older version that is compatible with Cassandra's JMX reporting by overriding the dropwizard-metrics.version property in your pom.xml or build.gradle.

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
  • Thanks for the helpful answer. – locohost Nov 02 '18 at 15:02
  • 1
    The downgrade hint from the ticket: The problem is that cassandra-driver-core 3.6.0 depends on dropwizard version 3.2.2. Version 4.0.3 includes a breaking change which causes class not found errors. – kisna Dec 17 '18 at 21:17
  • 1
    For those using TestContainers, beware that the `CassandraContainer` uses JMX Reporting when executing CQL init scripts : https://github.com/testcontainers/testcontainers-java/issues/1011 – Michael Técourt Dec 26 '18 at 16:42
24

instead of overriding cluster as mentionned by Andy Wilkinson, you could alternatively override getMetricsEnabled so that always returns false.

@Override
protected boolean getMetricsEnabled() { return false; }
Heny Kamoun
  • 256
  • 1
  • 5
  • Thank you for pointing this out. I was looking for methods to override the value too but always looked for something with jmx in its name ;) This is also more convenient than getting the cluster from the superclass – locohost Nov 07 '18 at 09:43
  • You're welcome. The default implementation of `cluster` calls `getMetricsEnabled`. By overriding only `getMetricsEnabled`, we can keep the default implementation (and behavior) of `cluster` – Heny Kamoun Nov 08 '18 at 09:26
  • It's a cleaner way to disable metrics, love it. – Marco Capo Apr 22 '19 at 17:37
16

I tried the the answers here, I don't know how but error still persisted. I read this from docs.datastax.com , where they talked about Moving JMX reporting in Metrics 4 to a separate module, metrics-jmx. Which they made clear that it might cause issues/errors.

To fix this, I just had to call this method .withoutJMXReporting() as in the below.

Cluster cluster = Cluster.builder()
        .withoutJMXReporting()
        .build();

You can follow quietly here

Young Emil
  • 2,220
  • 2
  • 26
  • 37
6

Including old version of library also fixes problem:

implementation("io.dropwizard.metrics:metrics-core:3.2.2")

Jemshit
  • 9,501
  • 5
  • 69
  • 106
1

@Bean public CassandraClusterFactoryBean cluster() { CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean(); cluster.setContactPoints(environment.getProperty("spring.data.cassandra.contact-points")); cluster.setPort(Integer.parseInt(environment.getProperty("spring.data.cassandra.port"))); cluster.setJmxReportingEnabled(false); return cluster; }

cluster.setJmxReportingEnabled(false) is the answer seems.

Prasad
  • 19
  • 1