Cassandra Server

§Cassandra Server

By default, Lagom services needing to persist data use Cassandra as database. For convenience, we have embedded a Cassandra server in the development environment, so that you don’t have to worry about installing it. There are a number of settings and tasks available to tune the Cassandra server to your liking, let’s explore them:

§Default port

By default, the Cassandra server is started on port 4000. We are aware that Cassandra is usually run on port 9042, and that is precisely the reason why we picked a different port: we do not want to interfere with your locally running Cassandra, if you happen to have one. If the current default port doesn’t suit you, and for instance you would prefer to have the embedded Cassandra server running on port 9042, you can do so by adding the following in your build.

In the Maven root project pom:

<plugin>
    <groupId>com.lightbend.lagom</groupId>
    <artifactId>lagom-maven-plugin</artifactId>
    <version>${lagom.version}</version>
    <configuration>
        <cassandraPort>9042</cassandraPort>
    </configuration>
</plugin>

In sbt:

lagomCassandraPort in ThisBuild := 9042

§Clean up on start

By default, all database files created by your running services are going to be deleted the next time the Cassandra server is started. You can turn off this feature by adding the following in your build.

In the Maven root project pom:

<plugin>
    <groupId>com.lightbend.lagom</groupId>
    <artifactId>lagom-maven-plugin</artifactId>
    <version>${lagom.version}</version>
    <configuration>
        <cassandraCleanOnStart>false</cassandraCleanOnStart>
    </configuration>
</plugin>

In sbt:

lagomCassandraCleanOnStart in ThisBuild := false

§Keyspace (deprecated)

A keyspace in Cassandra is a namespace that defines data replication on nodes. Each service should use a unique keyspace name so that the tables of different services do not conflict with each other. In the development environment, the keyspace is automatically set to be the project’s name by default (after possibly having replaced a few characters that aren’t allowed). If the generated keyspace doesn’t suit you, you are free to provide a custom one.

In Maven, you can do this by modifying the service implementation’s pom configuration:

<plugin>
    <groupId>com.lightbend.lagom</groupId>
    <artifactId>lagom-maven-plugin</artifactId>
    <configuration>
        <lagomService>true</lagomService>
        <cassandraKeyspace>users</cassandraKeyspace>
    </configuration>
</plugin>

In sbt, add the lagomCassandraKeyspace setting to the service implementation project:

lazy val usersImplKeyspaced = (project in file("usersImpl")).enablePlugins(LagomScala)
  .settings(
    name := "users-impl",
    lagomCassandraKeyspace := "users"
  )

It is worth pointing out that, despite the above, a Cassandra keyspace will still need to be provided when running your service in production. Hence, if you’d like to provide a Cassandra keyspace name that can be used both in development and production, it is recommended to do so via a configuration file.

For instance, instead of setting the keyspace using the lagomCassandraKeyspace as we did before, we can obtain the same result by adding the following additional keys/values in the project’s application.conf (note that if you do not have an application.conf, you should create one. For the above defined project, it would be typically placed under usersImpl/src/main/resources/):

cassandra-journal.keyspace=users
cassandra-snapshot-store.keyspace=users
lagom.persistence.read-side.cassandra.keyspace=users

Note that Cassandra uses keyspace values from the application.conf file instead of any you might define in the build. For that reason, overriding the keyspace in the build is deprecated, and will be removed in a future version of Lagom.

See Cassandra persistent entity configuration for more information about configuring keyspaces.

§JVM options

The Cassandra server is run on a separate process, and a JVM is started with sensible memory defaults. However, if the default JVM options don’t suit you, you can override them by adding the following in your build.

In the Maven root project pom:

<plugin>
    <groupId>com.lightbend.lagom</groupId>
    <artifactId>lagom-maven-plugin</artifactId>
    <version>${lagom.version}</version>
    <configuration>
        <cassandraJvmOptions>
             <opt>-Xms256m</opt>
             <opt>-Xmx1024m</opt>
             <opt>-Dcassandra.jmx.local.port=4099</opt>
             <opt>-DCassandraLauncher.configResource=dev-embedded-cassandra.yaml</opt>
         </cassandraJvmOptions>
    </configuration>
