Via this blog we’re releasing the first developer preview of the 1.4.0 Java SDK. Aside from the usual bugfixes and enhancements, this new minor release provides support for optimized connection management which was recently introduced in Couchbase Server 2.5.0. See below for more information on what’s new here.

You can download the preview either from Maven Central or a zip archive with all JARs included.

Update: The developer preview has been refreshed to 1.4.0dp2 as of April 4, 2014.

Optimized Connection Management

Couchbase Server 2.5.0 introduced a new way of fetching a cluster configuration a couple of weeks ago. In addition to the previous way of loading it over port 8091 (http), it is now possible for the SDK to load it directly through the underlying binary protocol (port 11210). Previously, to keep track of ongoing cluster changes, the client had to establish a streaming connection to the configuration port (which did push new config chunks to the client). Now, the client receives new configurations along with data operation responses over the binary port. This makes bootstrap much faster and more efficient, making it easier to manage large deployments.

When using the Java SDK, there is nothing that needs to be changed API wise, but since the bootstrap process changes slightly, its good to understand what is actually going on. For a general introduction into that topic, I recommend Mark Nunberg’s blog post on the similar changes to libcouchbase, which covers lots of the surrounding bits and pieces.

The Java SDK takes the list of bootstrap nodes passed in, but ignores everything from the URI aside the hostname for now. It tries to contact the target server on port 11210. If the server responds with a valid configuration (which happens if it is a 2.5.0 or later node and a couchbase bucket), this configuration gets immediately stored and used. No streaming connection is attached, but this binary connection is reused to fetch configuration updates on demand as needed. If the server doesn’t respond with a valid configuration, all of the other nodes in the bootstrap list are tried with the same behaviour. If none of them return a valid config (for example if a memcache bucket is used or all of the nodes in the cluster are version 2.2 or older), the client falls back to the (old) HTTP type bootstrap and streaming connection.  While this process changes the behavior and doesn’t seem to match what the arguments imply is happening, we think this is the right thing to do for compatibility purposes with existing applications (though we’re open to feedback).

The same process is established when the configuration connection gets lost or other parts of the SDK indicate that the configuration connection is outdated (for example a high amount of failing operations).

INFO-level logging has been added so that it is visible from the logs which bootstrap approach is used. If the new connection management facilities did work, this log message is shown:

INFO com.couchbase.client.vbucket.provider.BucketConfigurationProvider:  Could bootstrap through carrier publication.

Otherwise, this logging output can be found:

INFO com.couchbase.client.vbucket.provider.BucketConfigurationProvider:  Binary config not available, bootstrapped through HTTP.

Since this change is a slightly larger one inside the SDK, please kick the tires on the developer preview (that’s mainly why we opted in to do a preview instead going directly to a final release) and give us feedback on various scenarios in your environment.  Our test team is also running it through its paces.

Total numbers of records on the ViewResponse

Every non-reduced view exposes the total number of rows in the view and this is now reflected also in the Java SDK. This is especially useful in pagination and unit testing scenarios. Here is an example (from the beer-sample dataset):

View view = c.getView(“beer”, “brewery_beers”);
Query query = new Query();
query.setLimit(10);

ViewResponse response = c.query(view, query);
System.out.println(“In this batch: ” + response.size());
System.out.println(“Total in this View: ” + response.getTotalRows());

This prints:

In this batch: 10
Total in this View: 7303

This has been a long-standing user request and is now in this release.

Enhanced replica read capabilities

Another user request – since we added replica-read capabilities – was that there should also be a way to retreive the CAS value from the replica node. This basically resembles the well known “gets” command, but this time for replicas. We added the capability through the asyncGetsFromReplica and getsFromReplica commands. Here is an example on how to utilize the new methods:

CASValuekey = c.getsFromReplica(“key”);System.out.println(“Value is: ” + key.getValue() +”, CAS is: ” + key.getCas());This will print something like:

Value is: myvalue, CAS is: 5954429833794

Keep in mind that the semantics are the same as with “getFromReplica”, so that the returned value with CAS could either be from the master or one of the replica nodes, depending on who responded first. This CAS value can be used for subsequent write commands that need to include the CAS value for optimistic locking.

Typesafe status codes on OperationStatus

In the past, it has always been a bit of a hassle to deal with future operation status response strings. There was no good way to deal with them other than checking strings. This minor release brings StatusCodes to the OperationStatus objects, which allows you to simply check against an ENUM.For example, here is how a successful response looks like:

OperationFuture set = c.set(“key”, “value”);assert set.getStatus().getStatusCode() == StatusCode.SUCCESS;

Now we can use the same approach to check if an add response did fail because the key has already been set:

OperationFuture add = c.add(“key”, “value”);assert add.getStatus().getStatusCode() == StatusCode.ERR_EXISTS;

The StatusCode provides all possible status codes that can be returned, and before the final release we’ll also provide proper documentation when they can occur (so you know what to look for when checking the codes).

Next Steps

We’ve decided to do a developer preview for this minor release because we want to make sure that the new optimized connection management facilities are battle tested before a final release. Please kick the tires and report any issues you find on our issue tracker. As soon as our test team has given us the green light and if there are no concerns from DP users, we’ll release it as GA!

Author

Posted by Michael Nitschinger

Michael Nitschinger works as a Principal Software Engineer at Couchbase. He is the architect and maintainer of the Couchbase Java SDK, one of the first completely reactive database drivers on the JVM. He also authored and maintains the Couchbase Spark Connector. Michael is active in the open source community, a contributor to various other projects like RxJava and Netty.

2 Comments

  1. Ravi Paramasivam September 4, 2015 at 3:13 pm

    Hi Nitschinger,

    We are getting the below exceptions randomly with couchbase 2.x and java client sdk 1.4.x

    1. Shutting down bucket \”Sample\” on \’ns_1@10.10.10.163\’ for server shutdownns_memcached002ns_1@10.10.10.16322:33:48 – Tue Aug 11, 2015

    2.com.couchbase.client.vbucket.ConfigurationException: Could not fetch a valid Bucket configuration.2015-08-06 00:37:37 STDIO [ERROR] at com.couchbase.client.vbucket.provider.BucketConfigurationProvider.bootstrap(BucketConfigurationProvider.ja…:123)
    2015-08-06 00:37:37 STDIO [ERROR]

    Any idea how we can re-produce this and fix it?

    1. Hi Ravi,
      The best is to port this discussion to the forums, http://forums.couchbase.com, where we\’ll be able to better follow the discussion and ask for more detail (make sure to post in the Java SDK category, and give as much context as you can).
      Thanks!

Leave a reply