Micronaut Cassandra

Provides integration between Micronaut and Cassandra

Version:

1 Introduction

The micronaut-cassandra module includes support for integrating Micronaut services with Cassandra.

2 Release History

For this project, you can find a list of releases (with release notes) here:

3 Setting up Cassandra

Using the CLI

If you are creating your project using the Micronaut CLI, supply the cassandra feature to include Cassandra configuration in your project:

$ mn create-app my-app --features cassandra

To enable the Cassandra configuration, add the following dependency to your application:

implementation("io.micronaut.cassandra:micronaut-cassandra")
<dependency>
    <groupId>io.micronaut.cassandra</groupId>
    <artifactId>micronaut-cassandra</artifactId>
</dependency>

Micronaut supports Cassandra configuration by using the Datastax Java Driver. Configuration values can be supplied a property source such as below. The property name is derived from the builder methods in CqlSessionBuilder. Micronaut will create a CqlSession bean. This bean can be then injected into any other Micronaut bean.

Supply Single Configuration
cassandra.default.advanced.metadata.schema.enabled=false
cassandra.default.basic.contact-points[0]=127.0.0.1:9042
cassandra.default.basic.contact-points[1]=127.0.0.2:8042
cassandra.default.basic.load-balancing-policy.local-datacenter=datacenter1
cassandra:
  default:
    advanced:
      metadata:
        schema:
          enabled: false
    basic:
      contact-points:
        - "127.0.0.1:9042"
        - "127.0.0.2:8042"
      load-balancing-policy:
        local-datacenter: datacenter1
[cassandra]
  [cassandra.default]
    [cassandra.default.advanced]
      [cassandra.default.advanced.metadata]
        [cassandra.default.advanced.metadata.schema]
          enabled=false
    [cassandra.default.basic]
      contact-points=[
        "127.0.0.1:9042",
        "127.0.0.2:8042"
      ]
      [cassandra.default.basic.load-balancing-policy]
        local-datacenter="datacenter1"
cassandra {
  'default' {
    advanced {
      metadata {
        schema {
          enabled = false
        }
      }
    }
    basic {
      contactPoints = ["127.0.0.1:9042", "127.0.0.2:8042"]
      loadBalancingPolicy {
        localDatacenter = "datacenter1"
      }
    }
  }
}
{
  cassandra {
    default {
      advanced {
        metadata {
          schema {
            enabled = false
          }
        }
      }
      basic {
        contact-points = ["127.0.0.1:9042", "127.0.0.2:8042"]
        load-balancing-policy {
          local-datacenter = "datacenter1"
        }
      }
    }
  }
}
{
  "cassandra": {
    "default": {
      "advanced": {
        "metadata": {
          "schema": {
            "enabled": false
          }
        }
      },
      "basic": {
        "contact-points": ["127.0.0.1:9042", "127.0.0.2:8042"],
        "load-balancing-policy": {
          "local-datacenter": "datacenter1"
        }
      }
    }
  }
}

Multiple Cluster instances can be configured as follows:

Supply Multiple Configuration
cassandra.default.advanced.metadata.schema.enabled=false
cassandra.default.basic.contact-points[0]=127.0.0.1:9042
cassandra.default.basic.load-balancing-policy.local-datacenter=datacenter1
cassandra.secondary.advanced.metadata.schema.enabled=false
cassandra.secondary.basic.contact-points[0]=127.0.0.1:9043
cassandra.secondary.basic.load-balancing-policy.local-datacenter=datacenter2
cassandra:
  default:
    advanced:
      metadata:
        schema:
          enabled: false
    basic:
      contact-points:
        - "127.0.0.1:9042"
      load-balancing-policy:
        local-datacenter: datacenter1
  secondary:
    advanced:
      metadata:
        schema:
          enabled: false
    basic:
      contact-points:
        - "127.0.0.1:9043"
      load-balancing-policy:
        local-datacenter: datacenter2
[cassandra]
  [cassandra.default]
    [cassandra.default.advanced]
      [cassandra.default.advanced.metadata]
        [cassandra.default.advanced.metadata.schema]
          enabled=false
    [cassandra.default.basic]
      contact-points=[
        "127.0.0.1:9042"
      ]
      [cassandra.default.basic.load-balancing-policy]
        local-datacenter="datacenter1"
  [cassandra.secondary]
    [cassandra.secondary.advanced]
      [cassandra.secondary.advanced.metadata]
        [cassandra.secondary.advanced.metadata.schema]
          enabled=false
    [cassandra.secondary.basic]
      contact-points=[
        "127.0.0.1:9043"
      ]
      [cassandra.secondary.basic.load-balancing-policy]
        local-datacenter="datacenter2"