</plugin>

In sbt:

lagomCassandraJvmOptions in ThisBuild :=
  Seq("-Xms256m", "-Xmx1024m", "-Dcassandra.jmx.local.port=4099",
    "-DCassandraLauncher.configResource=dev-embedded-cassandra.yaml") // these are actually the default jvm options

§Yaml configuration

As shown above, the YAML configuration file can be configured by modifying the Cassandra JVM options to include a -DCassandraLauncher.configResource system property that points to a resource in your src/main/resources directory.

§Logging

Logging is configured such that it goes to the standard output, and the log level for org.apache.cassandra is set to ERROR. Here is the used logback.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%date{ISO8601} %-5level %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="org.apache.cassandra" level="ERROR" />

  <root level="INFO">
    <appender-ref ref="STDOUT" />
  </root>
  
</configuration>

There is no mechanism in place to edit the used logback.xml. If you need to tune the logging configuration, you should install Cassandra, and read the instructions to connect to a locally running Cassandra.

§Cassandra start time

As mentioned, the runAll task also takes care of starting the embedded Cassandra server, before starting any other service. Moreover, services are usually started only after the Cassandra server is reachable. By default, the Cassandra server is given up to 20 seconds to be up and running, but you can change this default by adding the following in your build.

In the Maven root project pom:

<plugin>
    <groupId>com.lightbend.lagom</groupId>
    <artifactId>lagom-maven-plugin</artifactId>
    <version>${lagom.version}</version>
    <configuration>
        <cassandraMaxBootWaitingSeconds>0</cassandraMaxBootWaitingSeconds>
    </configuration>
</plugin>

In sbt:

import scala.concurrent.duration._ // Mind that the import is needed.
lagomCassandraMaxBootWaitingTime in ThisBuild := 0.seconds

Changing the Cassandra server maximum boot waiting time to be 0 can be useful to emulate a real-world deployment scenario, since a running Cassandra instance may not be available the moment a service is started.

§Start and stop

The Cassandra server is automatically started when executing the runAll task. However, there are times when you might want to manually start only a few services, and hence you won’t use the runAll task. In this case, you can manually start the Cassandra server via the lagom:startCassandra maven task or lagomCassandraStart sbt task, and stopping it with the lagom:stopCassandra Maven task or lagomCassandraStop sbt task.

§Disable it

You can disable the embedded Cassandra server by adding the following in your build.

In the Maven root project pom:

<plugin>
    <groupId>com.lightbend.lagom</groupId>
    <artifactId>lagom-maven-plugin</artifactId>
    <version>${lagom.version}</version>
    <configuration>
        <cassandraEnabled>false</cassandraEnabled>
    </configuration>
</plugin>

In sbt:

lagomCassandraEnabled in ThisBuild := false

One good reason to disable the embedded Cassandra server is if you need your services to connect to an external, locally running, Cassandra instance.

§Connecting to a locally running Cassandra instance

It’s possible to connect to an externally run Cassandra instance in place of the embedded one. All you need to do is adding the following in your build.

In the Maven root project pom:

<plugin>
    <groupId>com.lightbend.lagom</groupId>
    <artifactId>lagom-maven-plugin</artifactId>
    <version>${lagom.version}</version>
    <configuration>
        <unmanagedServices>
            <cas_native>http://localhost:9042</cas_native>
        </unmanagedServices>
        <cassandraEnabled>false</cassandraEnabled>
    </configuration>
</plugin>

In sbt:

lagomCassandraEnabled in ThisBuild := false
lagomUnmanagedServices in ThisBuild := Map("cas_native" -> "http://localhost:9042")

These two settings will only be used when running Lagom in DevMode. The purpose of these two settings is to disable the embedded Cassandra server and configure the Service Locator in DevMode to still be able to locate Cassandra when looking for cas_native. You may want to disable the Lagom-managed Cassandra server if you already have a Cassandra server running locally or in your company infrastructure and prefer using that. In that scenario it doesn’t make sense for Lagom to start a Cassandra server and you will also gain few seconds of bootup time.

The service locator setup in these examples assumes your local Cassandra instance is running on port 9042.

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.