Install and Start Using the Scala SDK with Couchbase Server

The Couchbase Scala SDK enables you to interact with a Couchbase Server cluster from the Scala language.
These pages cover the second Alpha of the Couchbase Scala SDK — 1.0 alpha 3. As such they are likely to change without notice. The alpha code should not be used in production.

Installing the SDK

The Couchbase Scala SDK is available on the Couchbase Maven repository and can be included in your build.gradle like this:

repositories {
    maven {
        url 'http://files.couchbase.com/maven2'
    }
}

dependencies {
    compile group: 'com.couchbase.client', name: 'scala-client_2.12', version: '1.0.0-alpha.4'
}

Or into your Maven pom.xml:

<repositories>
    <repository>
      <id>couchbase</id>
      <name>Couchbase Preview Repository</name>
      <url>http://files.couchbase.com/maven2</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.couchbase.client</groupId>
        <artifactId>scala-client_2.12</artifactId>
        <version>1.0.0-alpha.4</version>
    </dependency>
</dependencies>

Or for SBT:

resolvers += "Couchbase Snapshots" at "http://files.couchbase.com/maven2"
libraryDependencies += "com.couchbase.client" %% "scala-client" % "1.0.0-alpha.4"

Scala 2.11 Support

The last release of Scala 2.11 was in November 2017, and users are strongly recommended to use Scala 2.12.

There is a Scala 2.11 build of the Couchbase SDK, but due to technical limitations between 2.11 and the optional dependencies used by the SDK, the application is required to use one of two workarounds to prevent compilation errors. Either:

  1. Use Maven.

  2. Or use gradle or SBT and re-declare all optional dependencies of the Scala SDK in your build file:

libraryDependencies += "com.lihaoyi" %% "upickle" % "0.7.1" % "optional"
libraryDependencies += "io.circe" %% "circe-core" % "0.10.0" % "optional"
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.7" % "optional"
libraryDependencies += "org.json4s" %% "json4s-native" % "3.6.4" % "optional"
libraryDependencies += "org.typelevel" %% "jawn-ast" % "0.14.0" % "optional"

This workaround is only required if you are using Scala 2.11. Scala 2.12 is unaffected.

The most recent version of the SDK with 2.11 support is "1.0.0-alpha.3".

Connecting to a Cluster

Now you have the Scala client installed, try out the following to connect to a Couchbase cluster.

First pull in all the imports we’ll be using:

import java.util.UUID

import com.couchbase.client.scala.Cluster
import com.couchbase.client.scala.json.{JsonObject, JsonObjectSafe}

import scala.util.{Failure, Success}

Now we can connect to the cluster:

val cluster = Cluster.connect("10.112.180.101", "username", "password")

Of course, you’ll need to change the IP address to match your own cluster’s.

Couchbase uses Role Based Access Control (RBAC) to control access to resources, so specify the username and password of a user you’ve setup during installation of the Couchbase Data Platform.

Now we can open a Couchbase bucket, and its default collection:

val bucket     = cluster.bucket("bucket-name")
val collection = bucket.defaultCollection

The Scala SDK is forwards-looking to future releases of Couchbase Server which will support the new features of scopes and collections. These will allow documents to be grouped in a more granular way than buckets allow. For now, we will just open the 'default collection', which includes all documents in a bucket, and is forwards and backwards compatible with all supported versions of Couchbase Server.

JSON

Now we can do some simple Key Value (KV) operations. First, let’s create some JSON.

The Scala SDK directly supports several popular JSON libraries, including uPickle/uJson, Circe, Play Json, Jawn, and Json4s (if you’d like to see your favourite supported, please let us know). In addition you can supply JSON encoded into a String or Array[Byte], opening the door to any JSON library; Jsoniter and Jackson have been tested this way, but any should work.

You can also directly encode and decode Scala case classes to and from the SDK.

To make things easy and to help get you started, the Scala SDK also bundles a home-grown small JSON library, which you are free to use instead of or alongside any of the other supported JSON libraries. The philosophy behind this library is to provide a very easy-to-use API and the fastest JSON implementation possible.

These options are described in detail here, but to get us started let’s created some simple JSON using the built-in JsonObject library:

val json = JsonObject("status" -> "awesome")

Key-Value Operations

And now let’s upsert it into Couchbase (upsert is an operation that will insert the document if it does not exist, or replace it if it does). We need to provide a unique ID for the JSON, and we’ll use a UUID here:

val docId = UUID.randomUUID().toString
collection.upsert(docId, json) match {
  case Success(result)    =>
  case Failure(exception) => println("Error: " + exception)
}
A note on error handling: the Scala SDK will not throw exceptions. Instead, methods that can error will return a Scala Try object, which can either be a Success containing the result, or a Failure containing a Throwable exception. The easiest way to handle a single operation is with pattern matching, as shown above.

Now let’s get the data back (this example will look a little messy, but we’ll see how to clean it up shortly):

// Get a document
collection.get(docId) match {
  case Success(result) =>

    // Convert the content to a JsonObjectSafe
    result.contentAs[JsonObjectSafe] match {
      case Success(json) =>

        // Pull out the JSON's status field, if it exists
        json.str("status") match {
          case Success(hello) => println(s"Couchbase is $hello")
          case _              => println("Field 'status' did not exist")
        }
      case Failure(err) => println("Error decoding result: " + err)
    }
  case Failure(err) => println("Error getting document: " + err)
}

Here we’re fetching the value for the key docId, converting that value to a JsonObjectSafe (a simple wrapper around JsonObject that returns Try rather than throwing exceptions - see here for details), and then accessing the value of the status key as a String.

Better Error Handling

All three of these operations could fail, so there’s quite a lot of error handling code here to do something quite simple. One way to improve on this is by using flatMap, like this:

val result: Try[String] = collection.get(docId)
  .flatMap(_.contentAs[JsonObjectSafe])
  .flatMap(_.str("status"))

result match {
  case Success(status) => println(s"Couchbase is $status")
  case Failure(err)    => println("Error: " + err)
}

Alternatively, you can use a for-comprehension, like so:

val result: Try[String] = for {
  result <- collection.get(docId)
  json   <- result.contentAs[JsonObjectSafe]
  status <- json.str("status")
} yield status

result match {
  case Success(status) => println(s"Couchbase is $status")
  case Failure(err)    => println("Error: " + err)
}

Next Steps

You now know the basics of connecting to a Couchbase cluster, creating some JSON, and performing Key-Value operations.

Key-Value operations are described in detail here.

For performing operations against multiple documents, check out how to use N1QL in Scala here.

API reference are available in a javadocs jar alongside the release.