{"id":6440,"date":"2023-07-18T07:00:45","date_gmt":"2023-07-18T14:00:45","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=6440"},"modified":"2024-07-29T05:44:16","modified_gmt":"2024-07-29T12:44:16","slug":"latest-nosql-java-ecosystem-updates-2023-q1-q2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/latest-nosql-java-ecosystem-updates-2023-q1-q2\/","title":{"rendered":"Latest NoSQL Java Ecosystem Updates 2023 Q1 &amp; Q2"},"content":{"rendered":"<p>We&#8217;re always busy adding new features, fixes, patches, and improvements to our <a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/azure-cosmos-db-java-ecosystem\/\" target=\"_blank\" rel=\"noopener\">Java-based client libraries for Azure Cosmos DB for NoSQL<\/a>. In this regular blog series, we share highlights of recent updates in the last period.<\/p>\n<p>&nbsp;<\/p>\n<h2>January &#8211; June 2023 updates<\/h2>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"text-align: left;\"><a href=\"#spring-data-enhanced-multi-tenancy-support\">Spring data &#8211; enhanced multi-tenancy support<\/a><\/li>\n<li><a href=\"#azure-active-directory-authentication-support-for-spark-connector\">Azure Active Directory authentication support for Spark Connector<\/a><\/li>\n<li><a href=\"#java-sdk-proactive-connection-management\">Java SDK Proactive Connection Management<\/a><\/li>\n<li><a href=\"#hierarchical-partition-key-support\">Hierarchical Partition Key support<\/a><\/li>\n<li><a href=\"#retriable-writes\">Retriable Writes<\/a><\/li>\n<li><a href=\"#partition-merge-support\">Partition merge support<\/a><\/li>\n<li><a href=\"#end-to-end-timeout-policy\">End-to-end timeout policy<\/a><\/li>\n<li><a href=\"#threshold-based-availability-optimization\">Threshold-based availability optimization<\/a><\/li>\n<li><a href=\"#priority-based-throttling\">Priority-based throttling<\/a><\/li>\n<li><a href=\"#computed-properties\">Computed Properties<\/a><\/li>\n<li><a href=\"#request-level-metrics-filtering\">Request-level metrics filtering<\/a><\/li>\n<li><a href=\"#spring-boot-3-support-for-spring-data\">Spring Boot 3 support for Spring Data<\/a><\/li>\n<li><a href=\"#kafka-connector-enhancements\">Kafka connector enhancements<\/a><\/li>\n<li><a href=\"#session-token-mismatch-optimization\">Session token mismatch optimization<\/a><\/li>\n<li><a href=\"#fixes-patches-and-enhancements\">Fixes, patches, and enhancements<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h5>Spring data &#8211; enhanced multi-tenancy support<\/h5>\n<p>In January 2023 we added enhanced support for <a href=\"https:\/\/learn.microsoft.com\/azure\/architecture\/guide\/multitenant\/service\/cosmos-db\" target=\"_blank\" rel=\"noopener\">building multi-tenant applications in Azure Cosmos DB<\/a> using the Azure <a href=\"https:\/\/aka.ms\/JavaCosmosSpringDevGuide\" target=\"_blank\" rel=\"noopener\">Cosmos DB Spring Data Client Library<\/a>. Developers can now implement a <a href=\"https:\/\/learn.microsoft.com\/azure\/architecture\/guide\/multitenant\/service\/cosmos-db#database-per-tenant\" target=\"_blank\" rel=\"noopener\">database per tenant<\/a>\u00a0or\u00a0<a href=\"https:\/\/learn.microsoft.com\/azure\/architecture\/guide\/multitenant\/service\/cosmos-db#container-per-tenant\" target=\"_blank\" rel=\"noopener\">container per tenant<\/a> performance isolation model seamlessly integrated into the <a href=\"https:\/\/docs.spring.io\/spring-data\/data-commons\/docs\/1.6.1.RELEASE\/reference\/html\/repositories.html\" target=\"_blank\" rel=\"noopener\">Spring Data Repository\u00a0<\/a>abstraction layer. Check out <a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/building-multi-tenant-java-apps-using-spring-data-and-azure-cosmos-db\/\" target=\"_blank\" rel=\"noopener\">this blog<\/a> for more details!<\/p>\n<p>&nbsp;<\/p>\n<h5>Azure Active Directory authentication support for Spark Connector<\/h5>\n<p>Azure Active Directory support was added in February 2023 for the <a href=\"https:\/\/aka.ms\/JavaCosmosSparkConnectorLatest\" target=\"_blank\" rel=\"noopener\">OLTP Spark connector<\/a>. Check out the documentation <a href=\"https:\/\/aka.ms\/CosmosSparkConnectorAAD\" target=\"_blank\" rel=\"noopener\">here<\/a>, and the fully worked sample <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/blob\/main\/sdk\/cosmos\/azure-cosmos-spark_3_2-12\/Samples\/Scala\/NYC-Taxi-Data\/01_Batch_AAD.scala\" target=\"_blank\" rel=\"noopener\">here<\/a>!<\/p>\n<p>&nbsp;<\/p>\n<h5>Java SDK Proactive Connection Management<\/h5>\n<p>In February 2023 <a href=\"https:\/\/aka.ms\/CosmosJavaProactiveConnections\" target=\"_blank\" rel=\"noopener\">proactive connection management<\/a> was added to the Java SDK. Developers can now warm up connections and caches for containers for both the current read region and a pre-defined number of preferred remote regions, as opposed to just the current read region. Some scenarios in which you may want to do this would include:<\/p>\n<ul>\n<li>Improving tail latency in cross-region failover scenarios (for example with <a href=\"#threshold-based-speculative-processing\">speculative processing<\/a>).<\/li>\n<li>Reducing overall latency for writes in multi-region scenarios where only a single write region is configured.<\/li>\n<\/ul>\n<p>Define the number of regions for which you want connections to be warmed up, and the SDK will use the list of preferred regions configured through <a href=\"https:\/\/aka.ms\/CosmosJavaPreferredRegions\" target=\"_blank\" rel=\"noopener\">CosmosClientBuilder<\/a>. A duration can also be specified within which connections are established aggressively in a blocking manner. Once this duration elapses, connections are established defensively but in a non-blocking manner.<\/p>\n<pre class=\"notranslate\"><span class=\"pl-c\">\/\/ containers to which connections are to be proactively opened<\/span>\r\n<span class=\"pl-smi\">CosmosContainerIdentity<\/span> <span class=\"pl-s1\">containerIdentity1<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">CosmosContainerIdentity<\/span>(<span class=\"pl-s\">\"sample_db_id\"<\/span>, <span class=\"pl-s\">\"sample_container_id_1\"<\/span>);\r\n<span class=\"pl-smi\">CosmosContainerIdentity<\/span> <span class=\"pl-s1\">containerIdentity2<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">CosmosContainerIdentity<\/span>(<span class=\"pl-s\">\"sample_db_id\"<\/span>, <span class=\"pl-s\">\"sample_container_id_2\"<\/span>);\r\n\r\n<span class=\"pl-c\">\/\/ no. of regions to which connections are to be proactively opened<\/span>\r\n<span class=\"pl-smi\">int<\/span> <span class=\"pl-s1\">proactiveConnectionRegionsCount<\/span> = <span class=\"pl-c1\">1<\/span>;\r\n\r\n<span class=\"pl-c\">\/\/ duration for which connections are to be aggressively opened in a blocking manner<\/span>\r\n<span class=\"pl-c\">\/\/ beyond this duration connections will be defensively opened in a non-blocking manner<\/span>\r\n<span class=\"pl-smi\">Duration<\/span> <span class=\"pl-s1\">aggressiveWarmupDuration<\/span> = <span class=\"pl-smi\">Duration<\/span>.<span class=\"pl-en\">ofSeconds<\/span>(<span class=\"pl-c1\">1<\/span>);\r\n\r\n<span class=\"pl-c\">\/\/ building the client along with opening connections<\/span>\r\n<span class=\"pl-smi\">CosmosAsyncClient<\/span> <span class=\"pl-s1\">clientWithOpenConnections<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">CosmosClientBuilder<\/span>()\r\n          .<span class=\"pl-en\">endpoint<\/span>(<span class=\"pl-s\">\"&lt;account URL goes here\"<\/span>)\r\n          .<span class=\"pl-en\">key<\/span>(<span class=\"pl-s\">\"&lt;account key goes here&gt;\"<\/span>)\r\n          .<span class=\"pl-en\">endpointDiscoveryEnabled<\/span>(<span class=\"pl-c1\">true<\/span>)\r\n          .<span class=\"pl-en\">preferredRegions<\/span>(<span class=\"pl-smi\">Arrays<\/span>.<span class=\"pl-en\">asList<\/span>(<span class=\"pl-s\">\"sample_region_1\"<\/span>, <span class=\"pl-s\">\"sample_region_2\"<\/span>))\r\n          .<span class=\"pl-en\">openConnectionsAndInitCaches<\/span>(<span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">CosmosContainerProactiveInitConfigBuilder<\/span>(<span class=\"pl-smi\">Arrays<\/span>.<span class=\"pl-en\">asList<\/span>(<span class=\"pl-s1\">containerIdentity1<\/span>, <span class=\"pl-s1\">containerIdentity2<\/span>))\r\n                .<span class=\"pl-en\">setProactiveConnectionRegionsCount<\/span>(<span class=\"pl-s1\">proactiveConnectionRegionsCount<\/span>)\r\n                .<span class=\"pl-en\">setAggressiveWarmupDuration<\/span>(<span class=\"pl-s1\">aggressiveWarmupDuration<\/span>)\r\n                .<span class=\"pl-en\">build<\/span>())\r\n          .<span class=\"pl-en\">directMode<\/span>()\r\n          .<span class=\"pl-en\">buildAsyncClient<\/span>();<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h5>Hierarchical Partition Key support<\/h5>\n<p>Support for <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/hierarchical-partition-keys\" target=\"_blank\" rel=\"noopener\">hierarchical partition keys in Azure Cosmos DB<\/a> was made GA for the Java SDK in March 2023. Check out code examples <a href=\"https:\/\/aka.ms\/CosmosJavaSubpartitioning\" target=\"_blank\" rel=\"noopener\">here<\/a>! Note: this is currently available <strong>only<\/strong> for the <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/nosql\/sdk-java-v4\" target=\"_blank\" rel=\"noopener\">core Java SDK<\/a>, and is not yet supported for the other connectors at the time of writing.<\/p>\n<p>&nbsp;<\/p>\n<h5>Retriable Writes<\/h5>\n<p>We&#8217;ve added support for retrying writes when they are not guaranteed to be idempotent. Previously the SDK would only issue retries for write operations when the failure condition happened before the request was actually written to the network, or when the error code from the service guarantees that the service never processed the request. But now, developers can now opt-in to retrying writes at a request level, even when these conditions are not met. See <a href=\"https:\/\/aka.ms\/CosmosJavaRetriableWrites\" target=\"_blank\" rel=\"noopener\">here<\/a> for more details.<\/p>\n<pre class=\"notranslate\"><span class=\"pl-smi\">String<\/span> <span class=\"pl-s1\">pkValue<\/span> = <span class=\"pl-s\">\"myPKValue\"<\/span>; <span class=\"pl-c\">\/\/ whatever the logical partition key value is      <\/span>\r\n<span class=\"pl-smi\">boolean<\/span> <span class=\"pl-c1\">ENABLE_RETRIES<\/span> = <span class=\"pl-c1\">true<\/span>;\r\n<span class=\"pl-smi\">boolean<\/span> <span class=\"pl-c1\">USE_TRACKING_ID<\/span> = <span class=\"pl-c1\">true<\/span>;\r\n<span class=\"pl-smi\">CosmosItemRequestOptions<\/span> <span class=\"pl-s1\">optionsWithRetry<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">CosmosItemRequestOptions<\/span>()\r\n    .<span class=\"pl-en\">setNonIdempotentWriteRetryPolicy<\/span>(<span class=\"pl-c1\">ENABLE_RETRIES<\/span>, <span class=\"pl-c1\">USE_TRACKING_ID<\/span>);\r\n<span class=\"pl-s1\">asyncContainer<\/span>.<span class=\"pl-en\">createItem<\/span>(<span class=\"pl-s1\">item<\/span>, <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">PartitionKey<\/span>(<span class=\"pl-s1\">pkValue<\/span>), <span class=\"pl-s1\">optionsWithRetry<\/span>).<span class=\"pl-en\">block<\/span>();\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><\/h5>\n<h5><\/h5>\n<h5>Partition merge support<\/h5>\n<p><a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/merge\" target=\"_blank\" rel=\"noopener\">Merging partitions in Azure Cosmos DB<\/a> are now fully supported for the Java SDK, Spark Connector, and Spring Data Client Library!<\/p>\n<p>&nbsp;<\/p>\n<h5>End-to-end timeout policy<\/h5>\n<p><span class=\"ui-provider fz b c d e f g h i j k l m n o p q r s t u v w x y z ab ac ae af ag ah ai aj ak\" dir=\"ltr\">We observed that many customers want to set aggressive end-to-end timeouts, which ultimately impacted tail latency and effectively caused availability to drop significantly since requests were not being canceled. <\/span><\/p>\n<p>The Java SDK now supports an end-to-end timeout policy, allowing developers to provide a timeout value that covers the whole execution of any request, including requests that span multiple partitions. Ongoing requests will be canceled if the timeout setting is reached.<\/p>\n<p><span class=\"ui-provider fz b c d e f g h i j k l m n o p q r s t u v w x y z ab ac ae af ag ah ai aj ak\" dir=\"ltr\">This helps to optimize availability while still honoring aggressive end-to-end timeouts. T<\/span>ail latency is reduced by failing faster, and <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/request-units\" target=\"_blank\" rel=\"noopener\">request units<\/a> and client-side compute costs are reduced by stopping retries after the timeout.<\/p>\n<p>The timeout duration can be set on CosmosItemRequestOptions. The options can then be passed to any request sent to Azure Cosmos DB.<\/p>\n<pre>CosmosEndToEndOperationLatencyPolicyConfig endToEndOperationLatencyPolicyConfig = new CosmosEndToEndOperationLatencyPolicyConfigBuilder(Duration.ofSeconds(1)).build();\r\nCosmosItemRequestOptions options = new CosmosItemRequestOptions();\r\noptions.setCosmosEndToEndOperationLatencyPolicyConfig(endToEndOperationLatencyPolicyConfig);\r\ncontainer.readItem(\"id\", new PartitionKey(\"pk\"), options, TestObject.class);<\/pre>\n<p>&nbsp;<\/p>\n<h5>Threshold-based availability optimization<\/h5>\n<p>A new threshold-based parallel processing capability in the Java SDK has also been added, which can be activated when creating an end-to-end timeout policy as above, to even further improve tail latency and availability. When enabled, parallel executions of the same request (read requests only) will be sent to secondary regions, where the request that responds fastest is the one that is accepted.<\/p>\n<p><strong>How parallel execution works<\/strong><\/p>\n<p>The object <code>ThresholdBasedAvailabilityStrategy<\/code> takes two parameters. The first is the <code>threshold<\/code>, and the second is the <code>threshold step<\/code>.<\/p>\n<p>Assume you have three regions set as `preferredRegions` in <a href=\"https:\/\/aka.ms\/CosmosJavaPreferredRegions\" target=\"_blank\" rel=\"noopener\">CosmosClientBuilder<\/a>, in the following order:\u00a0 <code>East US<\/code>, <code>East US 2<\/code>, <code>West US<\/code>.<\/p>\n<p>Assume the following values for <code>speculation threshold<\/code>\u00a0and <code>threshold step<\/code>:<\/p>\n<pre>int threshold = 500;\r\nint thresholdStep = 100;\r\n\r\n<\/pre>\n<ol>\n<li>At time T1, a request to <code>East US<\/code> is made.<\/li>\n<li>If there is no response in 500ms, a request to <code>East US 2<\/code> is made.<\/li>\n<li>If there is no response at 500+100ms, a request to <code>West US<\/code> is made.<\/li>\n<\/ol>\n<pre>int threshold = 500;\r\nint thresholdStep = 100;\r\nCosmosEndToEndOperationLatencyPolicyConfig config = new CosmosEndToEndOperationLatencyPolicyConfigBuilder(Duration.ofSeconds(3))\r\n        .availabilityStrategy(new ThresholdBasedAvailabilityStrategy(Duration.ofMillis(threshold), Duration.ofMillis(thresholdStep)))\r\n        .build();\r\nCosmosItemRequestOptions options = new CosmosItemRequestOptions();\r\noptions.setCosmosEndToEndOperationLatencyPolicyConfig(config);\r\ncontainer.readItem(\"id\", new PartitionKey(\"pk\"), options, JsonNode.class).block();\r\n<\/pre>\n<p>Note that in the case where cross region requests are required, this can incur additional cost in terms of <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/request-units\" target=\"_blank\" rel=\"noopener\">request units<\/a> &#8211; but this is of course a trade-off one would choose in order to drastically reduce and in some cases eliminate tail latency.<\/p>\n<p>&nbsp;<\/p>\n<h5>Priority-based throttling<\/h5>\n<p>We have introduced Priority Based Throttling to the Java SDK, allowing developers to set a priority on their request. This will help them avoid throttling on high-priority requests and will throttle the low-priority requests. In the Java SDK, priority-based throttling has been exposed as a property of <a href=\"https:\/\/aka.ms\/CosmosJavaThroughputControl\" target=\"_blank\" rel=\"noopener\">throughput control groups<\/a>. You can read more about priority-based throttling in our blog <a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/introducing-priority-based-execution-in-azure-cosmos-db-preview\/\" target=\"_blank\" rel=\"noopener\">here<\/a>, and a demo sample of priority-based throttling <a href=\"https:\/\/github.com\/Azure-Samples\/azure-cosmos-java-sql-api-samples\/blob\/da39bf4e57c6d814c478d10eed5c2905a764d667\/src\/main\/java\/com\/azure\/cosmos\/examples\/throughputcontrol\/async\/ThroughputControlQuickstartAsync.java#L233\" target=\"_blank\" rel=\"noopener\">here<\/a>. Priority-based throttling can also be enabled in the Spark Connector by setting <code>spark.cosmos.throughputControl.priorityLevel<\/code> to <code>low<\/code> or <code>high<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<h5>Computed Properties<\/h5>\n<p>Support for <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/nosql\/query\/computed-properties?tabs=java\" target=\"_blank\" rel=\"noopener\">computed properties<\/a> is now available in the Java SDK. See <a href=\"https:\/\/aka.ms\/CosmosJavaComputedProperties\" target=\"_blank\" rel=\"noopener\">here<\/a> for code examples.<\/p>\n<p>&nbsp;<\/p>\n<h5>Request-level metrics filtering<\/h5>\n<p>In the last period, we released support for <a href=\"https:\/\/aka.ms\/CosmosJavaSDKClientSideMetrics\" target=\"_blank\" rel=\"noopener\">emitting metrics from the Azure Cosmos DB Java SDK<\/a> via a <a href=\"https:\/\/micrometer.io\/\" target=\"_blank\" rel=\"noopener\">micrometer MeterRegistry<\/a>. In recent months, we added support for filtering metrics based on certain thresholds. This will reduce the overhead significantly, as request-level metrics will be sampled and only be emitted when operations violate the expected thresholds (latency, Request Unit charge, etc.). You can also now apply sampling for diagnostic capturing in the Azure Cosmos DB SDK using <code>sampleDiagnostic<\/code>, to help further tune client-side resource consumption related to metrics. The sampling rate can be modified after Azure Cosmos DB Client initialization &#8211; so the sampling rate can be modified without any restarts being necessary.<\/p>\n<pre>PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);\r\n\r\n\/\/provide the prometheus registry to the telemetry config\r\nCosmosClientTelemetryConfig telemetryConfig = new CosmosClientTelemetryConfig()\r\n        .diagnosticsThresholds(\r\n                new CosmosDiagnosticsThresholds()\r\n                        .setRequestChargeThreshold(10)\r\n                        .setNonPointOperationLatencyThreshold(Duration.ofDays(10))\r\n                        .setPointOperationLatencyThreshold(Duration.ofDays(10))\r\n        )\r\n        .sampleDiagnostics(0.25)\r\n        .clientCorrelationId(\"samplePrometheusMetrics001\")\r\n        .metricsOptions(new CosmosMicrometerMetricsOptions().meterRegistry(prometheusRegistry)\r\n                \/\/.configureDefaultTagNames(CosmosMetricTagName.PARTITION_KEY_RANGE_ID)\r\n                .applyDiagnosticThresholdsForTransportLevelMeters(true)\r\n        );<\/pre>\n<h5>Spring Boot 3 support for Spring Data<\/h5>\n<p>Support for Spring Boot 3 has been added to the latest version of the <a href=\"https:\/\/aka.ms\/JavaCosmosSpringDevGuide\" target=\"_blank\" rel=\"noopener\">Azure Cosmos DB Spring Data Client Library<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h5>Kafka connector enhancements<\/h5>\n<p>We&#8217;ve added two configurable enhancements to <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/nosql\/kafka-connector\" target=\"_blank\" rel=\"noopener\">Kafka Connect for Azure Cosmos DB<\/a>:<\/p>\n<ol>\n<li>When using the <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/nosql\/kafka-connector-source\" target=\"_blank\" rel=\"noopener\">source connector<\/a>, determine whether to update the lease container continuation token based on Kafka offset using config <code>connect.cosmos.offset.useLatest<\/code>. This resolves issues that may occur depending on whether a lease container is, or is not, initialized. By default, this is set to <code>false<\/code>. See the <a href=\"https:\/\/github.com\/microsoft\/kafka-connect-cosmosdb\/blob\/dev\/CHANGELOG.md#190-2023-06-19\" target=\"_blank\" rel=\"noopener\">change log<\/a> for more information.<\/li>\n<li>When using the <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/nosql\/kafka-connector-sink\" target=\"_blank\" rel=\"noopener\">sink connector<\/a>, determine whether to enable &#8220;compression&#8221; to remove duplicate records in a single batch, using the config <code>connect.cosmos.sink.bulk.compression.enabled<\/code>. When set to <code>true<\/code>, this ensures that when there are multiple records arriving from Kafka which have the same <code>id<\/code> value in a given batch, only the record with the latest timestamp is kept. By default, this is set to <code>true<\/code>.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h5>Session token mismatch optimization<\/h5>\n<p>One of the <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/consistency-levels\" target=\"_blank\" rel=\"noopener\">consistency levels<\/a> that Azure Cosmos DB provides is <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/consistency-levels#session-consistency\" target=\"_blank\" rel=\"noopener\">session consistency<\/a>. With this setting, reads are guaranteed to honor the read-your-writes, and write-follows-reads guarantees. After every write operation, the client receives an updated Session Token from the server. The client caches the tokens and sends them to the server for read operations in a specified region. However, there are some scenarios where <code class=\"notranslate\">404 \/ 1002<\/code>\u00a0(<code class=\"notranslate\">NOT_FOUND \/ READ_SESSION_NOT_AVAILABLE<\/code>) errors are returned by the service. This can occur when:<\/p>\n<ul dir=\"auto\">\n<li>The session token in the request has a higher\u00a0<code class=\"notranslate\">GlobalLSN<\/code>\u00a0value or a higher\u00a0<code class=\"notranslate\">LocalLSN<\/code>\u00a0value (specific to multi-write accounts) than that of the session token in the response. This points to either a lagging region or a lagging replica.<\/li>\n<li>A loss of quorum between replicas due to network partition between them.<\/li>\n<\/ul>\n<p>By default, the SDK will retry all replicas in the local region in order to obtain a valid session token. However, this might incur unnecessary tail latency in a multi-region deployment, if a valid session token can be obtained from a remote region. This change allows application developers to configure hints through a <code><span class=\"ui-provider fz b c d e f g h i j k l m n o p q r s t u v w x y z ab ac ae af ag ah ai aj ak\" dir=\"ltr\">SessionRetryOptions<\/span>\u00a0<\/code>instance which will signal to the SDK whether to pin retries on the local region or move quicker to a remote region, especially when\u00a0<code class=\"notranslate\">READ_SESSION_NOT_AVAILABLE<\/code> errors are thrown.<\/p>\n<p>First, build the <code><span class=\"ui-provider fz b c d e f g h i j k l m n o p q r s t u v w x y z ab ac ae af ag ah ai aj ak\" dir=\"ltr\">SessionRetryOptions<\/span>\u00a0<\/code>instance:<\/p>\n<div class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre class=\"notranslate\"><span class=\"pl-c\">\/\/ if local region retries are prioritzed<\/span>\r\n<span class=\"pl-smi\">SessionRetryOptions<\/span> <span class=\"pl-s1\">sessionRetryOptions<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">SessionRetryOptionsBuilder<\/span>()\r\n                .<span class=\"pl-en\">setRegionSwitchHint<\/span>(<span class=\"pl-smi\">CosmosRegionSwitchHint<\/span>.<span class=\"pl-c1\">LOCAL_REGION_PREFERRED<\/span>)\r\n                .<span class=\"pl-en\">build<\/span>();<\/pre>\n<\/div>\n<div class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre class=\"notranslate\"><span class=\"pl-c\">\/\/ if remote region retries are prioritized<\/span>\r\n<span class=\"pl-smi\">SessionRetryOptions<\/span> <span class=\"pl-s1\">sessionRetryOptions<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">SessionRetryOptionsBuilder<\/span>()\r\n                .<span class=\"pl-en\">setRegionSwitchHint<\/span>(<span class=\"pl-smi\">CosmosRegionSwitchHint<\/span>.<span class=\"pl-c1\">REMOTE_REGION_PREFERRED<\/span>)\r\n                .<span class=\"pl-en\">build<\/span>();<\/pre>\n<\/div>\n<p>Set the built\u00a0<code class=\"notranslate\">SessionRetryOptions<\/code>\u00a0instance on the\u00a0<code class=\"notranslate\">CosmosClientBuilder<\/code> instance:<\/p>\n<div class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre class=\"notranslate\"><span class=\"pl-smi\">CosmosAsyncClient<\/span> <span class=\"pl-s1\">clientWithPreferredRegions<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">CosmosClientBuilder<\/span>()\r\n    .<span class=\"pl-en\">endpoint<\/span>(<span class=\"pl-s\">\"&lt;account URL goes here&gt;\"<\/span>)\r\n    .<span class=\"pl-en\">key<\/span>(<span class=\"pl-s\">\"&lt;account key goes here&gt;\"<\/span>)\r\n    .<span class=\"pl-en\">sessionRetryOptions<\/span>(<span class=\"pl-s1\">sessionRetryOptions<\/span>)\r\n    .<span class=\"pl-en\">directMode<\/span>()\r\n    .<span class=\"pl-en\">buildAsyncClient<\/span>();<\/pre>\n<\/div>\n<p>In order to control the no. of retries in the local region when\u00a0<code class=\"notranslate\">REMOTE_REGION_PREFERRED<\/code>\u00a0is set as the region switch hint, set the following JVM config as below:<\/p>\n<div class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre class=\"notranslate\"><span class=\"pl-smi\">int<\/span> <span class=\"pl-s1\">maxRetriesInLocalRegion<\/span>= <span class=\"pl-c1\">5<\/span>;\r\n<span class=\"pl-smi\">System<\/span>.<span class=\"pl-en\">setProperty<\/span>(<span class=\"pl-s\">\"COSMOS.MAX_RETRIES_IN_LOCAL_REGION_WHEN_REMOTE_REGION_PREFERRED\"<\/span>, <span class=\"pl-smi\">String<\/span>.<span class=\"pl-en\">valueOf<\/span>(<span class=\"pl-s1\">maxRetriesInLocalRegion<\/span>));<\/pre>\n<\/div>\n<p><span class=\"ui-provider fz b c d e f g h i j k l m n o p q r s t u v w x y z ab ac ae af ag ah ai aj ak\" dir=\"ltr\">Using this hint can also improve CPU utilization since the SDK is not making as many retry requests to different replicas on a single region. Read availability also improves since we leverage more regions that the customer has configured for their account.\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h5><\/h5>\n<h5>Fixes, patches, and enhancements<\/h5>\n<p>In addition to all of the above features, we have of course made a large number of smaller bug fixes, security patches, enhancements, and improvements. You can track all the changes for each client library, along with the <strong>minimum version we recommend you use<\/strong>, by viewing the change logs:<\/p>\n<ul>\n<li><strong>Java SDK <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/blob\/main\/sdk\/cosmos\/azure-cosmos\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">change log<\/a><\/strong><\/li>\n<li><strong>Spring Data Client Library <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/blob\/main\/sdk\/spring\/azure-spring-data-cosmos\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">change log<\/a><\/strong><\/li>\n<li><strong>OLTP Spark Connector <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/blob\/main\/sdk\/cosmos\/azure-cosmos-spark_3-3_2-12\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">change log<\/a><\/strong><\/li>\n<li><strong>Kafka Connectors <a href=\"https:\/\/github.com\/microsoft\/kafka-connect-cosmosdb\/blob\/dev\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">change log<\/a><\/strong><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3 id=\"get-started\">Get Started with Java in Azure Cosmos DB<i class=\"fabric-icon fabric-icon--Link\" aria-hidden=\"true\"><\/i><\/h3>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/sql\/sql-api-sdk-java-v4\" target=\"_blank\" rel=\"noopener\">Azure Cosmos DB Java SDK v4 technical documentation<\/a><\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/nosql\/troubleshoot-java-sdk-v4?tabs=sync\" target=\"_blank\" rel=\"noopener\">Diagnose and troubleshoot Azure Cosmos DB Java SDK v4<\/a><\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/sql\/sql-api-java-sdk-samples\" target=\"_blank\" rel=\"noopener\">Azure Cosmos DB Java SDK v4 getting started sample application<\/a><\/li>\n<li><a href=\"https:\/\/aka.ms\/CosmosJavaSDKSamples\" target=\"_blank\" rel=\"noopener\">Java V4 SDK comprehensive samples repository<\/a><\/li>\n<li><a href=\"https:\/\/aka.ms\/CosmosSpringDataSamples\" target=\"_blank\" rel=\"noopener\">Azure Cosmos DB Spring Data Client Library Samples<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/AzureCosmosDB\/CosmicWorksJava\" target=\"_blank\" rel=\"noopener\">Cosmic Works Java<\/a><\/li>\n<li class=\"\"><a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/sql\/sql-api-sdk-java-v4\" target=\"_blank\" rel=\"noopener\">Release notes and additional resources<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/java-sdk-v4-async-vs-sync\/\" target=\"_blank\" rel=\"noopener\">Exploring the Async API (reactor programming)<\/a><\/li>\n<\/ul>\n<h3 id=\"about-azure-cosmos-db\">About Azure Cosmos DB<i class=\"fabric-icon fabric-icon--Link\" aria-hidden=\"true\"><\/i><\/h3>\n<p>Azure Cosmos DB is a fully managed and serverless distributed database for modern app development, with SLA-backed speed and availability, automatic and instant scalability, and support for open source PostgreSQL, MongoDB and Apache Cassandra. <a href=\"https:\/\/cosmos.azure.com\/try\/\">Try Azure Cosmos DB for free here<\/a>. To stay in the loop on Azure Cosmos DB updates, follow us on <a href=\"https:\/\/twitter.com\/AzureCosmosDB\">Twitter<\/a>, <a href=\"https:\/\/www.youtube.com\/AzureCosmosDB\">YouTube<\/a>, and <a href=\"https:\/\/www.linkedin.com\/company\/azure-cosmos-db\/\">LinkedIn<\/a>.<\/p>\n<p class=\"\">To easily build your first database, watch our\u00a0<a href=\"https:\/\/youtube.com\/playlist?list=PLmamF3YkHLoLLGUtSoxmUkORcWaTyHlXp\" target=\"_blank\" rel=\"noopener\">Get Started videos<\/a> on YouTube and explore ways to <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/optimize-dev-test\" target=\"_blank\" rel=\"noopener\">dev\/test free.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;re always busy adding new features, fixes, patches, and improvements to our Java-based client libraries for Azure Cosmos DB for NoSQL. In this regular blog series, we share highlights of recent updates in the last period. &nbsp; January &#8211; June 2023 updates &nbsp; Spring data &#8211; enhanced multi-tenancy support Azure Active Directory authentication support for [&hellip;]<\/p>\n","protected":false},"author":9387,"featured_media":5405,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[14,1915,643,1778,1849],"tags":[],"class_list":["post-6440","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-sql-api","category-java-ecosystem-updates","category-java-sdk","category-spark","category-spring-data"],"acf":[],"blog_post_summary":"<p>We&#8217;re always busy adding new features, fixes, patches, and improvements to our Java-based client libraries for Azure Cosmos DB for NoSQL. In this regular blog series, we share highlights of recent updates in the last period. &nbsp; January &#8211; June 2023 updates &nbsp; Spring data &#8211; enhanced multi-tenancy support Azure Active Directory authentication support for [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/6440","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/users\/9387"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=6440"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/6440\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/5405"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=6440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=6440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=6440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}