cassandra {
  'default' {
    advanced {
      metadata {
        schema {
          enabled = false
        }
      }
    }
    basic {
      contactPoints = ["127.0.0.1:9042"]
      loadBalancingPolicy {
        localDatacenter = "datacenter1"
      }
    }
  }
  secondary {
    advanced {
      metadata {
        schema {
          enabled = false
        }
      }
    }
    basic {
      contactPoints = ["127.0.0.1:9043"]
      loadBalancingPolicy {
        localDatacenter = "datacenter2"
      }
    }
  }
}
{
  cassandra {
    default {
      advanced {
        metadata {
          schema {
            enabled = false
          }
        }
      }
      basic {
        contact-points = ["127.0.0.1:9042"]
        load-balancing-policy {
          local-datacenter = "datacenter1"
        }
      }
    }
    secondary {
      advanced {
        metadata {
          schema {
            enabled = false
          }
        }
      }
      basic {
        contact-points = ["127.0.0.1:9043"]
        load-balancing-policy {
          local-datacenter = "datacenter2"
        }
      }
    }
  }
}
{
  "cassandra": {
    "default": {
      "advanced": {
        "metadata": {
          "schema": {
            "enabled": false
          }
        }
      },
      "basic": {
        "contact-points": ["127.0.0.1:9042"],
        "load-balancing-policy": {
          "local-datacenter": "datacenter1"
        }
      }
    },
    "secondary": {
      "advanced": {
        "metadata": {
          "schema": {
            "enabled": false
          }
        }
      },
      "basic": {
        "contact-points": ["127.0.0.1:9043"],
        "load-balancing-policy": {
          "local-datacenter": "datacenter2"
        }
      }
    }
  }
}

4 Health Checks

When the cassandra module is activated a CassandraHealthIndicator is activated resulting in the /health endpoint and CurrentHealthStatus interface resolving the health of the Cassandra cluster. The details show session status for each configured CqlSession bean.

{
  "name": "cassandra",
  "details": {
    "s0": {
      "session": "OPEN",
      "cluster_name": "Test Cluster",
      "nodes_count": 1,
      "nodes_state": {
        "UP": 1
      },
      "nodes (10 max.)": {
        "b9a3f593-5051-4552-a443-b2b3db1abcfe": {
          "endpoint": {},
          "open_connections": 2,
          "rack": "rack1",
          "distance": "LOCAL",
          "uptime_ms": 1694194386645,
          "datacenter": "datacenter1",
          "is_reconnecting": false,
          "state": "UP",
          "broadcast_address": {
            "MCGlobal": false,
            "MCLinkLocal": false,
            "MCNodeLocal": false,
            "MCOrgLocal": false,
            "MCSiteLocal": false,
            "address": [-84, 18, 0, 3],
            "anyLocalAddress": false,
            "canonicalHostName": "172.18.0.3",
            "hostAddress": "172.18.0.3",
            "hostName": "172.18.0.3",
            "linkLocalAddress": false,
            "multicastAddress": false,
            "siteLocalAddress": true,
            "loopbackAddress": false
          },
          "cassandra_version": {
            "major": 4,
            "minor": 1,
            "patch": 3,
            "DSEPatch": -1,
            "buildLabel": null,
            "preReleaseLabels": null
          }
        }
      }
    },
    "s1": {
      "session": "OPEN",
      "cluster_name": "Test Cluster",
      "nodes_count": 1,
      "nodes_state": {
        "UP": 1
      },
      "nodes (10 max.)": {
        "b9a3f593-5051-4552-a443-b2b3db1abcfe": {
          "endpoint": {},
          "open_connections": 1,
          "rack": "rack1",
          "distance": "IGNORED",
          "uptime_ms": 1694194387117,
          "datacenter": "datacenter1",
          "is_reconnecting": false,
          "state": "UP",
          "broadcast_address": {
            "MCGlobal": false,
            "MCLinkLocal": false,
            "MCNodeLocal": false,
            "MCOrgLocal": false,
            "MCSiteLocal": false,
            "address": [-84, 18, 0, 3],
            "anyLocalAddress": false,
            "canonicalHostName": "172.18.0.3",
            "hostAddress": "172.18.0.3",
            "hostName": "172.18.0.3",
            "linkLocalAddress": false,
            "multicastAddress": false,
            "siteLocalAddress": true,
            "loopbackAddress": false
          },
          "cassandra_version": {
            "major": 4,
            "minor": 1,
            "patch": 3,
            "DSEPatch": -1,
            "buildLabel": null,
            "preReleaseLabels": null
          }
        }
      }
    }
  },
  "status": {
    "name": "UP",
    "description": {
      "empty": true,
      "present": false
    },
    "operational": {
      "empty": false,
      "present": true
    },
    "severity": {
      "empty": true,
      "present": false
    }
  }
}
To disable the Cassandra health indicator entirely, add endpoints.health.cassandra.enabled: false.

