From 202f37e730a2d77c8a103d07c87431a2425c76a7 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 14:46:00 +0100 Subject: [PATCH 01/23] 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 02/23] 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 d0edbfe3d2046b9f531a0e81b1bf571f43870bfa Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 16:12:39 +0100 Subject: [PATCH 03/23] add additional lookup --- .../connectivity/DestinationService.java | 25 +++++++++++++++++++ 1 file changed, 25 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..2d91b987c 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 @@ -120,6 +120,10 @@ static ResilienceConfiguration createResilienceConfiguration( Try tryGetDestination( @Nonnull final String destinationName, @Nonnull final DestinationOptions options ) { + if( Cache.preLookupCheckEnabled && !preLookupCheckSuccessful(destinationName) ) { + final String msg = "Destination %s was not found among the destinations of the current tenant."; + return Try.failure(new DestinationNotFoundException(String.format(msg, destinationName))); + } return Cache.getOrComputeDestination(this, destinationName, options, this::loadAndParseDestination); } @@ -384,6 +388,13 @@ private static boolean hasCauseAssignableFrom( @Nonnull final Throwable t, @Nonn return ExceptionUtils.getThrowableList(t).stream().map(Throwable::getClass).anyMatch(cls::isAssignableFrom); } + private boolean preLookupCheckSuccessful( final String destinationName ) + { + return getAllDestinationProperties() + .stream() + .anyMatch(properties -> properties.get(DestinationProperty.NAME).contains(destinationName)); + } + /** * Helper class that encapsulates all caching related configuration options. * @@ -426,6 +437,7 @@ public static final class Cache private static boolean cacheEnabled = true; private static boolean changeDetectionEnabled = true; + private static boolean preLookupCheckEnabled = true; static { recreateSingleCache(); @@ -443,6 +455,18 @@ static boolean isChangeDetectionEnabled() return changeDetectionEnabled; } + /** + * Disables checking if a destination exists before trying to call it directly when invoking + * {@link #tryGetDestination}. All available destinations can be found with + * {@link #getAllDestinationProperties}. + * + * @since 5.25.0 + */ + public static void disablePreLookupCheck() + { + preLookupCheckEnabled = false; + } + @Nonnull static com.github.benmanes.caffeine.cache.Cache instanceSingle() { @@ -496,6 +520,7 @@ static void reset() cacheEnabled = true; } changeDetectionEnabled = true; + preLookupCheckEnabled = true; sizeLimit = Option.some(DEFAULT_SIZE_LIMIT); expirationDuration = Option.some(DEFAULT_EXPIRATION_DURATION); From 6d66f5c0d6fc5b5b2dccf6e6424b8e3e5f902883 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 16:12:49 +0100 Subject: [PATCH 04/23] tests --- .../DestinationServiceAuthenticationTest.java | 6 +- ...nationServicePrincipalPropagationTest.java | 3 + .../connectivity/DestinationServiceTest.java | 67 +++++++++++++++++-- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceAuthenticationTest.java b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceAuthenticationTest.java index 914e6fce1..62a9e7127 100644 --- a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceAuthenticationTest.java +++ b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceAuthenticationTest.java @@ -66,6 +66,8 @@ void setMockAdapter() .when(mockAdapter) .getConfigurationAsJson(anyString(), any()); sut = new DestinationService(mockAdapter); + // Disable PreLookupCheck to simplify test setup + DestinationService.Cache.disablePreLookupCheck(); } @Test @@ -290,7 +292,7 @@ void testOAuth2PasswordWithoutUserToken() assertThat(dest.asHttp().getHeaders()) .containsExactlyInAnyOrder(new Header("Authorization", "Bearer " + oAuthToken)); - verify(mockAdapter, times(1)).getConfigurationAsJson(anyString(), eq(expectedStrategy)); + verify(mockAdapter, times(1)).getConfigurationAsJson(eq(SERVICE_PATH_DESTINATION), eq(expectedStrategy)); verifyNoMoreInteractions(mockAdapter); } @@ -382,7 +384,7 @@ void testSAPAssertionSSO() assertThat(dest.asHttp().getAuthenticationType()).isEqualTo(AuthenticationType.SAP_ASSERTION_SSO); assertThat(dest.asHttp().getHeaders()).containsExactlyInAnyOrder(new Header("Cookie", assertionCookie)); - verify(mockAdapter, times(1)).getConfigurationAsJson(anyString(), eq(expectedStrategy)); + verify(mockAdapter, times(1)).getConfigurationAsJson(eq(SERVICE_PATH_DESTINATION), eq(expectedStrategy)); verifyNoMoreInteractions(mockAdapter); } diff --git a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServicePrincipalPropagationTest.java b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServicePrincipalPropagationTest.java index 1437bca9f..64fa1d847 100644 --- a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServicePrincipalPropagationTest.java +++ b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServicePrincipalPropagationTest.java @@ -108,6 +108,9 @@ void setupConnectivity( @Nonnull final WireMockRuntimeInfo wm ) .withRequestBody( equalTo("grant_type=client_credentials&client_secret=CLIENT_SECRET&client_id=CLIENT_ID")) .willReturn(okJson("{\"access_token\":\"provider-client-credentials\",\"expires_in\":3600}"))); + + // Disable PreLookupCheck to simplify test setup + DestinationService.Cache.disablePreLookupCheck(); } @AfterEach 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 55a418c9a..bafee51c5 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 @@ -113,6 +113,15 @@ class DestinationServiceTest "ProxyType": "Internet", "KeyStorePassword": "password", "KeyStoreLocation": "aaa" + }, + { + "Name": "SomeDestinationName", + "Type": "HTTP", + "URL": "https://a.s4hana.ondemand.com", + "Authentication": "ClientCertificateAuthentication", + "ProxyType": "Internet", + "KeyStorePassword": "password", + "KeyStoreLocation": "aaa" }] """; @@ -336,6 +345,9 @@ class DestinationServiceTest @BeforeEach void setup() { + // Disable PreLookupCheck to simplify test setup + DestinationService.Cache.disablePreLookupCheck(); + providerTenant = new DefaultTenant("provider-tenant"); subscriberTenant = new DefaultTenant("subscriber-tenant"); context.setTenant(subscriberTenant); @@ -442,7 +454,7 @@ void testGettingDestinationProperties() assertThat(destinationList) .extracting(d -> d.get(DestinationProperty.NAME).get()) - .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT"); + .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT", destinationName); final DestinationProperties destination = destinationList @@ -478,7 +490,7 @@ void testGettingDestinationPropertiesProvider() final Collection destinationList = loader.getAllDestinationProperties(ALWAYS_PROVIDER); assertThat(destinationList) .extracting(d -> d.get(DestinationProperty.NAME).get()) - .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT"); + .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT", destinationName); } @Test @@ -494,7 +506,7 @@ void testGettingDestinationPropertiesSubscriber() final Collection destinationList = loader.getAllDestinationProperties(ONLY_SUBSCRIBER); assertThat(destinationList) .extracting(d -> d.get(DestinationProperty.NAME).get()) - .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT"); + .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT", destinationName); } @Test @@ -589,10 +601,10 @@ void testGetAllDestinationsForProvider() final List destinationList = new ArrayList<>(); destinations.get().forEach(destinationList::add); - assertThat(destinationList.size()).isEqualTo(3); + assertThat(destinationList.size()).isEqualTo(4); assertThat(destinationList) .extracting(d -> d.get(DestinationProperty.NAME).get()) - .containsOnly("CC8-HTTP-BASIC", "CC8-HTTP-CERT", "CC8-HTTP-CERT1"); + .containsOnly("CC8-HTTP-BASIC", "CC8-HTTP-CERT", "CC8-HTTP-CERT1", destinationName); } @SuppressWarnings( "deprecation" ) @@ -1918,4 +1930,49 @@ private String createHttpDestinationServiceResponse( final String name, final St } """, name, url); } + + @Test + void testPrependGetAllDestinationsCall() + { + // Reset Cache to re-enable the PreLookupCheck + DestinationService.Cache.reset(); + + doReturn(responseServiceInstanceDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); + doReturn(responseSubaccountDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); + + Destination result = loader.tryGetDestination(destinationName).get(); + + verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); + verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); + verify(destinationServiceAdapter, times(1)) + .getConfigurationAsJson(eq("/v1/destinations/" + destinationName), any()); + verifyNoMoreInteractions(destinationServiceAdapter); + } + + @Test + void testPrependGetAllDestinationsCallWithMissingDestination() + { + // Reset Cache to re-enable the PreLookupCheck + DestinationService.Cache.reset(); + + doReturn(responseServiceInstanceDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); + doReturn(responseSubaccountDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); + + assertThatThrownBy(() -> loader.tryGetDestination("thisDestinationDoesNotExist").get()) + .isInstanceOf(DestinationNotFoundException.class) + .hasMessageContaining("was not found among the destinations of the current tenant."); + + verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); + verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); + verifyNoMoreInteractions(destinationServiceAdapter); + + } } From 2f474ba243fb8cd62d12eacc88960f1ad8015da1 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 16:12:56 +0100 Subject: [PATCH 05/23] release notes --- release_notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release_notes.md b/release_notes.md index 3112514a9..256ede78c 100644 --- a/release_notes.md +++ b/release_notes.md @@ -12,7 +12,8 @@ ### ✨ New Functionality -- +- `DestinationService.tryGetDestination` now checks if the given destination exists before trying to call it directly. + This behaviour is enabled by default and can be disabled via `DestinationService.Cache.disablePreLookupCheck`. ### 📈 Improvements From 342b0490ab498fa9405b50ffcded8506d5a2e5e6 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 16:44:46 +0100 Subject: [PATCH 06/23] fix DestinationNotFoundException message --- .../sdk/cloudplatform/connectivity/DestinationService.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/DestinationService.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java index 2d91b987c..fbf5b2a1b 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 @@ -122,7 +122,7 @@ static ResilienceConfiguration createResilienceConfiguration( { if( Cache.preLookupCheckEnabled && !preLookupCheckSuccessful(destinationName) ) { final String msg = "Destination %s was not found among the destinations of the current tenant."; - return Try.failure(new DestinationNotFoundException(String.format(msg, destinationName))); + return Try.failure(new DestinationNotFoundException(destinationName, String.format(msg, destinationName))); } return Cache.getOrComputeDestination(this, destinationName, options, this::loadAndParseDestination); } From 1e852723cbdd51e0593d1c422c62b6912bfd1799 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 5 Jan 2026 16:54:45 +0100 Subject: [PATCH 07/23] propagate DestinationOptions --- .../cloudplatform/connectivity/DestinationService.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 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 fbf5b2a1b..2b0c17b44 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 @@ -120,7 +120,7 @@ static ResilienceConfiguration createResilienceConfiguration( Try tryGetDestination( @Nonnull final String destinationName, @Nonnull final DestinationOptions options ) { - if( Cache.preLookupCheckEnabled && !preLookupCheckSuccessful(destinationName) ) { + if( Cache.preLookupCheckEnabled && !preLookupCheckSuccessful(destinationName, options) ) { final String msg = "Destination %s was not found among the destinations of the current tenant."; return Try.failure(new DestinationNotFoundException(destinationName, String.format(msg, destinationName))); } @@ -388,9 +388,13 @@ private static boolean hasCauseAssignableFrom( @Nonnull final Throwable t, @Nonn return ExceptionUtils.getThrowableList(t).stream().map(Throwable::getClass).anyMatch(cls::isAssignableFrom); } - private boolean preLookupCheckSuccessful( final String destinationName ) + private boolean preLookupCheckSuccessful( final String destinationName, final DestinationOptions options ) { - return getAllDestinationProperties() + final DestinationServiceRetrievalStrategy retrievalStrategy = + DestinationServiceOptionsAugmenter + .getRetrievalStrategy(options) + .getOrElse(DestinationServiceRetrievalStrategy.CURRENT_TENANT); + return getAllDestinationProperties(retrievalStrategy) .stream() .anyMatch(properties -> properties.get(DestinationProperty.NAME).contains(destinationName)); } From 09b68975d8140833bba53b9c25c0c5ef2eb94ff5 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 6 Jan 2026 13:07:29 +0100 Subject: [PATCH 08/23] correct since tag --- .../sdk/cloudplatform/connectivity/DestinationService.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/DestinationService.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java index 2b0c17b44..264a8c38a 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 @@ -464,7 +464,7 @@ static boolean isChangeDetectionEnabled() * {@link #tryGetDestination}. All available destinations can be found with * {@link #getAllDestinationProperties}. * - * @since 5.25.0 + * @since 5.26.0 */ public static void disablePreLookupCheck() { From af8b3c2b47a93d14fa5eeb0b5a43d6e696dea247 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 6 Jan 2026 15:32:35 +0100 Subject: [PATCH 09/23] add another unit test --- .../connectivity/DestinationServiceTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) 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 bafee51c5..bd9455aaf 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 @@ -664,6 +664,8 @@ void testGetDestinationOnlySubscriberStrategyReadsSubscriberDestinations() @Test void testGetDestinationOnlySubscriberStrategyDoesNotReadProviderDestinations() { + + // JONAS: use this here as base for test. Check which calls are made using GetOrComputeAllDestinationsCommand final DestinationOptions options = DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(ONLY_SUBSCRIBER)).build(); @@ -1973,6 +1975,34 @@ void testPrependGetAllDestinationsCallWithMissingDestination() verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); verifyNoMoreInteractions(destinationServiceAdapter); + } + + @Test + void testPrependGetAllDestinationsCallUsesCorrectRetrievalStrategy() + { + // Reset Cache to re-enable the PreLookupCheck + DestinationService.Cache.reset(); + + doReturn(responseServiceInstanceDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); + doReturn(responseServiceInstanceDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); + // destination with name destinationName is provider-only + doReturn(responseSubaccountDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson( + eq("/v1/subaccountDestinations"), + argThat(s -> s.behalf() == TECHNICAL_USER_PROVIDER)); + + final DestinationOptions options = + DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(ALWAYS_PROVIDER)).build(); + + // set current tenant to be the subscriber tenant + context.setTenant(providerTenant); + Destination result = loader.tryGetDestination(destinationName, options).get(); + assertThat(result.asHttp().getUri()).isEqualTo(URI.create(providerUrl)); } } From 7982777d51f3a6191167fb83e2b5c9800f12fbe9 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 6 Jan 2026 15:38:27 +0100 Subject: [PATCH 10/23] remove comment --- .../sdk/cloudplatform/connectivity/DestinationServiceTest.java | 2 -- 1 file changed, 2 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 bd9455aaf..b653234f1 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 @@ -664,8 +664,6 @@ void testGetDestinationOnlySubscriberStrategyReadsSubscriberDestinations() @Test void testGetDestinationOnlySubscriberStrategyDoesNotReadProviderDestinations() { - - // JONAS: use this here as base for test. Check which calls are made using GetOrComputeAllDestinationsCommand final DestinationOptions options = DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(ONLY_SUBSCRIBER)).build(); From f22e9be4d37d66d5de2cbe96d67e770de5ef87e9 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 7 Jan 2026 10:37:25 +0100 Subject: [PATCH 11/23] retrigger --- .../cloudplatform/connectivity/DestinationServiceTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 b653234f1..09f95d1a7 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 @@ -1994,12 +1994,12 @@ void testPrependGetAllDestinationsCallUsesCorrectRetrievalStrategy() eq("/v1/subaccountDestinations"), argThat(s -> s.behalf() == TECHNICAL_USER_PROVIDER)); - final DestinationOptions options = - DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(ALWAYS_PROVIDER)).build(); - // set current tenant to be the subscriber tenant context.setTenant(providerTenant); + final DestinationOptions options = + DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(ALWAYS_PROVIDER)).build(); + Destination result = loader.tryGetDestination(destinationName, options).get(); assertThat(result.asHttp().getUri()).isEqualTo(URI.create(providerUrl)); } From bf810473e2c7df8cd356ff524210568ffa0780cb Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 7 Jan 2026 16:13:51 +0100 Subject: [PATCH 12/23] 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 e47b755746e3f5fc4a5813b1de4ccd836c45ba1a Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 7 Jan 2026 18:26:53 +0100 Subject: [PATCH 13/23] add skipping logic and test --- .../connectivity/DestinationService.java | 10 ++- .../connectivity/DestinationServiceTest.java | 64 ++++++++++++++++++- 2 files changed, 70 insertions(+), 4 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 41439d1df..20ea4afe8 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 @@ -121,9 +121,13 @@ static ResilienceConfiguration createResilienceConfiguration( Try tryGetDestination( @Nonnull final String destinationName, @Nonnull final DestinationOptions options ) { - if( Cache.preLookupCheckEnabled && !preLookupCheckSuccessful(destinationName, options) ) { - final String msg = "Destination %s was not found among the destinations of the current tenant."; - return Try.failure(new DestinationNotFoundException(destinationName, String.format(msg, destinationName))); + if (Cache.preLookupCheckEnabled) { + if (Cache.isUsingExperimentalFeatures(options)) { + log.warn("Using cache/change detection together with either fragments, cross-level options, or custom headers is discouraged. PreLookup check is skipped."); + } else if (!preLookupCheckSuccessful(destinationName, options)) { + final String msg = "Destination %s was not found among the destinations of the current tenant."; + return Try.failure(new DestinationNotFoundException(destinationName, String.format(msg, destinationName))); + } } return Cache.getOrComputeDestination(this, destinationName, options, this::loadAndParseDestination); } 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 09f95d1a7..89b99f708 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 @@ -49,6 +49,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; +import java.util.stream.Stream; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; @@ -62,6 +63,9 @@ import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.parallel.Isolated; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.stubbing.Answer; import com.auth0.jwt.JWT; @@ -1944,7 +1948,7 @@ void testPrependGetAllDestinationsCall() .when(destinationServiceAdapter) .getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); - Destination result = loader.tryGetDestination(destinationName).get(); + loader.tryGetDestination(destinationName).get(); verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); @@ -2003,4 +2007,62 @@ void testPrependGetAllDestinationsCallUsesCorrectRetrievalStrategy() Destination result = loader.tryGetDestination(destinationName, options).get(); assertThat(result.asHttp().getUri()).isEqualTo(URI.create(providerUrl)); } + + @ParameterizedTest + @MethodSource("provideTestData") + void testPrependGetAllDestinationsCallSkipped(DestinationOptions options, String expectedPath) { + // Reset Cache to re-enable the PreLookupCheck + DestinationService.Cache.reset(); + + // additional mock for cross level test case + final String responseWithCrossLevel = """ + { + "destinationConfiguration": { + "Name": "%s", + "Type": "HTTP", + "URL": "https://foo.com", + "Description": "%s level destination" + } + } + """; + doReturn(responseWithCrossLevel.formatted(destinationName, "subaccount")) + .when(destinationServiceAdapter) + .getConfigurationAsJson(eq(expectedPath), any()); + + // call single destination with options + loader.tryGetDestination(destinationName, options).get(); + + // verify that there was no call to all-destination endpoints + verify(destinationServiceAdapter, times(0)).getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); + verify(destinationServiceAdapter, times(0)).getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); + verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq(expectedPath), any()); + verifyNoMoreInteractions(destinationServiceAdapter); + } + + private static Stream provideTestData() { + final Header h1 = new Header("X-Custom-Header-1", "value-1"); + final DestinationOptions optionsWithHeader = + DestinationOptions.builder().augmentBuilder(augmenter().customHeaders(h1)).build(); + + final DestinationOptions optionsWithSubaccount = + DestinationOptions + .builder() + .augmentBuilder( + DestinationServiceOptionsAugmenter + .augmenter() + .crossLevelConsumption(DestinationServiceOptionsAugmenter.CrossLevelScope.SUBACCOUNT)) + .build(); + + final DestinationOptions optionsWithFragment = DestinationOptions + .builder() + .augmentBuilder(DestinationServiceOptionsAugmenter.augmenter().fragmentName("a-fragment")) + .build(); + + + return Stream.of( + Arguments.of(optionsWithHeader, "/v1/destinations/" + destinationName), + Arguments.of(optionsWithSubaccount, "/v2/destinations/" + destinationName + "@subaccount"), + Arguments.of(optionsWithFragment, "/v1/destinations/" + destinationName) + ); + } } From 87dd83d1fde7ac1d9123d9350870e57f37135c2f Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Thu, 8 Jan 2026 08:39:03 +0100 Subject: [PATCH 14/23] 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 3697192a73948aa8f7c8fc78404a396268691d4e Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Thu, 8 Jan 2026 08:41:59 +0100 Subject: [PATCH 15/23] improve warn message --- .../sdk/cloudplatform/connectivity/DestinationService.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/DestinationService.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java index 53d82860e..f4a92c5ea 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 @@ -123,7 +123,7 @@ static ResilienceConfiguration createResilienceConfiguration( { if (Cache.preLookupCheckEnabled) { if (Cache.isUsingExperimentalFeatures(options)) { - log.warn("Using cache/change detection together with either fragments, cross-level options, or custom headers is discouraged. PreLookup check is skipped."); + log.warn("Using pre-lookup check together with either fragments, cross-level options, or custom headers might lead to unexpected behaviour. Pre-lookup check is skipped."); } else if (!preLookupCheckSuccessful(destinationName, options)) { final String msg = "Destination %s was not found among the destinations of the current tenant."; return Try.failure(new DestinationNotFoundException(destinationName, String.format(msg, destinationName))); From b969c29600bc57d9aff3571f63878832770b6725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 11:47:47 +0100 Subject: [PATCH 16/23] Minor API adjustments --- .../connectivity/DestinationService.java | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 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 dad9c6568..d6d7103b0 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 @@ -1,5 +1,8 @@ package com.sap.cloud.sdk.cloudplatform.connectivity; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.getRetrievalStrategy; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceRetrievalStrategy.CURRENT_TENANT; + import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -11,6 +14,7 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -122,17 +126,41 @@ static ResilienceConfiguration createResilienceConfiguration( Try tryGetDestination( @Nonnull final String destinationName, @Nonnull final DestinationOptions options ) { - if (Cache.preLookupCheckEnabled) { - if (Cache.isUsingExperimentalFeatures(options)) { - log.warn("Using pre-lookup check together with either fragments, cross-level options, or custom headers might lead to unexpected behaviour. Pre-lookup check is skipped."); - } else if (!preLookupCheckSuccessful(destinationName, options)) { - final String msg = "Destination %s was not found among the destinations of the current tenant."; - return Try.failure(new DestinationNotFoundException(destinationName, String.format(msg, destinationName))); - } + final Option validationError = validateDestinationLookup(destinationName, options); + if( validationError.isDefined() ) { + return Try.failure(validationError.get()); } return Cache.getOrComputeDestination(this, destinationName, options, this::loadAndParseDestination); } + Option validateDestinationLookup( String destinationName, DestinationOptions options ) + { + final Option VALID_LOOKUP = Option.none(); + if( !Cache.preLookupCheckEnabled ) { + return VALID_LOOKUP; + } + if( !Cache.isEnabled() ) { + return VALID_LOOKUP; + } + if( Cache.isUsingExperimentalFeatures(options) ) { + final String msg = + "Using pre-lookup check together with either fragments, cross-level options, or custom headers might lead to unexpected behaviour. Pre-lookup check is skipped."; + log.warn(msg); + return VALID_LOOKUP; + } + + final DestinationServiceRetrievalStrategy strategy = getRetrievalStrategy(options).getOrElse(CURRENT_TENANT); + final Collection cachedDestinations = getAllDestinationProperties(strategy); + final Predicate pred = p -> p.get(DestinationProperty.NAME).contains(destinationName); + if( cachedDestinations.stream().anyMatch(pred) ) { + return VALID_LOOKUP; + } + + final String msgFormat = "Destination %s was not found among the destinations for %s."; + final String msg = String.format(msgFormat, destinationName, strategy); + return Option.some(new DestinationNotFoundException(destinationName, msg)); + } + Destination loadAndParseDestination( final String destName, final DestinationOptions options ) throws DestinationAccessException, DestinationNotFoundException @@ -201,7 +229,7 @@ public Try> tryGetAllDestinations() @Nonnull public Collection getAllDestinationProperties() { - return getAllDestinationProperties(DestinationServiceRetrievalStrategy.CURRENT_TENANT); + return getAllDestinationProperties(CURRENT_TENANT); } /** @@ -394,17 +422,6 @@ private static boolean hasCauseAssignableFrom( @Nonnull final Throwable t, @Nonn return ExceptionUtils.getThrowableList(t).stream().map(Throwable::getClass).anyMatch(cls::isAssignableFrom); } - private boolean preLookupCheckSuccessful( final String destinationName, final DestinationOptions options ) - { - final DestinationServiceRetrievalStrategy retrievalStrategy = - DestinationServiceOptionsAugmenter - .getRetrievalStrategy(options) - .getOrElse(DestinationServiceRetrievalStrategy.CURRENT_TENANT); - return getAllDestinationProperties(retrievalStrategy) - .stream() - .anyMatch(properties -> properties.get(DestinationProperty.NAME).contains(destinationName)); - } - /** * Helper class that encapsulates all caching related configuration options. * From 73f2960a52f6d667a8675869d6e404a6ab1bbcab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 11:49:11 +0100 Subject: [PATCH 17/23] Apply fix --- .../connectivity/DestinationService.java | 10 +++-- .../DestinationServiceCacheTest.java | 44 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 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 d6d7103b0..308c068f8 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 @@ -946,11 +946,15 @@ private static Try> getOrComputeAllDestinations( .execute(); } - private static boolean isUsingExperimentalFeatures( @Nonnull final DestinationOptions options ) + static boolean isUsingExperimentalFeatures( @Nonnull final DestinationOptions options ) { - final String[] featureNames = { "X-fragment-name", "crossLevelSetting", "customHeader" }; + final String[] featureNames = + { + DestinationServiceOptionsAugmenter.X_FRAGMENT_KEY, + DestinationServiceOptionsAugmenter.CROSS_LEVEL_SETTING_KEY, + DestinationServiceOptionsAugmenter.CUSTOM_HEADER_KEY }; final Set keys = options.getOptionKeys(); - return keys.stream().anyMatch(s -> Arrays.stream(featureNames).anyMatch(s::equalsIgnoreCase)); + return keys.stream().anyMatch(s -> Arrays.stream(featureNames).anyMatch(s::startsWith)); } private Cache() diff --git a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceCacheTest.java b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceCacheTest.java index e4b031ec1..92cf2d4ed 100644 --- a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceCacheTest.java +++ b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceCacheTest.java @@ -1,11 +1,20 @@ package com.sap.cloud.sdk.cloudplatform.connectivity; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.augmenter; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceRetrievalStrategy.ALWAYS_PROVIDER; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceRetrievalStrategy.CURRENT_TENANT; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceRetrievalStrategy.ONLY_SUBSCRIBER; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceTokenExchangeStrategy.EXCHANGE_ONLY; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceTokenExchangeStrategy.FORWARD_USER_TOKEN; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceTokenExchangeStrategy.LOOKUP_ONLY; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import java.time.Duration; +import java.util.Arrays; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Isolated; @@ -14,6 +23,7 @@ import com.sap.cloud.sdk.cloudplatform.resilience.CacheExpirationStrategy; import io.vavr.control.Option; +import lombok.val; @Isolated( "Test interacts with global destination cache" ) class DestinationServiceCacheTest @@ -102,4 +112,38 @@ void testSize() assertThat(cacheSingle).isNotSameAs(DestinationService.Cache.instanceSingle()); assertThat(cacheAll).isSameAs(DestinationService.Cache.instanceAll()); } + + @SuppressWarnings( "deprecation" ) + @Test + @DisplayName( "Identification of experimental DestinationOptionsAugmenter settings in options" ) + void testExperimentalSettingsIdentificationInOptions() + { + val experimentalAugmentersSet = + new DestinationServiceOptionsAugmenter[][] { + { augmenter().customHeaders(new Header("experimental-header", "value")) }, + { augmenter().crossLevelConsumption(DestinationServiceOptionsAugmenter.CrossLevelScope.SUBACCOUNT) }, + { augmenter().crossLevelConsumption(DestinationServiceOptionsAugmenter.CrossLevelScope.INSTANCE) }, + { augmenter().fragmentName("a-fragment") } }; + + val legacyAugmentersSet = + new DestinationServiceOptionsAugmenter[][] { + {}, + { augmenter().refreshToken("a-token") }, + { augmenter().retrievalStrategy(ALWAYS_PROVIDER) }, + { augmenter().tokenExchangeStrategy(FORWARD_USER_TOKEN) }, + { augmenter().tokenExchangeStrategy(EXCHANGE_ONLY), augmenter().retrievalStrategy(CURRENT_TENANT) }, + { augmenter().tokenExchangeStrategy(LOOKUP_ONLY), augmenter().retrievalStrategy(ONLY_SUBSCRIBER) } }; + + for( final DestinationServiceOptionsAugmenter[] legacyAugmenters : legacyAugmentersSet ) { + val b = DestinationOptions.builder(); + Arrays.stream(legacyAugmenters).forEach(b::augmentBuilder); + assertThat(DestinationService.Cache.isUsingExperimentalFeatures(b.build())).isFalse(); + } + + for( final DestinationServiceOptionsAugmenter[] experimentalAugmenters : experimentalAugmentersSet ) { + val b = DestinationOptions.builder(); + Arrays.stream(experimentalAugmenters).forEach(b::augmentBuilder); + assertThat(DestinationService.Cache.isUsingExperimentalFeatures(b.build())).isTrue(); + } + } } From e3b85b9540b3755bfd12a0135b5aeddd65dd1a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 11:49:17 +0100 Subject: [PATCH 18/23] Format --- .../connectivity/DestinationServiceTest.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 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 89b99f708..5e495c7fc 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 @@ -1972,7 +1972,7 @@ void testPrependGetAllDestinationsCallWithMissingDestination() assertThatThrownBy(() -> loader.tryGetDestination("thisDestinationDoesNotExist").get()) .isInstanceOf(DestinationNotFoundException.class) - .hasMessageContaining("was not found among the destinations of the current tenant."); + .hasMessageContaining("was not found among the destinations for CurrentTenant."); verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/instanceDestinations"), any()); verify(destinationServiceAdapter, times(1)).getConfigurationAsJson(eq("/v1/subaccountDestinations"), any()); @@ -2009,8 +2009,9 @@ void testPrependGetAllDestinationsCallUsesCorrectRetrievalStrategy() } @ParameterizedTest - @MethodSource("provideTestData") - void testPrependGetAllDestinationsCallSkipped(DestinationOptions options, String expectedPath) { + @MethodSource( "provideTestData" ) + void testPrependGetAllDestinationsCallSkipped( DestinationOptions options, String expectedPath ) + { // Reset Cache to re-enable the PreLookupCheck DestinationService.Cache.reset(); @@ -2039,7 +2040,8 @@ void testPrependGetAllDestinationsCallSkipped(DestinationOptions options, String verifyNoMoreInteractions(destinationServiceAdapter); } - private static Stream provideTestData() { + private static Stream provideTestData() + { final Header h1 = new Header("X-Custom-Header-1", "value-1"); final DestinationOptions optionsWithHeader = DestinationOptions.builder().augmentBuilder(augmenter().customHeaders(h1)).build(); @@ -2053,16 +2055,16 @@ private static Stream provideTestData() { .crossLevelConsumption(DestinationServiceOptionsAugmenter.CrossLevelScope.SUBACCOUNT)) .build(); - final DestinationOptions optionsWithFragment = DestinationOptions - .builder() - .augmentBuilder(DestinationServiceOptionsAugmenter.augmenter().fragmentName("a-fragment")) - .build(); - + final DestinationOptions optionsWithFragment = + DestinationOptions + .builder() + .augmentBuilder(DestinationServiceOptionsAugmenter.augmenter().fragmentName("a-fragment")) + .build(); - return Stream.of( - Arguments.of(optionsWithHeader, "/v1/destinations/" + destinationName), - Arguments.of(optionsWithSubaccount, "/v2/destinations/" + destinationName + "@subaccount"), - Arguments.of(optionsWithFragment, "/v1/destinations/" + destinationName) - ); + return Stream + .of( + Arguments.of(optionsWithHeader, "/v1/destinations/" + destinationName), + Arguments.of(optionsWithSubaccount, "/v2/destinations/" + destinationName + "@subaccount"), + Arguments.of(optionsWithFragment, "/v1/destinations/" + destinationName)); } } From a5c89d00703eb46be570de3f03f6d8c6d4b70dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 11:59:04 +0100 Subject: [PATCH 19/23] Minor format --- .../connectivity/DestinationServiceTest.java | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 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 5e495c7fc..58ca55202 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 @@ -1801,10 +1801,7 @@ void testFragmentDestinationsAreCacheIsolated() .getConfigurationAsJson(any(), argThat(it -> it.fragment() == null)); final Function optsBuilder = - frag -> DestinationOptions - .builder() - .augmentBuilder(DestinationServiceOptionsAugmenter.augmenter().fragmentName(frag)) - .build(); + frag -> DestinationOptions.builder().augmentBuilder(augmenter().fragmentName(frag)).build(); final Destination dA = loader.tryGetDestination("destination", optsBuilder.apply("a-fragment")).get(); final Destination dB = loader.tryGetDestination("destination", optsBuilder.apply("b-fragment")).get(); @@ -2004,13 +2001,13 @@ void testPrependGetAllDestinationsCallUsesCorrectRetrievalStrategy() final DestinationOptions options = DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(ALWAYS_PROVIDER)).build(); - Destination result = loader.tryGetDestination(destinationName, options).get(); + final Destination result = loader.tryGetDestination(destinationName, options).get(); assertThat(result.asHttp().getUri()).isEqualTo(URI.create(providerUrl)); } @ParameterizedTest - @MethodSource( "provideTestData" ) - void testPrependGetAllDestinationsCallSkipped( DestinationOptions options, String expectedPath ) + @MethodSource("testCasesUncachedDestinationLookup") + void testPrependGetAllDestinationsCallSkipped( final DestinationOptions options, final String expectedPath ) { // Reset Cache to re-enable the PreLookupCheck DestinationService.Cache.reset(); @@ -2040,26 +2037,22 @@ void testPrependGetAllDestinationsCallSkipped( DestinationOptions options, Strin verifyNoMoreInteractions(destinationServiceAdapter); } - private static Stream provideTestData() + private static Stream testCasesUncachedDestinationLookup() { + // custom header final Header h1 = new Header("X-Custom-Header-1", "value-1"); final DestinationOptions optionsWithHeader = DestinationOptions.builder().augmentBuilder(augmenter().customHeaders(h1)).build(); + // cross-level consumption + final DestinationServiceOptionsAugmenter.CrossLevelScope crossLevelScope = + DestinationServiceOptionsAugmenter.CrossLevelScope.SUBACCOUNT; final DestinationOptions optionsWithSubaccount = - DestinationOptions - .builder() - .augmentBuilder( - DestinationServiceOptionsAugmenter - .augmenter() - .crossLevelConsumption(DestinationServiceOptionsAugmenter.CrossLevelScope.SUBACCOUNT)) - .build(); + DestinationOptions.builder().augmentBuilder(augmenter().crossLevelConsumption(crossLevelScope)).build(); + // fragments final DestinationOptions optionsWithFragment = - DestinationOptions - .builder() - .augmentBuilder(DestinationServiceOptionsAugmenter.augmenter().fragmentName("a-fragment")) - .build(); + DestinationOptions.builder().augmentBuilder(augmenter().fragmentName("a-fragment")).build(); return Stream .of( From 11d0c668995e975ed4c1e7993ab3c72730aee12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 12:21:26 +0100 Subject: [PATCH 20/23] Minor format --- .../sdk/cloudplatform/connectivity/DestinationService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 308c068f8..78fcb76b8 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 @@ -133,13 +133,13 @@ static ResilienceConfiguration createResilienceConfiguration( return Cache.getOrComputeDestination(this, destinationName, options, this::loadAndParseDestination); } - Option validateDestinationLookup( String destinationName, DestinationOptions options ) + Option validateDestinationLookup( final String destinationName, final DestinationOptions options ) { final Option VALID_LOOKUP = Option.none(); - if( !Cache.preLookupCheckEnabled ) { + if( !Cache.isEnabled() ) { return VALID_LOOKUP; } - if( !Cache.isEnabled() ) { + if( !Cache.preLookupCheckEnabled ) { return VALID_LOOKUP; } if( Cache.isUsingExperimentalFeatures(options) ) { From b444fec73f56a7a53d5760a1060f78a550c9c62d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 12:21:40 +0100 Subject: [PATCH 21/23] Add low-level test method --- .../connectivity/DestinationServiceTest.java | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) 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 58ca55202..0d3ff6a2a 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 @@ -2,6 +2,7 @@ import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationRetrievalStrategy.withUserToken; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationRetrievalStrategy.withoutToken; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.CrossLevelScope.PROVIDER_SUBACCOUNT; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.DESTINATION_RETRIEVAL_STRATEGY_KEY; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.DESTINATION_TOKEN_EXCHANGE_STRATEGY_KEY; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.augmenter; @@ -51,6 +52,8 @@ import java.util.function.Function; import java.util.stream.Stream; +import io.vavr.control.Option; +import lombok.val; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.message.BasicHttpResponse; @@ -2006,7 +2009,7 @@ void testPrependGetAllDestinationsCallUsesCorrectRetrievalStrategy() } @ParameterizedTest - @MethodSource("testCasesUncachedDestinationLookup") + @MethodSource( "testCasesUncachedDestinationLookup" ) void testPrependGetAllDestinationsCallSkipped( final DestinationOptions options, final String expectedPath ) { // Reset Cache to re-enable the PreLookupCheck @@ -2060,4 +2063,59 @@ private static Stream testCasesUncachedDestinationLookup() Arguments.of(optionsWithSubaccount, "/v2/destinations/" + destinationName + "@subaccount"), Arguments.of(optionsWithFragment, "/v1/destinations/" + destinationName)); } + + @Test + void testValidateDestinationLookup() + { + val OPTIONS_EMPTY = DestinationOptions.builder().build(); + val OPTIONS_EXPER = + DestinationOptions.builder().augmentBuilder(augmenter().crossLevelConsumption(PROVIDER_SUBACCOUNT)).build(); + val OPTIONS_CURRT = + DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(CURRENT_TENANT)).build(); + val OPTIONS_PROVT = + DestinationOptions.builder().augmentBuilder(augmenter().retrievalStrategy(ALWAYS_PROVIDER)).build(); + + val adapter = mock(DestinationServiceAdapter.class); + val sut = spy(new DestinationService(adapter)); + + val curr = List.of(DefaultHttpDestination.builder("http://current-tenant-1").name("current-dest-1").build()); + doReturn(curr).when(sut).getAllDestinationProperties(CURRENT_TENANT); + val prov = List.of(DefaultHttpDestination.builder("http://provider-tenant-1").name("provider-dest-1").build()); + doReturn(prov).when(sut).getAllDestinationProperties(ALWAYS_PROVIDER); + + // valid case: disabled cache + DestinationService.Cache.disable(); + assertThat(sut.validateDestinationLookup("unknown-dest-1", OPTIONS_EMPTY)).isEmpty(); + + // valid case: disabled pre-lookup check + DestinationService.Cache.reset(); + DestinationService.Cache.disablePreLookupCheck(); + assertThat(sut.validateDestinationLookup("unknown-dest-1", OPTIONS_EMPTY)).isEmpty(); + + // valid case: experimental properties + DestinationService.Cache.reset(); + assertThat(sut.validateDestinationLookup("unknown-dest-1", OPTIONS_EXPER)).isEmpty(); + + // valid case: current tenant + DestinationService.Cache.reset(); + assertThat(sut.validateDestinationLookup("current-dest-1", OPTIONS_CURRT)).isEmpty(); + + // valid case: provider tenant + DestinationService.Cache.reset(); + assertThat(sut.validateDestinationLookup("provider-dest-1", OPTIONS_PROVT)).isEmpty(); + + // invalid case: current tenant + DestinationService.Cache.reset(); + assertThat(sut.validateDestinationLookup("unknown-dest-1", OPTIONS_PROVT)) + .allSatisfy( + e -> assertThat(e) + .hasMessage("Destination unknown-dest-1 was not found among the destinations for AlwaysProvider.")); + + // invalid case: provider tenant + DestinationService.Cache.reset(); + assertThat(sut.validateDestinationLookup("unknown-dest-1", OPTIONS_CURRT)) + .allSatisfy( + e -> assertThat(e) + .hasMessage("Destination unknown-dest-1 was not found among the destinations for CurrentTenant.")); + } } From 6cab0ac8e444d2e4135f8e32f844a33763af4c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 12:25:08 +0100 Subject: [PATCH 22/23] Format imports --- .../cloudplatform/connectivity/DestinationServiceTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 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 0d3ff6a2a..660149345 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 @@ -2,10 +2,10 @@ import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationRetrievalStrategy.withUserToken; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationRetrievalStrategy.withoutToken; -import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.CrossLevelScope.PROVIDER_SUBACCOUNT; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.DESTINATION_RETRIEVAL_STRATEGY_KEY; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.DESTINATION_TOKEN_EXCHANGE_STRATEGY_KEY; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.augmenter; +import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceOptionsAugmenter.CrossLevelScope.PROVIDER_SUBACCOUNT; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceRetrievalStrategy.ALWAYS_PROVIDER; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceRetrievalStrategy.CURRENT_TENANT; import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceRetrievalStrategy.ONLY_SUBSCRIBER; @@ -52,8 +52,6 @@ import java.util.function.Function; import java.util.stream.Stream; -import io.vavr.control.Option; -import lombok.val; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.message.BasicHttpResponse; @@ -91,6 +89,7 @@ import io.github.resilience4j.circuitbreaker.CallNotPermittedException; import io.vavr.control.Try; import lombok.SneakyThrows; +import lombok.val; @Isolated( "Test interacts with global destination cache" ) class DestinationServiceTest From c492b6fd791f5c14abb15c756b8a338e4c61366a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20D=C3=BCmont?= Date: Fri, 9 Jan 2026 12:31:32 +0100 Subject: [PATCH 23/23] Fix PMD --- .../cloudplatform/connectivity/DestinationService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 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 78fcb76b8..64c4f8917 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 @@ -135,25 +135,25 @@ static ResilienceConfiguration createResilienceConfiguration( Option validateDestinationLookup( final String destinationName, final DestinationOptions options ) { - final Option VALID_LOOKUP = Option.none(); + final Option validLookup = Option.none(); if( !Cache.isEnabled() ) { - return VALID_LOOKUP; + return validLookup; } if( !Cache.preLookupCheckEnabled ) { - return VALID_LOOKUP; + return validLookup; } if( Cache.isUsingExperimentalFeatures(options) ) { final String msg = "Using pre-lookup check together with either fragments, cross-level options, or custom headers might lead to unexpected behaviour. Pre-lookup check is skipped."; log.warn(msg); - return VALID_LOOKUP; + return validLookup; } final DestinationServiceRetrievalStrategy strategy = getRetrievalStrategy(options).getOrElse(CURRENT_TENANT); final Collection cachedDestinations = getAllDestinationProperties(strategy); final Predicate pred = p -> p.get(DestinationProperty.NAME).contains(destinationName); if( cachedDestinations.stream().anyMatch(pred) ) { - return VALID_LOOKUP; + return validLookup; } final String msgFormat = "Destination %s was not found among the destinations for %s.";