From cb8b5958cc63e5f31d48e67a4fb0e385dc226b2d Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 13 Jun 2023 17:07:27 +0200 Subject: [PATCH 1/9] feat(irs-api): Fix DiscoveryResponse --- .../DecentralDigitalTwinRegistryService.java | 13 ++++---- .../registry/domain/DiscoveryEndpoint.java | 2 +- .../domain/DiscoveryFinderClient.java | 15 ++++++---- .../registry/domain/DiscoveryResponse.java | 30 +++++++++++++++++++ ...centralDigitalTwinRegistryServiceTest.java | 25 +++++++++++----- 5 files changed, 64 insertions(+), 21 deletions(-) create mode 100644 irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java index e9732583f5..19afef839c 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java @@ -22,6 +22,7 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +import java.util.Arrays; import java.util.List; import lombok.RequiredArgsConstructor; @@ -50,9 +51,9 @@ public AssetAdministrationShellDescriptor getAAShellDescriptor(final DigitalTwin log.info("Retrieved AAS Identification for DigitalTwinRegistryKey: {}", key); final DiscoveryFinderRequest onlyBpn = new DiscoveryFinderRequest(List.of("bpn")); final List providedBpn = List.of(key.bpn()); - final List discoveryEndpoints = discoveryFinderClient.findDiscoveryEndpoints(onlyBpn); - final List connectorEndpoints = discoveryEndpoints.stream() - .map(discoveryEndpoint -> discoveryFinderClient.findConnectorEndpoints( + final DiscoveryEndpoint[] discoveryEndpoints = discoveryFinderClient.findDiscoveryEndpoints(onlyBpn).endpoints(); + final List connectorEndpoints = Arrays.stream(discoveryEndpoints) + .map(discoveryEndpoint -> discoveryFinderClient.findConnectorEndpoints( discoveryEndpoint.endpointAddress(), providedBpn) .stream() @@ -60,9 +61,9 @@ public AssetAdministrationShellDescriptor getAAShellDescriptor(final DigitalTwin .equals(key.bpn())) .map(EdcDiscoveryResult::connectorEndpoint) .toList()) - .flatMap(List::stream) - .flatMap(List::stream) - .toList(); + .flatMap(List::stream) + .flatMap(List::stream) + .toList(); // take first final EndpointDataReference endpointDataReference = endpointDataForConnectorsService.findEndpointDataForConnectors( connectorEndpoints).stream().findFirst().orElseThrow(); diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryEndpoint.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryEndpoint.java index b03460ffa9..12c46abe0a 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryEndpoint.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryEndpoint.java @@ -23,7 +23,7 @@ package org.eclipse.tractusx.irs.aaswrapper.registry.domain; /** - * A result of finding Discovery Endpoint + * A single Discovery Endpoint. */ public record DiscoveryEndpoint(String type, String description, String endpointAddress, String documentation, String resourceId) { diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClient.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClient.java index f73042119d..eb0ff504a5 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClient.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClient.java @@ -37,7 +37,8 @@ */ public interface DiscoveryFinderClient { - List findDiscoveryEndpoints(DiscoveryFinderRequest request); + DiscoveryResponse findDiscoveryEndpoints(DiscoveryFinderRequest request); + List findConnectorEndpoints(String endpointAddress, List bpns); } @@ -61,14 +62,16 @@ class DiscoveryFinderClientImpl implements DiscoveryFinderClient { @Override @Retry(name = "registry") - public List findDiscoveryEndpoints(final DiscoveryFinderRequest request) { - return restTemplate.postForObject(discoveryFinderUrl, request, List.class); + public DiscoveryResponse findDiscoveryEndpoints(final DiscoveryFinderRequest request) { + return restTemplate.postForObject(discoveryFinderUrl, request, DiscoveryResponse.class); } @Override @Retry(name = "registry") - public List findConnectorEndpoints(final String endpointAddress, - final List bpns) { - return restTemplate.postForObject(endpointAddress, bpns, List.class); + public List findConnectorEndpoints(final String endpointAddress, final List bpns) { + final EdcDiscoveryResult[] edcDiscoveryResults = restTemplate.postForObject(endpointAddress, bpns, + EdcDiscoveryResult[].class); + + return edcDiscoveryResults == null ? List.of() : List.of(edcDiscoveryResults); } } diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java new file mode 100644 index 0000000000..ae79890372 --- /dev/null +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java @@ -0,0 +1,30 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.aaswrapper.registry.domain; + +/** + * The result of searching Discovery Endpoints. + * @param endpoints the list of {@link DiscoveryEndpoint}s + */ +public record DiscoveryResponse(DiscoveryEndpoint[] endpoints) { +} diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java index 55097cd742..04448f4e0b 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java @@ -45,20 +45,29 @@ class DecentralDigitalTwinRegistryServiceTest { private final DecentralDigitalTwinRegistryClient decentralDigitalTwinRegistryClient = mock( DecentralDigitalTwinRegistryClient.class); - private final DecentralDigitalTwinRegistryService decentralDigitalTwinRegistryService = new DecentralDigitalTwinRegistryService(discoveryFinderClient, - endpointDataForConnectorsService, decentralDigitalTwinRegistryClient); + private final DecentralDigitalTwinRegistryService decentralDigitalTwinRegistryService = new DecentralDigitalTwinRegistryService( + discoveryFinderClient, endpointDataForConnectorsService, decentralDigitalTwinRegistryClient); @Test void shouldReturnExpectedShell() { // given - final DigitalTwinRegistryKey digitalTwinRegistryKey = new DigitalTwinRegistryKey("urn:uuid:4132cd2b-cbe7-4881-a6b4-39fdc31cca2b", "bpn"); + final DigitalTwinRegistryKey digitalTwinRegistryKey = new DigitalTwinRegistryKey( + "urn:uuid:4132cd2b-cbe7-4881-a6b4-39fdc31cca2b", "bpn"); final AssetAdministrationShellDescriptor expectedShell = shellDescriptor(Collections.emptyList()); - EndpointDataReference endpointDataReference = EndpointDataReference.Builder.newInstance().endpoint("url.to.host").build(); + EndpointDataReference endpointDataReference = EndpointDataReference.Builder.newInstance() + .endpoint("url.to.host") + .build(); + final DiscoveryEndpoint[] discoveryEndpoints = { new DiscoveryEndpoint("type", "desc", "address", "doc", + "resId") + }; when(discoveryFinderClient.findDiscoveryEndpoints(any(DiscoveryFinderRequest.class))).thenReturn( - Collections.singletonList(new DiscoveryEndpoint("type", "desc", "address", "doc", "resId"))); - when(endpointDataForConnectorsService.findEndpointDataForConnectors(anyList())).thenReturn(List.of(endpointDataReference)); - when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(), anyList())).thenReturn(Collections.emptyList()); - when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn(expectedShell); + new DiscoveryResponse(discoveryEndpoints)); + when(endpointDataForConnectorsService.findEndpointDataForConnectors(anyList())).thenReturn( + List.of(endpointDataReference)); + when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(), + anyList())).thenReturn(Collections.emptyList()); + when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn( + expectedShell); // when final AssetAdministrationShellDescriptor actualShell = decentralDigitalTwinRegistryService.getAAShellDescriptor( From ac67935d597b7ce71fb9853b65228ceeb85553ab Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 13 Jun 2023 17:32:29 +0200 Subject: [PATCH 2/9] feat(edc-client): Fix providerUrl for catalog request with filter --- .../eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java index 4b61b9ef69..eef70d463d 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java @@ -83,9 +83,10 @@ private CatalogRequest buildCatalogRequest(final int offset, final String provid /* package */ Catalog getCatalogWithFilter(final String providerConnectorUrl, final String key, final String value) { final var catalogUrl = config.getControlplane().getEndpoint().getData() + "/catalog/request"; + final var providerUrl = providerConnectorUrl + config.getControlplane().getProviderSuffix(); final var querySpec = QuerySpec.Builder.newInstance().filter(List.of(new Criterion(key, "=", value))); final var catalogRequest = CatalogRequest.builder() - .providerUrl(providerConnectorUrl) + .providerUrl(providerUrl) .querySpec(querySpec.build()) .build(); return edcRestTemplate.exchange(catalogUrl, HttpMethod.POST, new HttpEntity<>(catalogRequest, headers()), From 38573da8c7174629b2f178ac5f33c1191d5d4b21 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 13 Jun 2023 18:13:48 +0200 Subject: [PATCH 3/9] feat(edc-client): Add URI normalizing to prevent double slashes in path --- .../irs/edc/client/EdcControlPlaneClient.java | 10 ++-- .../irs/edc/client/EdcSubmodelClient.java | 46 +++++++++++-------- .../edc/client/EdcControlPlaneClientTest.java | 24 +++++----- 3 files changed, 45 insertions(+), 35 deletions(-) diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java index eef70d463d..55b42b6434 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java @@ -22,6 +22,8 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.edc.client; +import java.net.URI; +import java.net.URISyntaxException; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -80,10 +82,12 @@ private CatalogRequest buildCatalogRequest(final int offset, final String provid return CatalogRequest.builder().providerUrl(providerUrl).querySpec(querySpec.build()).build(); } - /* package */ Catalog getCatalogWithFilter(final String providerConnectorUrl, final String key, - final String value) { + /* package */ Catalog getCatalogWithFilter(final String providerConnectorUrl, final String key, final String value) + throws URISyntaxException { final var catalogUrl = config.getControlplane().getEndpoint().getData() + "/catalog/request"; - final var providerUrl = providerConnectorUrl + config.getControlplane().getProviderSuffix(); + final var providerUrl = new URI(providerConnectorUrl + config.getControlplane().getProviderSuffix()).normalize() + .toString(); + final var querySpec = QuerySpec.Builder.newInstance().filter(List.of(new Criterion(key, "=", value))); final var catalogRequest = CatalogRequest.builder() .providerUrl(providerUrl) diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java index 60a365e063..5575804ea7 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java @@ -24,6 +24,7 @@ import java.net.SocketTimeoutException; import java.net.URI; +import java.net.URISyntaxException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.List; @@ -38,15 +39,15 @@ import org.apache.commons.validator.routines.UrlValidator; import org.eclipse.dataspaceconnector.spi.types.domain.catalog.Catalog; import org.eclipse.dataspaceconnector.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.common.CxTestDataContainer; +import org.eclipse.tractusx.irs.common.Masker; +import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; +import org.eclipse.tractusx.irs.component.Relationship; import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; import org.eclipse.tractusx.irs.edc.client.model.CatalogItem; import org.eclipse.tractusx.irs.edc.client.model.NegotiationResponse; import org.eclipse.tractusx.irs.edc.client.model.notification.EdcNotification; import org.eclipse.tractusx.irs.edc.client.model.notification.EdcNotificationResponse; -import org.eclipse.tractusx.irs.common.CxTestDataContainer; -import org.eclipse.tractusx.irs.common.Masker; -import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; -import org.eclipse.tractusx.irs.component.Relationship; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; import org.springframework.util.StopWatch; @@ -136,6 +137,11 @@ class EdcSubmodelClientImpl implements EdcSubmodelClient { private final EdcControlPlaneClient edcControlPlaneClient; private final UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); + private static void stopWatchOnEdcTask(final StopWatch stopWatch) { + stopWatch.stop(); + log.info("EDC Task '{}' took {} ms", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis()); + } + @Override public CompletableFuture> getRelationships(final String submodelEndpointAddress, final RelationshipAspect traversalAspectType) throws EdcClientException { @@ -289,18 +295,24 @@ public CompletableFuture getEndpointReferenceForAsset(fin final StopWatch stopWatch = new StopWatch(); stopWatch.start("Get EDC Submodel task for shell descriptor, endpoint " + endpointAddress); - final Catalog catalog = edcControlPlaneClient.getCatalogWithFilter(endpointAddress, filterKey, filterValue); + final Catalog catalog; + try { + catalog = edcControlPlaneClient.getCatalogWithFilter(endpointAddress, filterKey, filterValue); + } catch (URISyntaxException e) { + throw new EdcClientException(e); + } final List items = catalog.getContractOffers() - .stream() - .map(contractOffer -> CatalogItem.builder() - .itemId(contractOffer.getId()) - .assetPropId( - contractOffer.getAsset().getId()) - .connectorId(catalog.getId()) - .policy(contractOffer.getPolicy()) - .build()) - .toList(); + .stream() + .map(contractOffer -> CatalogItem.builder() + .itemId(contractOffer.getId()) + .assetPropId( + contractOffer.getAsset() + .getId()) + .connectorId(catalog.getId()) + .policy(contractOffer.getPolicy()) + .build()) + .toList(); final NegotiationResponse response = contractNegotiationService.negotiate(endpointAddress, items.stream().findFirst().orElseThrow()); @@ -314,17 +326,11 @@ public CompletableFuture getEndpointReferenceForAsset(fin }); } - private Optional retrieveEndpointDataReference(final String contractAgreementId) { log.info("Retrieving dataReference from storage for contractAgreementId {}", Masker.mask(contractAgreementId)); return endpointDataReferenceStorage.remove(contractAgreementId); } - private static void stopWatchOnEdcTask(final StopWatch stopWatch) { - stopWatch.stop(); - log.info("EDC Task '{}' took {} ms", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis()); - } - @SuppressWarnings({ "PMD.AvoidRethrowingException", "PMD.AvoidCatchingGenericException" }) diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java index d12555de73..92c50422eb 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.net.URISyntaxException; import java.time.Clock; import java.time.Duration; import java.util.Optional; @@ -58,14 +59,13 @@ @ExtendWith(MockitoExtension.class) class EdcControlPlaneClientTest { - @Mock - private RestTemplate restTemplate; - @Spy private final AsyncPollingService pollingService = new AsyncPollingService(Clock.systemUTC(), Executors.newSingleThreadScheduledExecutor()); @Spy private final EdcConfiguration config = new EdcConfiguration(); + @Mock + private RestTemplate restTemplate; @InjectMocks private EdcControlPlaneClient testee; @@ -99,7 +99,7 @@ void shouldReturnValidCatalog() { } @Test - void shouldReturnValidCatalogUsingFilters() { + void shouldReturnValidCatalogUsingFilters() throws URISyntaxException { // arrange final var catalog = mock(Catalog.class); when(restTemplate.exchange(any(String.class), eq(HttpMethod.POST), any(HttpEntity.class), @@ -116,8 +116,8 @@ void shouldReturnValidCatalogUsingFilters() { void shouldReturnValidNegotiationId() { // arrange final var negotiationId = NegotiationId.builder().value("test").build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(NegotiationId.class))) - .thenReturn(ResponseEntity.of(Optional.of(negotiationId))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(NegotiationId.class))).thenReturn( + ResponseEntity.of(Optional.of(negotiationId))); final NegotiationRequest request = NegotiationRequest.builder().build(); // act @@ -135,8 +135,8 @@ void shouldReturnConfirmedNegotiationResult() throws Exception { .contractAgreementId("testContractId") .state("CONFIRMED") .build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), eq(NegotiationResponse.class))) - .thenReturn(ResponseEntity.of(Optional.of(negotiationResult))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), eq(NegotiationResponse.class))).thenReturn( + ResponseEntity.of(Optional.of(negotiationResult))); // act final var result = testee.getNegotiationResult(negotiationId); @@ -151,8 +151,8 @@ void shouldReturnValidTransferProcessId() { // arrange final var processId = TransferProcessId.builder().value("test").build(); final var request = TransferProcessRequest.builder().requestId("testRequest").build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(TransferProcessId.class))) - .thenReturn(ResponseEntity.of(Optional.of(processId))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(TransferProcessId.class))).thenReturn( + ResponseEntity.of(Optional.of(processId))); // act final var result = testee.startTransferProcess(request); @@ -166,8 +166,8 @@ void shouldReturnCompletedTransferProcessResult() throws Exception { // arrange final var processId = TransferProcessId.builder().value("test").build(); final var response = TransferProcessResponse.builder().responseId("testResponse").state("COMPLETED").build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), eq(TransferProcessResponse.class))) - .thenReturn(ResponseEntity.of(Optional.of(response))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), + eq(TransferProcessResponse.class))).thenReturn(ResponseEntity.of(Optional.of(response))); // act final var result = testee.getTransferProcess(processId); From 866ade76859cf3708e30f041eb56fb063bde656f Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 14 Jun 2023 09:43:48 +0200 Subject: [PATCH 4/9] feat(edc-client): Move appending of provider suffix to EdcSubmodelClient --- .../client/ContractNegotiationService.java | 7 ++--- .../irs/edc/client/EdcControlPlaneClient.java | 12 ++------ .../irs/edc/client/EdcSubmodelClient.java | 29 ++++++++++++------- .../edc/client/EdcControlPlaneClientTest.java | 24 +++++++-------- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/ContractNegotiationService.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/ContractNegotiationService.java index cff7ac8f71..ae91c07a01 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/ContractNegotiationService.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/ContractNegotiationService.java @@ -52,8 +52,6 @@ public class ContractNegotiationService { private final EdcControlPlaneClient edcControlPlaneClient; - private final EdcConfiguration config; - private final PolicyCheckerService policyCheckerService; public NegotiationResponse negotiate(final String providerConnectorUrl, final CatalogItem catalogItem) @@ -72,8 +70,7 @@ public NegotiationResponse negotiate(final String providerConnectorUrl, final Ca final NegotiationRequest negotiationRequest = NegotiationRequest.builder() .connectorId(catalogItem.getConnectorId()) - .connectorAddress(providerConnectorUrl - + config.getControlplane().getProviderSuffix()) + .connectorAddress(providerConnectorUrl) .offer(contractOfferRequest) .build(); @@ -94,7 +91,7 @@ public NegotiationResponse negotiate(final String providerConnectorUrl, final Ca .managedResources(TransferProcessRequest.DEFAULT_MANAGED_RESOURCES) .connectorId(catalogItem.getConnectorId()) .connectorAddress( - providerConnectorUrl + config.getControlplane().getProviderSuffix()) + providerConnectorUrl) .contractId(response.getContractAgreementId()) .assetId(catalogItem.getAssetPropId()) .dataDestination(destination) diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java index 55b42b6434..775e84b8db 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClient.java @@ -22,8 +22,6 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.edc.client; -import java.net.URI; -import java.net.URISyntaxException; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -66,10 +64,9 @@ public class EdcControlPlaneClient { /* package */ Catalog getCatalog(final String providerConnectorUrl, final int offset) { final var catalogUrl = config.getControlplane().getEndpoint().getData() + "/catalog/request"; - final var providerUrl = providerConnectorUrl + config.getControlplane().getProviderSuffix(); final var limit = config.getControlplane().getCatalogPageSize(); - final CatalogRequest request = buildCatalogRequest(offset, providerUrl, limit); + final CatalogRequest request = buildCatalogRequest(offset, providerConnectorUrl, limit); return edcRestTemplate.exchange(catalogUrl, HttpMethod.POST, new HttpEntity<>(request, headers()), Catalog.class).getBody(); } @@ -82,15 +79,12 @@ private CatalogRequest buildCatalogRequest(final int offset, final String provid return CatalogRequest.builder().providerUrl(providerUrl).querySpec(querySpec.build()).build(); } - /* package */ Catalog getCatalogWithFilter(final String providerConnectorUrl, final String key, final String value) - throws URISyntaxException { + /* package */ Catalog getCatalogWithFilter(final String providerConnectorUrl, final String key, final String value) { final var catalogUrl = config.getControlplane().getEndpoint().getData() + "/catalog/request"; - final var providerUrl = new URI(providerConnectorUrl + config.getControlplane().getProviderSuffix()).normalize() - .toString(); final var querySpec = QuerySpec.Builder.newInstance().filter(List.of(new Criterion(key, "=", value))); final var catalogRequest = CatalogRequest.builder() - .providerUrl(providerUrl) + .providerUrl(providerConnectorUrl) .querySpec(querySpec.build()) .build(); return edcRestTemplate.exchange(catalogUrl, HttpMethod.POST, new HttpEntity<>(catalogRequest, headers()), diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java index 5575804ea7..bd0b7c6047 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClient.java @@ -24,7 +24,6 @@ import java.net.SocketTimeoutException; import java.net.URI; -import java.net.URISyntaxException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.List; @@ -169,10 +168,12 @@ private NegotiationResponse fetchNegotiationResponse(final String submodelEndpoi final String providerConnectorUrl = submodelEndpointAddress.substring(0, indexOfUrn); final String target = submodelEndpointAddress.substring(indexOfUrn + 1, indexOfSubModel); final String decodedTarget = URLDecoder.decode(target, StandardCharsets.UTF_8); - log.info("Starting contract negotiation with providerConnectorUrl {} and target {}", providerConnectorUrl, + final String providerWithSuffix = appendSuffix(providerConnectorUrl, + config.getControlplane().getProviderSuffix()); + log.info("Starting contract negotiation with providerConnectorUrl {} and target {}", providerWithSuffix, decodedTarget); - final CatalogItem catalogItem = catalogCache.getCatalogItem(providerConnectorUrl, decodedTarget).orElseThrow(); - return contractNegotiationService.negotiate(providerConnectorUrl, catalogItem); + final CatalogItem catalogItem = catalogCache.getCatalogItem(providerWithSuffix, decodedTarget).orElseThrow(); + return contractNegotiationService.negotiate(providerWithSuffix, catalogItem); } private CompletableFuture> startSubmodelDataRetrieval( @@ -294,13 +295,9 @@ public CompletableFuture getEndpointReferenceForAsset(fin return execute(endpointAddress, () -> { final StopWatch stopWatch = new StopWatch(); stopWatch.start("Get EDC Submodel task for shell descriptor, endpoint " + endpointAddress); + final String providerWithSuffix = appendSuffix(endpointAddress, config.getControlplane().getProviderSuffix()); - final Catalog catalog; - try { - catalog = edcControlPlaneClient.getCatalogWithFilter(endpointAddress, filterKey, filterValue); - } catch (URISyntaxException e) { - throw new EdcClientException(e); - } + final Catalog catalog = edcControlPlaneClient.getCatalogWithFilter(providerWithSuffix, filterKey, filterValue); final List items = catalog.getContractOffers() .stream() @@ -313,7 +310,7 @@ public CompletableFuture getEndpointReferenceForAsset(fin .policy(contractOffer.getPolicy()) .build()) .toList(); - final NegotiationResponse response = contractNegotiationService.negotiate(endpointAddress, + final NegotiationResponse response = contractNegotiationService.negotiate(providerWithSuffix, items.stream().findFirst().orElseThrow()); return pollingService.createJob() @@ -326,6 +323,16 @@ public CompletableFuture getEndpointReferenceForAsset(fin }); } + private String appendSuffix(final String endpointAddress, final String providerSuffix) { + String addressWithSuffix; + if (endpointAddress.endsWith("/") && providerSuffix.startsWith("/")) { + addressWithSuffix = endpointAddress.substring(0, endpointAddress.length() - 1) + providerSuffix; + } else { + addressWithSuffix = endpointAddress + providerSuffix; + } + return addressWithSuffix; + } + private Optional retrieveEndpointDataReference(final String contractAgreementId) { log.info("Retrieving dataReference from storage for contractAgreementId {}", Masker.mask(contractAgreementId)); return endpointDataReferenceStorage.remove(contractAgreementId); diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java index 92c50422eb..d12555de73 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcControlPlaneClientTest.java @@ -29,7 +29,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.net.URISyntaxException; import java.time.Clock; import java.time.Duration; import java.util.Optional; @@ -59,13 +58,14 @@ @ExtendWith(MockitoExtension.class) class EdcControlPlaneClientTest { + @Mock + private RestTemplate restTemplate; + @Spy private final AsyncPollingService pollingService = new AsyncPollingService(Clock.systemUTC(), Executors.newSingleThreadScheduledExecutor()); @Spy private final EdcConfiguration config = new EdcConfiguration(); - @Mock - private RestTemplate restTemplate; @InjectMocks private EdcControlPlaneClient testee; @@ -99,7 +99,7 @@ void shouldReturnValidCatalog() { } @Test - void shouldReturnValidCatalogUsingFilters() throws URISyntaxException { + void shouldReturnValidCatalogUsingFilters() { // arrange final var catalog = mock(Catalog.class); when(restTemplate.exchange(any(String.class), eq(HttpMethod.POST), any(HttpEntity.class), @@ -116,8 +116,8 @@ void shouldReturnValidCatalogUsingFilters() throws URISyntaxException { void shouldReturnValidNegotiationId() { // arrange final var negotiationId = NegotiationId.builder().value("test").build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(NegotiationId.class))).thenReturn( - ResponseEntity.of(Optional.of(negotiationId))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(NegotiationId.class))) + .thenReturn(ResponseEntity.of(Optional.of(negotiationId))); final NegotiationRequest request = NegotiationRequest.builder().build(); // act @@ -135,8 +135,8 @@ void shouldReturnConfirmedNegotiationResult() throws Exception { .contractAgreementId("testContractId") .state("CONFIRMED") .build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), eq(NegotiationResponse.class))).thenReturn( - ResponseEntity.of(Optional.of(negotiationResult))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), eq(NegotiationResponse.class))) + .thenReturn(ResponseEntity.of(Optional.of(negotiationResult))); // act final var result = testee.getNegotiationResult(negotiationId); @@ -151,8 +151,8 @@ void shouldReturnValidTransferProcessId() { // arrange final var processId = TransferProcessId.builder().value("test").build(); final var request = TransferProcessRequest.builder().requestId("testRequest").build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(TransferProcessId.class))).thenReturn( - ResponseEntity.of(Optional.of(processId))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(), eq(TransferProcessId.class))) + .thenReturn(ResponseEntity.of(Optional.of(processId))); // act final var result = testee.startTransferProcess(request); @@ -166,8 +166,8 @@ void shouldReturnCompletedTransferProcessResult() throws Exception { // arrange final var processId = TransferProcessId.builder().value("test").build(); final var response = TransferProcessResponse.builder().responseId("testResponse").state("COMPLETED").build(); - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), - eq(TransferProcessResponse.class))).thenReturn(ResponseEntity.of(Optional.of(response))); + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(), eq(TransferProcessResponse.class))) + .thenReturn(ResponseEntity.of(Optional.of(response))); // act final var result = testee.getTransferProcess(processId); From 00c9806d612cbf30c1a0e4da1820e93d55bc3221 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 14 Jun 2023 10:22:42 +0200 Subject: [PATCH 5/9] feat(edc-client): Remove unused parameter config --- .../tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java | 2 +- .../eclipse/tractusx/irs/edc/client/SubmodelRetryerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java index df9eeba038..0092455b4a 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java @@ -106,7 +106,7 @@ void configureSystemUnderTest() { final PolicyCheckerService policyCheckerService = mock(PolicyCheckerService.class); when(policyCheckerService.isValid(any())).thenReturn(Boolean.TRUE); final ContractNegotiationService contractNegotiationService = new ContractNegotiationService(controlPlaneClient, - config, policyCheckerService); + policyCheckerService); final OutboundMeterRegistryService meterRegistry = mock(OutboundMeterRegistryService.class); final RetryRegistry retryRegistry = RetryRegistry.ofDefaults(); diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelRetryerTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelRetryerTest.java index c64043e877..79206adb43 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelRetryerTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelRetryerTest.java @@ -76,7 +76,7 @@ void setUp() { final CatalogCache catalogCache = new InMemoryCatalogCache(edcCatalogFacade, cacheConfiguration); final ContractNegotiationService negotiationService = new ContractNegotiationService(controlPlaneClient, - config, policyCheckerService); + policyCheckerService); final EdcDataPlaneClient dataPlaneClient = new EdcDataPlaneClient(restTemplate); final EndpointDataReferenceStorage storage = new EndpointDataReferenceStorage(Duration.ofMinutes(1)); From a21a5c3972c2c08317a2483c38daa946b5a2fded Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 14 Jun 2023 10:24:00 +0200 Subject: [PATCH 6/9] feat(edc-client): Add providerSuffix config --- .../irs/edc/client/EdcSubmodelClientTest.java | 56 +++++++++---------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClientTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClientTest.java index 2e307737c9..b73114172f 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClientTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelClientTest.java @@ -56,6 +56,12 @@ import org.eclipse.dataspaceconnector.spi.types.domain.catalog.Catalog; import org.eclipse.dataspaceconnector.spi.types.domain.contract.offer.ContractOffer; import org.eclipse.dataspaceconnector.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; +import org.eclipse.tractusx.irs.component.GlobalAssetIdentification; +import org.eclipse.tractusx.irs.component.LinkedItem; +import org.eclipse.tractusx.irs.component.Relationship; +import org.eclipse.tractusx.irs.component.enums.BomLifecycle; +import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.edc.client.exceptions.ContractNegotiationException; import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; import org.eclipse.tractusx.irs.edc.client.exceptions.TimeoutException; @@ -64,12 +70,6 @@ import org.eclipse.tractusx.irs.edc.client.model.NegotiationResponse; import org.eclipse.tractusx.irs.edc.client.model.notification.EdcNotification; import org.eclipse.tractusx.irs.edc.client.model.notification.EdcNotificationResponse; -import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; -import org.eclipse.tractusx.irs.component.GlobalAssetIdentification; -import org.eclipse.tractusx.irs.component.LinkedItem; -import org.eclipse.tractusx.irs.component.Relationship; -import org.eclipse.tractusx.irs.component.enums.BomLifecycle; -import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.testing.containers.LocalTestDataConfigurationAware; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; @@ -83,51 +83,50 @@ class EdcSubmodelClientTest extends LocalTestDataConfigurationAware { private static final String ENDPOINT_ADDRESS = "http://localhost/urn:123456/submodel"; - + private static final String PROVIDER_SUFFIX = "/test"; + private final EndpointDataReferenceStorage endpointDataReferenceStorage = new EndpointDataReferenceStorage( + Duration.ofMinutes(1)); + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); + private final TimeMachine clock = new TimeMachine(); + private final AsyncPollingService pollingService = new AsyncPollingService(clock, scheduler); + @Spy + private final EdcConfiguration config = new EdcConfiguration(); + private final RetryRegistry retryRegistry = RetryRegistry.ofDefaults(); @Mock private ContractNegotiationService contractNegotiationService; @Mock private EdcDataPlaneClient edcDataPlaneClient; @Mock private EdcControlPlaneClient edcControlPlaneClient; - @Mock private CatalogCache catalogCache; - - private final EndpointDataReferenceStorage endpointDataReferenceStorage = new EndpointDataReferenceStorage( - Duration.ofMinutes(1)); - private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - - private final TimeMachine clock = new TimeMachine(); - - private final AsyncPollingService pollingService = new AsyncPollingService(clock, scheduler); - - @Spy - private final EdcConfiguration config = new EdcConfiguration(); - private EdcSubmodelClient testee; - @Mock private OutboundMeterRegistryService meterRegistry; - private final RetryRegistry retryRegistry = RetryRegistry.ofDefaults(); EdcSubmodelClientTest() throws IOException { super(); } + private static Asset createAsset(final String assetId) { + return Asset.Builder.newInstance().id(assetId).property("asset:prop:id", assetId).build(); + } + @BeforeEach void setUp() { config.setControlplane(new EdcConfiguration.ControlplaneConfig()); config.getControlplane().setEndpoint(new EdcConfiguration.ControlplaneConfig.EndpointConfig()); config.getControlplane().getEndpoint().setData("https://irs-consumer-controlplane.dev.demo.catena-x.net/data"); config.getControlplane().setRequestTtl(Duration.ofMinutes(10)); + config.getControlplane().setProviderSuffix(PROVIDER_SUFFIX); config.setSubmodel(new EdcConfiguration.SubmodelConfig()); config.getSubmodel().setPath("/submodel"); config.getSubmodel().setUrnPrefix("/urn"); config.getSubmodel().setRequestTtl(Duration.ofMinutes(10)); testee = new EdcSubmodelClientImpl(config, contractNegotiationService, edcDataPlaneClient, - endpointDataReferenceStorage, pollingService, meterRegistry, retryRegistry, catalogCache, edcControlPlaneClient); + endpointDataReferenceStorage, pollingService, meterRegistry, retryRegistry, catalogCache, + edcControlPlaneClient); } @Test @@ -327,7 +326,7 @@ void shouldRetrieveEndpointReferenceForAsset() throws Exception { // arrange final String filterKey = "filter-key"; final String filterValue = "filter-value"; - when(edcControlPlaneClient.getCatalogWithFilter(ENDPOINT_ADDRESS, filterKey, filterValue)).thenReturn( + when(edcControlPlaneClient.getCatalogWithFilter(ENDPOINT_ADDRESS + PROVIDER_SUFFIX, filterKey, filterValue)).thenReturn( createCatalog("asset-id", 3)); when(contractNegotiationService.negotiate(any(), any())).thenReturn( NegotiationResponse.builder().contractAgreementId("agreementId").build()); @@ -335,8 +334,7 @@ void shouldRetrieveEndpointReferenceForAsset() throws Exception { endpointDataReferenceStorage.put("agreementId", expected); // act - final var result = testee.getEndpointReferenceForAsset(ENDPOINT_ADDRESS, - filterKey, filterValue); + final var result = testee.getEndpointReferenceForAsset(ENDPOINT_ADDRESS, filterKey, filterValue); final EndpointDataReference actual = result.get(5, TimeUnit.SECONDS); // assert @@ -364,17 +362,13 @@ private Catalog createCatalog(final String assetId, final int numberOfOffers) { final List contractOffers = IntStream.range(0, numberOfOffers) .boxed() .map(i -> ContractOffer.Builder.newInstance() - .id("offer"+i) + .id("offer" + i) .asset(createAsset(assetId)) .policy(policy) .build()) .toList(); return Catalog.Builder.newInstance().id("default").contractOffers(contractOffers).build(); } - - private static Asset createAsset(final String assetId) { - return Asset.Builder.newInstance().id(assetId).property("asset:prop:id", assetId).build(); - } } class TimeMachine extends Clock { From 56aa3adcbc5d2d239ce766bad04919a9696f93b3 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 14 Jun 2023 10:25:47 +0200 Subject: [PATCH 7/9] feat(edc-client): Switch from primitive array to List --- .../DecentralDigitalTwinRegistryService.java | 14 +++++++------- .../registry/domain/DiscoveryResponse.java | 4 +++- .../DecentralDigitalTwinRegistryServiceTest.java | 5 ++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java index 19afef839c..0688fe7b84 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java @@ -22,7 +22,6 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.aaswrapper.registry.domain; -import java.util.Arrays; import java.util.List; import lombok.RequiredArgsConstructor; @@ -51,9 +50,10 @@ public AssetAdministrationShellDescriptor getAAShellDescriptor(final DigitalTwin log.info("Retrieved AAS Identification for DigitalTwinRegistryKey: {}", key); final DiscoveryFinderRequest onlyBpn = new DiscoveryFinderRequest(List.of("bpn")); final List providedBpn = List.of(key.bpn()); - final DiscoveryEndpoint[] discoveryEndpoints = discoveryFinderClient.findDiscoveryEndpoints(onlyBpn).endpoints(); - final List connectorEndpoints = Arrays.stream(discoveryEndpoints) - .map(discoveryEndpoint -> discoveryFinderClient.findConnectorEndpoints( + final List discoveryEndpoints = discoveryFinderClient.findDiscoveryEndpoints(onlyBpn) + .endpoints(); + final List connectorEndpoints = discoveryEndpoints.stream() + .map(discoveryEndpoint -> discoveryFinderClient.findConnectorEndpoints( discoveryEndpoint.endpointAddress(), providedBpn) .stream() @@ -61,9 +61,9 @@ public AssetAdministrationShellDescriptor getAAShellDescriptor(final DigitalTwin .equals(key.bpn())) .map(EdcDiscoveryResult::connectorEndpoint) .toList()) - .flatMap(List::stream) - .flatMap(List::stream) - .toList(); + .flatMap(List::stream) + .flatMap(List::stream) + .toList(); // take first final EndpointDataReference endpointDataReference = endpointDataForConnectorsService.findEndpointDataForConnectors( connectorEndpoints).stream().findFirst().orElseThrow(); diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java index ae79890372..3589634616 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java @@ -22,9 +22,11 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +import java.util.List; + /** * The result of searching Discovery Endpoints. * @param endpoints the list of {@link DiscoveryEndpoint}s */ -public record DiscoveryResponse(DiscoveryEndpoint[] endpoints) { +public record DiscoveryResponse(List endpoints) { } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java index 04448f4e0b..c275b884dd 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java @@ -57,9 +57,8 @@ void shouldReturnExpectedShell() { EndpointDataReference endpointDataReference = EndpointDataReference.Builder.newInstance() .endpoint("url.to.host") .build(); - final DiscoveryEndpoint[] discoveryEndpoints = { new DiscoveryEndpoint("type", "desc", "address", "doc", - "resId") - }; + final List discoveryEndpoints = List.of( + new DiscoveryEndpoint("type", "desc", "address", "doc", "resId")); when(discoveryFinderClient.findDiscoveryEndpoints(any(DiscoveryFinderRequest.class))).thenReturn( new DiscoveryResponse(discoveryEndpoints)); when(endpointDataForConnectorsService.findEndpointDataForConnectors(anyList())).thenReturn( From 2c0ccf37c212f4dbea7321e54f9ca896d20e338b Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 14 Jun 2023 11:07:00 +0200 Subject: [PATCH 8/9] feat(edc-client): Add test for DiscoveryFinderClientImpl --- .../domain/DiscoveryFinderClientImplTest.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClientImplTest.java diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClientImplTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClientImplTest.java new file mode 100644 index 0000000000..7702d2a137 --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClientImplTest.java @@ -0,0 +1,80 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.aaswrapper.registry.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.web.client.RestTemplate; + +@ExtendWith(MockitoExtension.class) +class DiscoveryFinderClientImplTest { + @Mock + private RestTemplate restTemplate; + + @Test + void shouldReturnEmptyListWhenDiscoveryReturnsNull() { + // Arrange + final String discoveryFinderUrl = "https://discovery.mock/api/administration/connectors/discovery/search"; + final String providerUrl = "https://discovery.mock/api/administration/connectors/discovery"; + final List bpns = List.of("BPN123"); + final DiscoveryFinderClientImpl discoveryFinderClient = new DiscoveryFinderClientImpl(discoveryFinderUrl, + restTemplate); + when(restTemplate.postForObject(providerUrl, bpns, EdcDiscoveryResult[].class)).thenReturn(null); + + // Act + final List connectorEndpoints = discoveryFinderClient.findConnectorEndpoints(providerUrl, + bpns); + + // Assert + assertThat(connectorEndpoints).isNotNull().isEmpty(); + } + + @Test + void shouldReturnEmptyListWhenDiscoveryReturnsEmpty() { + // Arrange + final String discoveryFinderUrl = "https://discovery.mock/api/administration/connectors/discovery/search"; + final String providerUrl = "https://discovery.mock/api/administration/connectors/discovery"; + final List bpns = List.of("BPN123"); + final DiscoveryFinderClientImpl discoveryFinderClient = new DiscoveryFinderClientImpl(discoveryFinderUrl, + restTemplate); + final EdcDiscoveryResult[] discoveryResponse = { new EdcDiscoveryResult("BPN123", + List.of("https://provider.edc")) + }; + + when(restTemplate.postForObject(providerUrl, bpns, EdcDiscoveryResult[].class)).thenReturn(discoveryResponse); + + // Act + final List connectorEndpoints = discoveryFinderClient.findConnectorEndpoints(providerUrl, + bpns); + + // Assert + assertThat(connectorEndpoints).isNotNull().hasSize(1); + } +} \ No newline at end of file From 51466bc88b08ea3e5dac1b47fe8cd5935c06a75d Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 14 Jun 2023 13:48:11 +0200 Subject: [PATCH 9/9] feat(irs-api): Update Javadoc --- .../irs/aaswrapper/registry/domain/DiscoveryResponse.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java index 3589634616..03423dec69 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java @@ -25,8 +25,7 @@ import java.util.List; /** - * The result of searching Discovery Endpoints. - * @param endpoints the list of {@link DiscoveryEndpoint}s + * The result of searching the Discovery Finder. Contains a list of {@link DiscoveryEndpoint}s. */ public record DiscoveryResponse(List endpoints) { }