{"id":7085,"date":"2019-06-18T08:03:34","date_gmt":"2019-06-18T15:03:34","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=7085"},"modified":"2023-05-19T04:35:50","modified_gmt":"2023-05-19T11:35:50","slug":"couchbase-scala-sdk","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/","title":{"rendered":"Introducing the Couchbase Scala SDK"},"content":{"rendered":"<p>I\u2019m very happy to report that Couchbase now has a supported Scala SDK, allowing you to get and fetch documents, run N1QL queries, perform analytics and full text search lookups &#8211; all with native Scala.<\/p>\n<p>In this blog I\u2019m going to touch on the key features and design principles of the Scala SDK. \u00a0Or if you want to get going right away, then check out the <a href=\"https:\/\/docs.couchbase.com\/scala-sdk\/1.0\/start-using-sdk.html\">getting started guide here<\/a>. \u00a0The Scala SDK is available to download right now, in a pre-release alpha form.<\/p>\n<p>The Scala SDK uses the same high-performance and stable internal core as the new Java SDK 3.x, so although it\u2019s brand new, you can rest assured that it will be production-ready come GA.<\/p>\n<h3><b>Functional Error Handling &#8211; No Exceptions!<\/b><\/h3>\n<p>The Scala SDK presents a functional interface, with the majority of operations returning a Scala Try. \u00a0This can either be a Success and contain the expected value, or a Failure containing a Throwable. Though at first this seems a little verbose, and requires some programming discipline to always handle errors, this form of error handling quickly becomes second nature and lets you develop safe in the knowledge that a random exception isn\u2019t going to be thrown from the SDK.<\/p>\n<p>Here\u2019s a simple demo of inserting a document:<\/p>\n<pre class=\"lang:scala decode:true\">val json = JsonObject(\"status\" -&gt; \"awesome!\")\r\n\r\nval result: Try[MutationResult] = collection.insert(\"document-key\", json)<\/pre>\n<p>And then pattern matching on the Try result:<\/p>\n<pre class=\"lang:scala decode:true\">result match {\r\n \u00a0\u00a0\u00a0 case Success(mr) =&gt; println(\"Upsert was successful\")\r\n \u00a0\u00a0\u00a0 case Failure(err: KeyAlreadyExistsException) =&gt; println(\"document-key already exists\") \r\n \u00a0\u00a0\u00a0 case Failure(err) =&gt; println(\"Error: \" + err)\r\n}<\/pre>\n<p>(Of course, a production app would handle errors properly, rather than just using println!)<\/p>\n<p>If you\u2019d rather have something similar to the Java SDK, which throws exceptions, this is easy to simulate by simply calling .get() on any Try, which will throw if it\u2019s a Failure:<\/p>\n<pre class=\"lang:scala decode:true \">val result: MutationResult = collection.insert(\"document-key\", json).get()<\/pre>\n<p>It\u2019s easy to combine multiple Try\u2019s through flatMap. \u00a0Here we upsert a document, then get it, retrieve its content converted into the built-in JSON library JsonObjectSafe (more on that later), and finally getting a field named \u201cstatus\u201d from that. \u00a0All in a completely functional style, so for instance the get operation will only be tried if the upsert is successful.<\/p>\n<pre class=\"lang:scala decode:true\">val result: Try[String] = collection.upsert(\"document-key\", json)\r\n    .flatMap(_ =&gt; collection.get(\"document-key\"))\r\n    .flatMap(_.contentAs[JsonObjectSafe])\r\n    .flatMap(_.str(\"status\"))\r\n\r\nresult match {\r\n    case Success(status) =&gt; println(s\"Couchbase is $status\")\r\n    case Failure(err) =&gt;\u00a0\u00a0\u00a0 println(\"Error: \" + err)\r\n}<\/pre>\n<p>(For conciseness, most of the examples below will leave out checking the result. \u00a0But production apps should of course ABC &#8211; always be checking.)<\/p>\n<h3><b>Forward Looking<\/b><\/h3>\n<p>Out of the box, the SDK supports the new stronger durability that will be available in Couchbase Server 6.5:<\/p>\n<pre class=\"lang:scala decode:true\">val result = collection.upsert(\u201cdocId\u201d, json, durability = Durability.Majority)<\/pre>\n<p>And bakes in support for collections, a new method of organizing documents inside buckets which will be a cornerstone feature of a future release of Couchbase Server (with a preview coming soon). \u00a0The keen will soon be able to create some toy collections to play with, but for now it will suffice to open the default collection:<\/p>\n<pre class=\"lang:scala decode:true\">val cluster = Cluster.connect(\"cluster-ip\", \"username\", \"password\")\r\nval collection = cluster.bucket(\"bucket-name\").defaultCollection<\/pre>\n<p>This logic will work on all supported Couchbase Server versions (5.x and above).<\/p>\n<p>In addition, support is included for OpenTracing (now OpenTelemetry), the platform that\u2019s becoming the defacto standard for tracing complex distributed systems:<\/p>\n<pre class=\"lang:scala decode:true\">val result = collection.upsert(\u201cdocId\u201d, json, parentSpan = Some(mySpan))<\/pre>\n<h3><b>Simple API<\/b><\/h3>\n<p>The SDK leverages named and default parameters in place of overloads, so your code can be as simple:<\/p>\n<pre class=\"lang:scala decode:true\">val result = collection.upsert(\u201cdocId\u201d, json)<\/pre>\n<p>or as customized:<\/p>\n<pre class=\"lang:scala decode:true\">val result = collection.upsert(\u201cdocId\u201d, json, durability = Durability.Majority, expiration = 60.minutes, parentSpan = Some(mySpan))<\/pre>\n<p>as you need it to be.<\/p>\n<h3><b>Asynchronous<\/b><\/h3>\n<p>Like the Java SDK, three APIs are presented, giving you the flexibility to structure your application the way you need to.<\/p>\n<p>First is the simple blocking synchronous API you\u2019ve seen in the examples above. \u00a0This can be a good default choice, but of course requires you to explicitly manage your own threading if needed.<\/p>\n<p>Second is one built around reactive programming, using standard reactive types (Mono and Flux) from Project Reactor.<\/p>\n<p>An example of upserting in a reactive way:<\/p>\n<pre class=\"lang:scala decode:true\">val mono: Mono[MutationResult] = collection.reactive.upsert(\"document-key\", json)\r\n    .doOnError(err =&gt; println(s\"Error during upsert: ${err}\"))\r\n    .doOnNext(mutationResult =&gt; println(\"Success\"))<\/pre>\n<p>With reactive programming, nothing will happen until we subscribe to the Mono. \u00a0The simplest way to do this for testing purposes is to use block(), though this is bad practice for a real app:<\/p>\n<pre class=\"lang:scala decode:true \">val result: MutationResult = mono.block()<\/pre>\n<p>Reactive programming is a complex and deep subject that I can\u2019t go into too much here, but when mastered it provides a powerful tool, especially for handling the complexities of real-world distributed systems. \u00a0In particular, the reactive API provides backpressure on N1QL, FTS and analytics queries &#8211; so if the application is struggling to keep up with the data, it will automatically slow down consumption of rows and avoid out-of-memory errors. \u00a0I encourage the curious to check out the <a href=\"https:\/\/projectreactor.io\/docs\">Project Reactor documentation<\/a> to learn more.<\/p>\n<p>Finally, there is the asynchronous API built around Scala Futures, which provides a little of the thread management and composability of reactive programming, but in a form that\u2019s more familiar to many Scala developers. \u00a0A simple upsert example looks like this:<\/p>\n<pre class=\"lang:default decode:true\">val result: Future[MutationResult] = collection.async.upsert(\"document-key\", json)\r\n\r\nresult onComplete {\r\n    case Success(_) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 =&gt; println(\"Successfully upserted\")\r\n    case Failure(exception) =&gt; println(\"Error: \" + exception)\r\n}<\/pre>\n<h3><b>JSON Flexibility<\/b><\/h3>\n<p>A key aim was to not fence you into any particular JSON implementation, and out-of-the-box the Scala SDK will play nice with several popular Scala JSON libraries, including Circe, \u00b5Pickle \/ \u00b5Json, Json4s and Jawn. \u00a0You can see snippets of how to use each of them in <a href=\"https:\/\/docs.couchbase.com\/scala-sdk\/1.0\/howtos\/json.html\">the JSON docs<\/a>, but to whet your appetite here\u2019s some Circe in action &#8211; note how Circe types are directly sent to, and returned from, the SDK:<\/p>\n<pre class=\"lang:scala decode:true \">import io.circe.generic.auto._\r\nimport io.circe.syntax._\r\n\r\nval user = User(\u201cJohn Smith\u201d, 29)\r\nval json: io.circe.Json = user.asJson\r\n\r\nval result: Try[io.circe.Json] = collection.insert(\"id\", json)\r\n    .flatMap(_ =&gt; collection.get(\"id\"))\r\n     .flatMap(doc =&gt; doc.contentAs[io.circe.Json])\r\n\r\nresult match {\r\n    case Success(content: io.circe.Json) =&gt;\r\n        \/\/ Handle Circe Json here\r\n    case Failure(err) =&gt;\u00a0\u00a0\u00a0 println(\"Error: \" + err)\r\n}<\/pre>\n<h4>Built-in JSON<\/h4>\n<p>Taking a \u2018batteries included\u2019 approach there\u2019s also a simple JSON library included with the SDK, JsonObject. \u00a0Its main goals are:<\/p>\n<ul>\n<li>Convenience. Not everyone wants to evaluate multiple JSON libraries before getting started. JsonObject is a decent default choice.<\/li>\n<li>Speed. Our internal benchmarking (<a href=\"https:\/\/github.com\/couchbase\/couchbase-jvm-clients\/tree\/master\/benchmarks\">source<\/a> in case you\u2019d like to run them yourself) indicates JsonObject can be up to 20 times faster than the nearest Scala JSON library on some important operations. It achieves this mostly by being built around simple, but very fast, mutable JVM data structures.<\/li>\n<li>Flexibility. \u00a0The default JsonObject interface throws exceptions (the only place in the SDK that does). \u00a0Or you can easily convert it to a JsonObjectSafe, which provides a functional Try-based interface.<\/li>\n<li>Ease-of-use and mutability. We find ourselves in agreement with<a href=\"https:\/\/www.lihaoyi.com\/post\/uJsonfastflexibleandintuitiveJSONforScala.html\"> the author of \u00b5Json<\/a> that though immutability is usually desirable, it\u2019s not always the best choice in the particular case of JSON. Dealing with deeply nested JSON requires functional tools such as lenses which are rarely easy to read and use, not to mention possibly incurring a performance penalty. And JSON is most often dealt with briefly and in a limited scope (e.g. getting and modifying a document), so rarely benefits from the safety of immutability. So JsonObject presents a simple mutable API.<\/li>\n<\/ul>\n<p>You can delve into the <a href=\"https:\/\/docs.couchbase.com\/scala-sdk\/1.0\/howtos\/json.html#jsonobject-and-jsonarray\">JsonObject docs here<\/a>. \u00a0Of course, if you\u2019d rather have a more \u2018typically Scala\u2019 JSON library with immutable data, algebraic data types, lenses, cursors and other functional goodies, then one of the other supported libraries may be a better choice &#8211; the choice is yours, and you can easily mix and match multiple JSON libraries in the same app.<\/p>\n<h4><b>Direct Case Class Support<\/b><\/h4>\n<p>Though the Scala SDK has great support for JSON, sometimes it\u2019s easier and preferable to work directly with Scala case classes.<\/p>\n<p>By just adding this tiny bit of boilerplate for your case class, the SDK can automatically generate serialization logic:<\/p>\n<pre class=\"lang:scala decode:true\">case class User(name: String, age: Int)\r\n\r\nobject User {\r\n    implicit val codec: Codec[User] = Codecs.codec[User]\r\n}<\/pre>\n<p>And then you can easily send that case class directly to, and receive it back from, the SDK:<\/p>\n<pre class=\"lang:default decode:true\">val r: Try[User] = collection.insert(\u201cdocId\u201d, User(\u201cJohn Smith\u201d, 29))\r\n    .flatMap(_ =&gt; collection.get(\u201cdocId\u201d)\r\n    .flatMap(doc =&gt; doc.contentAs[User])<\/pre>\n<p>Under the hood this is converted and stored on Couchbase Server as the JSON you&#8217;d expect:<\/p>\n<pre class=\"lang:default decode:true\">{\"name\":\"John Smith\",\"age\":29}<\/pre>\n<p>This is plain ordinary JSON with no extra serialization metadata or similar, so it can be freely written as a case class and read out into a JSON library or by another SDK &#8211; or vice versa.<\/p>\n<p>Check out the <a href=\"https:\/\/docs.couchbase.com\/scala-sdk\/1.0\/howtos\/json.html#case-classes\">documentation on using case classes<\/a> for more.<\/p>\n<h3><b>Easy Queries<\/b><\/h3>\n<p>We\u2019ve made it as easy as possible to use Couchbase Analytics, N1QL and Full Text Search. \u00a0Here\u2019s an example of a N1QL query where rows are converted into JsonObject.<\/p>\n<pre class=\"lang:default decode:true\">cluster.query(\"\"\"select * from `travel-sample` limit 10;\"\"\")\r\n    .flatMap(_.allRowsAs[JsonObject]) match {\r\n\r\n    case Success(rows: Seq[JsonObject]) =&gt;\r\n        rows.foreach(row =&gt; println(row))\r\n    case Failure(err) =&gt;\r\n        println(s\"Error: $err\")\r\n}<\/pre>\n<p>And of course it\u2019s possible to get those results as any of the supported JSON types above, or directly as Scala case classes.<\/p>\n<p>And as mentioned above, using the reactive API means you get automatic backpressure for free, ensuring that your application consumes rows at a manageable rate and cannot hit out-of-memory issues on very large queries.<\/p>\n<p>&nbsp;<\/p>\n<p>If you\u2019re excited to get started with the Couchbase Scala SDK, then check out the <a href=\"https:\/\/docs.couchbase.com\/scala-sdk\/1.0\/start-using-sdk.html\">quickstart guide<\/a>. \u00a0It\u2019s available right now, though in an early alpha form. \u00a0There may be a few breaking changes ahead before going to GA, but on the flip-side this is the perfect time to try it out and give us your feedback by dropping a comment below, or raising it on <a href=\"https:\/\/www.couchbase.com\/forums\/\">our forums<\/a>, <a href=\"https:\/\/twitter.com\/couchbase\">Twitter<\/a> or <a href=\"https:\/\/gitter.im\/couchbase\/discuss?source=orgpage\">gitter<\/a>.\u00a0 Nothing is set in stone and we welcome the chance to make some changes and make this the best SDK possible.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019m very happy to report that Couchbase now has a supported Scala SDK, allowing you to get and fetch documents, run N1QL queries, perform analytics and full text search lookups &#8211; all with native Scala. In this blog I\u2019m going [&hellip;]<\/p>\n","protected":false},"author":40102,"featured_media":7088,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[2201],"tags":[],"ppma_author":[9084],"class_list":["post-7085","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tools-sdks"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Introducing the Couchbase Scala SDK - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"The Scala SDK is available to download, in a pre-release alpha form. Learn more about the key features and design principles of the Scala SDK.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Introducing the Couchbase Scala SDK\" \/>\n<meta property=\"og:description\" content=\"The Scala SDK is available to download, in a pre-release alpha form. Learn more about the key features and design principles of the Scala SDK.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-06-18T15:03:34+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-05-19T11:35:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/06\/scala_and_couchbase.png\" \/>\n\t<meta property=\"og:image:width\" content=\"666\" \/>\n\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Graham Pople, Senior Software Engineer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Graham Pople, Senior Software Engineer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/\"},\"author\":{\"name\":\"Graham Pople, Senior Software Engineer, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/40b3fd994e3f33a8068e54e36577eb8e\"},\"headline\":\"Introducing the Couchbase Scala SDK\",\"datePublished\":\"2019-06-18T15:03:34+00:00\",\"dateModified\":\"2023-05-19T11:35:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/\"},\"wordCount\":1417,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png\",\"articleSection\":[\"Tools &amp; SDKs\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/\",\"name\":\"Introducing the Couchbase Scala SDK - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png\",\"datePublished\":\"2019-06-18T15:03:34+00:00\",\"dateModified\":\"2023-05-19T11:35:50+00:00\",\"description\":\"The Scala SDK is available to download, in a pre-release alpha form. Learn more about the key features and design principles of the Scala SDK.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png\",\"width\":666,\"height\":350},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Introducing the Couchbase Scala SDK\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/40b3fd994e3f33a8068e54e36577eb8e\",\"name\":\"Graham Pople, Senior Software Engineer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/d0840b7ec045a43a30d21b57fa29318b\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/4084d00daa868b9b163191a655774c94b21629bbeecd00916470d9d9878462a7?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/4084d00daa868b9b163191a655774c94b21629bbeecd00916470d9d9878462a7?s=96&d=mm&r=g\",\"caption\":\"Graham Pople, Senior Software Engineer, Couchbase\"},\"description\":\"Graham is a senior software engineer at Couchbase who works on the SDK and Connectors team, mainly on the Scala and Java clients. Make his day by asking him about home composting.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/grahamp\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Introducing the Couchbase Scala SDK - The Couchbase Blog","description":"The Scala SDK is available to download, in a pre-release alpha form. Learn more about the key features and design principles of the Scala SDK.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/","og_locale":"en_US","og_type":"article","og_title":"Introducing the Couchbase Scala SDK","og_description":"The Scala SDK is available to download, in a pre-release alpha form. Learn more about the key features and design principles of the Scala SDK.","og_url":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/","og_site_name":"The Couchbase Blog","article_published_time":"2019-06-18T15:03:34+00:00","article_modified_time":"2023-05-19T11:35:50+00:00","og_image":[{"width":666,"height":350,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/06\/scala_and_couchbase.png","type":"image\/png"}],"author":"Graham Pople, Senior Software Engineer, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Graham Pople, Senior Software Engineer, Couchbase","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/"},"author":{"name":"Graham Pople, Senior Software Engineer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/40b3fd994e3f33a8068e54e36577eb8e"},"headline":"Introducing the Couchbase Scala SDK","datePublished":"2019-06-18T15:03:34+00:00","dateModified":"2023-05-19T11:35:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/"},"wordCount":1417,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png","articleSection":["Tools &amp; SDKs"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/","url":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/","name":"Introducing the Couchbase Scala SDK - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png","datePublished":"2019-06-18T15:03:34+00:00","dateModified":"2023-05-19T11:35:50+00:00","description":"The Scala SDK is available to download, in a pre-release alpha form. Learn more about the key features and design principles of the Scala SDK.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/06\/scala_and_couchbase.png","width":666,"height":350},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-scala-sdk\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Introducing the Couchbase Scala SDK"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/40b3fd994e3f33a8068e54e36577eb8e","name":"Graham Pople, Senior Software Engineer, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/d0840b7ec045a43a30d21b57fa29318b","url":"https:\/\/secure.gravatar.com\/avatar\/4084d00daa868b9b163191a655774c94b21629bbeecd00916470d9d9878462a7?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4084d00daa868b9b163191a655774c94b21629bbeecd00916470d9d9878462a7?s=96&d=mm&r=g","caption":"Graham Pople, Senior Software Engineer, Couchbase"},"description":"Graham is a senior software engineer at Couchbase who works on the SDK and Connectors team, mainly on the Scala and Java clients. Make his day by asking him about home composting.","url":"https:\/\/www.couchbase.com\/blog\/author\/grahamp\/"}]}},"authors":[{"term_id":9084,"user_id":40102,"is_guest":0,"slug":"grahamp","display_name":"Graham Pople, Senior Software Engineer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/4084d00daa868b9b163191a655774c94b21629bbeecd00916470d9d9878462a7?s=96&d=mm&r=g","author_category":"","last_name":"Pople, Senior Software Engineer, Couchbase","first_name":"Graham","job_title":"","user_url":"","description":"Graham is a senior software engineer at Couchbase who works on the SDK and Connectors team, mainly on the Scala and Java clients.  Make his day by asking him about home composting."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/7085","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/40102"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=7085"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/7085\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/7088"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=7085"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=7085"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=7085"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=7085"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}