See the section on the Health Endpoint for more information.

5 Micrometer Integration

The Cassandra DataStax Java Driver includes support for Micrometer metrics. To enable integration with Micronaut Micrometer include the following dependency:

implementation("io.micronaut.micrometer:micronaut-micrometer-core")
<dependency>
    <groupId>io.micronaut.micrometer</groupId>
    <artifactId>micronaut-micrometer-core</artifactId>
</dependency>

and:

implementation("com.datastax.oss:java-driver-metrics-micrometer")
<dependency>
    <groupId>com.datastax.oss</groupId>
    <artifactId>java-driver-metrics-micrometer</artifactId>
</dependency>

There are some additional requirements for settings in your application configuration

micronaut.metrics.enabled=true
cassandra.default.basic.contact-points[0]=127.0.0.1:${cassandra.port}
cassandra.default.basic.load-balancing-policy.local-datacenter=datacenter1
cassandra.default.advanced.metrics.factory.class=MicrometerMetricsFactory
cassandra.default.advanced.metrics.session.enabled[0]=connected-nodes
cassandra.default.advanced.metrics.session.enabled[1]=cql-requests
cassandra.default.advanced.metrics.session.enabled[2]=bytes-sent
cassandra.default.advanced.metrics.session.enabled[3]=bytes-received
cassandra.default.advanced.metrics.node.enabled[0]=cql-requests
micronaut:
  metrics:
    enabled: true
cassandra:
  default:
    basic:
      contact-points:
        - "127.0.0.1:${cassandra.port}"
      load-balancing-policy:
        local-datacenter: datacenter1
    advanced:
      metrics:
        factory:
          class: MicrometerMetricsFactory
        session:
          enabled:
            - connected-nodes
            - cql-requests
            - bytes-sent
            - bytes-received
        node:
          enabled:
            - cql-requests
[micronaut]
  [micronaut.metrics]
    enabled=true
[cassandra]
  [cassandra.default]
    [cassandra.default.basic]
      contact-points=[
        "127.0.0.1:${cassandra.port}"
      ]
      [cassandra.default.basic.load-balancing-policy]
        local-datacenter="datacenter1"
    [cassandra.default.advanced]
      [cassandra.default.advanced.metrics]
        [cassandra.default.advanced.metrics.factory]
          class="MicrometerMetricsFactory"
        [cassandra.default.advanced.metrics.session]
          enabled=[
            "connected-nodes",
            "cql-requests",
            "bytes-sent",
            "bytes-received"
          ]
        [cassandra.default.advanced.metrics.node]
          enabled=[
            "cql-requests"
          ]
micronaut {
  metrics {
    enabled = true
  }
}
cassandra {
  'default' {
    basic {
      contactPoints = ["127.0.0.1:${cassandra.port}"]
      loadBalancingPolicy {
        localDatacenter = "datacenter1"
      }
    }
    advanced {
      metrics {
        factory {
          'class' = "MicrometerMetricsFactory"
        }
        session {
          enabled = ["connected-nodes", "cql-requests", "bytes-sent", "bytes-received"]
        }
        node {
          enabled = ["cql-requests"]
        }
      }
    }
  }
}
{
  micronaut {
    metrics {
      enabled = true
    }
  }
  cassandra {
    default {
      basic {
        contact-points = ["127.0.0.1:${cassandra.port}"]
        load-balancing-policy {
          local-datacenter = "datacenter1"
        }
      }
      advanced {
        metrics {
          factory {
            class = "MicrometerMetricsFactory"
          }
          session {
            enabled = ["connected-nodes", "cql-requests", "bytes-sent", "bytes-received"]
          }
          node {
            enabled = ["cql-requests"]
          }
        }
      }
    }
  }
}
{
  "micronaut": {
    "metrics": {
      "enabled": true
    }
  },
  "cassandra": {
    "default": {
      "basic": {
        "contact-points": ["127.0.0.1:${cassandra.port}"],
        "load-balancing-policy": {
          "local-datacenter": "datacenter1"
        }
      },
      "advanced": {
        "metrics": {
          "factory": {
            "class": "MicrometerMetricsFactory"
          },
          "session": {
            "enabled": ["connected-nodes", "cql-requests", "bytes-sent", "bytes-received"]
          },
          "node": {
            "enabled": ["cql-requests"]
          }
        }
      }
    }
  }
}
  • micronaut.metrics.enabled set to true enables binding Cassandra to Micronaut Micrometer

  • advanced.factory.factory.class is specified with the value MicrometerMetricsFactory. The DataStax driver supports other metrics libraries, and this property indicates which one to use.

  • advanced.metrics.session.enabled and advanced.metrics.node.enabled accept a list of the metrics exposed by the DataStax driver. All possible values are documented in the driver configuration reference.

