From 202f37e730a2d77c8a103d07c87431a2425c76a7 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 14:46:00 +0100 Subject: [PATCH 1/5] apply fix --- .../connectivity/GetOrComputeAllDestinationsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommand.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommand.java index ac9c217d2..bef1257ad 100644 --- a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommand.java +++ b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommand.java @@ -41,7 +41,7 @@ static GetOrComputeAllDestinationsCommand prepareCommand( final CacheKey cacheKey = CacheKey.ofTenantOptionalIsolation(); - cacheKey.append(destinationOptions); + cacheKey.append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(destinationOptions)); final ReentrantLock isolationLock = Objects.requireNonNull(isolationLocks.get(cacheKey, any -> new ReentrantLock())); From f04cf0bfb9413f23cb51b31ee01a249ca12f7d1a Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 15:18:02 +0100 Subject: [PATCH 2/5] adapt tests --- .../connectivity/DestinationServiceTest.java | 16 ++++++++++++---- .../GetOrComputeAllDestinationsCommandTest.java | 13 ++++++++++--- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java index a23533da1..55a418c9a 100644 --- a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java +++ b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java @@ -1255,9 +1255,13 @@ void testConcurrentFetchSameDestinationButDifferentTenant() assertThat(DestinationService.Cache.isolationLocks().asMap()) .containsOnlyKeys( CacheKey.fromIds("TenantA", null).append(destinationName, options), - CacheKey.fromIds("TenantA", null).append(options), + CacheKey + .fromIds("TenantA", null) + .append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(options)), CacheKey.fromIds("TenantB", null).append(destinationName, options), - CacheKey.fromIds("TenantB", null).append(options)); + CacheKey + .fromIds("TenantB", null) + .append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(options))); // assert cache entries for one get-single command for each tenant assertThat(DestinationService.Cache.instanceSingle().asMap()) @@ -1327,7 +1331,9 @@ void testPrincipalIsolationForDestinationWithUserPropagationWithExchangeOnlyStra .containsOnlyKeys( CacheKey.of(subscriberTenant, principal1).append(destinationName, options), CacheKey.of(subscriberTenant, principal2).append(destinationName, options), - CacheKey.of(subscriberTenant, null).append(options)); + CacheKey + .of(subscriberTenant, null) + .append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(options))); assertThat(DestinationService.Cache.instanceSingle().asMap()) .containsOnlyKeys( @@ -1371,7 +1377,9 @@ void testPrincipalIsolationForDestinationWithUserPropagationWithDefaultExchangeS assertThat(DestinationService.Cache.isolationLocks().asMap()) .containsOnlyKeys( CacheKey.of(subscriberTenant, null).append(destinationName, options), - CacheKey.of(subscriberTenant, null).append(options)); + CacheKey + .of(subscriberTenant, null) + .append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(options))); assertThat(DestinationService.Cache.instanceSingle().asMap()) .containsOnlyKeys( diff --git a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommandTest.java b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommandTest.java index afbd3cc98..a66528fb0 100644 --- a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommandTest.java +++ b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/GetOrComputeAllDestinationsCommandTest.java @@ -90,7 +90,12 @@ void testCommandIsIdempotent() assertThat(result.get()).containsExactly(destination); assertThat(allDestinationsCache.estimatedSize()).isEqualTo(1); - assertThat(allDestinationsCache.getIfPresent(CacheKey.ofNoIsolation().append(EMPTY_OPTIONS))) + assertThat( + allDestinationsCache + .getIfPresent( + CacheKey + .ofNoIsolation() + .append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(EMPTY_OPTIONS)))) .containsExactly(destination); verify(tryGetAllDestinations, times(1)).get(); } @@ -104,8 +109,10 @@ void testIsolationAndAtomicityPerTenant() final CountDownLatch mainThreadLatch = new CountDownLatch(1); final CountDownLatch getAllLatch = new CountDownLatch(1); final AtomicInteger lockInvocations = new AtomicInteger(); - final CacheKey t1Key = CacheKey.of(t1, null).append(EMPTY_OPTIONS); - final CacheKey t2Key = CacheKey.of(t2, null).append(EMPTY_OPTIONS); + final CacheKey t1Key = + CacheKey.of(t1, null).append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(EMPTY_OPTIONS)); + final CacheKey t2Key = + CacheKey.of(t2, null).append(DestinationServiceOptionsAugmenter.getRetrievalStrategy(EMPTY_OPTIONS)); final ReentrantLock tenantIsolationLock = spy(ReentrantLock.class); doAnswer(invocation -> { From bf810473e2c7df8cd356ff524210568ffa0780cb Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 7 Jan 2026 16:13:51 +0100 Subject: [PATCH 3/5] add warn log --- .../connectivity/DestinationService.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java index 840869d5e..98f763392 100644 --- a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java +++ b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java @@ -2,6 +2,7 @@ import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; @@ -878,11 +879,23 @@ private static Try> getOrComputeAllDestinations( return destinationDownloader.apply(options); } + if( isUsingExperimentalFeatures(options) ) { + log + .warn( + "Using cache/change detection together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected behaviour."); + } + return GetOrComputeAllDestinationsCommand .prepareCommand(options, instanceAll(), isolationLocks(), destinationDownloader) .execute(); } + private static boolean isUsingExperimentalFeatures( @Nonnull final DestinationOptions options ) + { + String[] featureNames = { "X-fragment-name", "crossLevelSetting", "customHeader" }; + return options.getOptionKeys().stream().anyMatch(s -> Arrays.stream(featureNames).anyMatch(s::contains)); + } + private Cache() { throw new IllegalStateException("This static class must never be instantiated."); From 87dd83d1fde7ac1d9123d9350870e57f37135c2f Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Thu, 8 Jan 2026 08:39:03 +0100 Subject: [PATCH 4/5] improve warn messages --- .../sdk/cloudplatform/connectivity/DestinationService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java index 98f763392..fe2d43bd4 100644 --- a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java +++ b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java @@ -848,6 +848,11 @@ private static Try getOrComputeDestination( @Nullable final GetOrComputeAllDestinationsCommand getAllCommand; if( changeDetectionEnabled ) { + if( isUsingExperimentalFeatures(options) ) { + log + .warn( + "Using change detection together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected caching behaviour."); + } getAllCommand = GetOrComputeAllDestinationsCommand .prepareCommand( @@ -882,7 +887,7 @@ private static Try> getOrComputeAllDestinations( if( isUsingExperimentalFeatures(options) ) { log .warn( - "Using cache/change detection together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected behaviour."); + "Using caching together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected caching behaviour."); } return GetOrComputeAllDestinationsCommand From 64dab3f0d341f0915a317d9e7bd98c6a11e1cbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 10:02:48 +0100 Subject: [PATCH 5/5] Minor fix --- .../connectivity/DestinationService.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java index fe2d43bd4..15dab98c7 100644 --- a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java +++ b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java @@ -7,6 +7,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiFunction; import java.util.function.Function; @@ -849,9 +850,9 @@ private static Try getOrComputeDestination( final GetOrComputeAllDestinationsCommand getAllCommand; if( changeDetectionEnabled ) { if( isUsingExperimentalFeatures(options) ) { - log - .warn( - "Using change detection together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected caching behaviour."); + final String msg = + "Using change detection together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected caching behaviour."; + log.warn(msg); } getAllCommand = GetOrComputeAllDestinationsCommand @@ -885,9 +886,9 @@ private static Try> getOrComputeAllDestinations( } if( isUsingExperimentalFeatures(options) ) { - log - .warn( - "Using caching together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected caching behaviour."); + final String msg = + "Using caching together with either fragments, cross-level options, or custom headers is discouraged and might lead to unexpected caching behaviour."; + log.warn(msg); } return GetOrComputeAllDestinationsCommand @@ -897,8 +898,9 @@ private static Try> getOrComputeAllDestinations( private static boolean isUsingExperimentalFeatures( @Nonnull final DestinationOptions options ) { - String[] featureNames = { "X-fragment-name", "crossLevelSetting", "customHeader" }; - return options.getOptionKeys().stream().anyMatch(s -> Arrays.stream(featureNames).anyMatch(s::contains)); + final String[] featureNames = { "X-fragment-name", "crossLevelSetting", "customHeader" }; + final Set keys = options.getOptionKeys(); + return keys.stream().anyMatch(s -> Arrays.stream(featureNames).anyMatch(s::equalsIgnoreCase)); } private Cache()