6 SSL Integration

The Cassandra DataStax Java Driver includes support for SSL, to secure traffic between the driver and Cassandra.

This an example of additional configuration for Micronaut Cassandra that enables SSL connections. The relevant values are defined under the cassandra.*.advanced.ssl-engine-factory.* property key and documented further in the Datastax Configuration Reference.

cassandra.default.advanced.ssl-engine-factory.class=DefaultSslEngineFactory
cassandra.default.advanced.ssl-engine-factory.truststore-path=<path to trust store>
cassandra.default.advanced.ssl-engine-factory.truststore-password=<password>
cassandra:
  default:
    advanced:
      ssl-engine-factory:
        class: DefaultSslEngineFactory
        truststore-path: <path to trust store>
        truststore-password: <password>
[cassandra]
  [cassandra.default]
    [cassandra.default.advanced]
      [cassandra.default.advanced.ssl-engine-factory]
        class="DefaultSslEngineFactory"
        truststore-path="<path to trust store>"
        truststore-password="<password>"
cassandra {
  'default' {
    advanced {
      sslEngineFactory {
        'class' = "DefaultSslEngineFactory"
        truststorePath = "<path to trust store>"
        truststorePassword = "<password>"
      }
    }
  }
}
{
  cassandra {
    default {
      advanced {
        ssl-engine-factory {
          class = "DefaultSslEngineFactory"
          truststore-path = "<path to trust store>"
          truststore-password = "<password>"
        }
      }
    }
  }
}
{
  "cassandra": {
    "default": {
      "advanced": {
        "ssl-engine-factory": {
          "class": "DefaultSslEngineFactory",
          "truststore-path": "<path to trust store>",
          "truststore-password": "<password>"
        }
      }
    }
  }
}
  • class: The class of the factory. DefaultSslEngineFactory is the default built-in implementation

  • truststore properties: these are optional and if not present system property configuration is used instead

7 Additional Notes

The Datastax Cassandra driver is configured using lightbend/config under the field datastax-java-driver.\*.

The equivalent bean created for micronaut is mapped under the cassandra... fields provided in your application.conf, but the bean will fallback on the datastax-java-driver.\* values if they are present.

These config values are provided to the CqlSession under the hood. Datastax does not provide a class that maps to all the various possible config keys, but a full list of values that can be provided can be found in the DefaultDriverOption enum.

datastax configuration under lightbend/config - application.conf
datastax-java-driver {
    basic {
        contact-points = [ "1.2.3.4:9042", "5.6.7.8:9042" ]
        load-balancing-policy.local-datacenter = datacenter1
    }
}
micronaut bean configuration - application configuration
cassandra.default.basic.contact-points[0]=127.0.0.1:9042
cassandra.default.basic.contact-points[1]=5.6.7.8:9042
cassandra.default.basic.load-balancing-policy.local-datacenter=datacenter1
cassandra:
  default:
    basic:
      contact-points:
        - "127.0.0.1:9042"
        - "5.6.7.8:9042"
      load-balancing-policy:
        local-datacenter: datacenter1
[cassandra]
  [cassandra.default]
    [cassandra.default.basic]
      contact-points=[
        "127.0.0.1:9042",
        "5.6.7.8:9042"
      ]
      [cassandra.default.basic.load-balancing-policy]
        local-datacenter="datacenter1"
cassandra {
  'default' {
    basic {
      contactPoints = ["127.0.0.1:9042", "5.6.7.8:9042"]
      loadBalancingPolicy {
        localDatacenter = "datacenter1"
      }
    }
  }
}
{
  cassandra {
    default {
      basic {
        contact-points = ["127.0.0.1:9042", "5.6.7.8:9042"]
        load-balancing-policy {
          local-datacenter = "datacenter1"
        }
      }
    }
  }
}
{
  "cassandra": {
    "default": {
      "basic": {
        "contact-points": ["127.0.0.1:9042", "5.6.7.8:9042"],
        "load-balancing-policy": {
          "local-datacenter": "datacenter1"
        }
      }
    }
  }
}

Micronaut Framework is very flexible with how application configuration is specified. Configuration properties can be overridden with environment variables. However, the Cassandra Datastax driver is not tolerant and fails fast when it encounters what it considers malformed/illegal configuration properties. Micronaut Cassandra handles this automatically for most cases, but if you want to use environment variables to override DataStax driver configuration they must be uppercase camelcase, e.g. CASSANDRA_DEFAULT_BASIC_SESSION_NAME

8 GraalVM support

Micronaut Cassandra is compatible with GraalVM so it is possible to create native images without any additional configuration.

See the section on GraalVM in the user guide for more information.

9 Repository

You can find the source code of this project in this repository: