diff --git a/CHANGELOG.md b/CHANGELOG.md index f6c42bc754..6b4e047183 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,14 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 _**For better traceability add the corresponding GitHub issue number in each changelog entry, please.**_ ## [Unreleased] +### Changed +- IRS now supports Asset Administration Shell v3.1 - adjusted lookup shells endpoint changes (assetIds query param is encoded). #359 +- ### Added - Extended EdcPolicyDefinitionService to check if a policy in the edc exists ## [4.8.0] - 2024-03-18 ### Changed - Improved maintainability in EdcSubmodelClientImpl by reduced method visibility and better naming (in context of #448). -- EdcPolicyDefinitionService, EdcContractDefinitionService and EdcAssetService return throw AlreadyExist exceptions when Conflict is returned from - EDC +- EdcPolicyDefinitionService, EdcContractDefinitionService and EdcAssetService throw AlreadyExist exceptions when + conflict is returned from EDC - Added AssetAdministrationShellDescriptor specificAssetIds support for externalSubjectId required for data provisioning - Registering a job - aspects array is now accepting full urn of aspect model instead of name only, eg. 'urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt' instead 'SingleLevelBomAsBuilt'. #439 - Changed the version of irs-registry-client from 1.6.0-SNAPSHOT to 1.6.0 diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java index 185d74a8b4..4ff1a14453 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java @@ -20,12 +20,14 @@ package org.eclipse.tractusx.irs; import static com.github.tomakehurst.wiremock.client.WireMock.containing; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.tractusx.irs.WiremockSupport.createEndpointDataReference; +import static org.eclipse.tractusx.irs.WiremockSupport.encodedAssetIds; import static org.eclipse.tractusx.irs.WiremockSupport.randomUUID; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_URL; @@ -158,7 +160,7 @@ void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundExcep void shouldStopJobAfterDepthIsReached() { // Arrange final String globalAssetIdLevel1 = "globalAssetId"; - final String globalAssetIdLevel2 = "urn:uuid:6d505432-8b31-4966-9514-4b753372683f"; + final String globalAssetIdLevel2 = "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5"; WiremockSupport.successfulSemanticModelRequest(); WiremockSupport.successfulSemanticHubRequests(); @@ -297,7 +299,7 @@ private void successfulRegistryAndDataRequest(final String globalAssetId, final final String registryEdcAssetId = "registry-asset"; successfulNegotiation(registryEdcAssetId); stubFor(getLookupShells200(PUBLIC_LOOKUP_SHELLS_PATH, List.of(shellId)).withQueryParam("assetIds", - containing(globalAssetId))); + equalTo(encodedAssetIds(globalAssetId)))); stubFor(getShellDescriptor200(PUBLIC_SHELL_DESCRIPTORS_PATH + WiremockSupport.encodedId(shellId), bpn, submodelDescriptors, globalAssetId, shellId, idShort)); successfulNegotiation(edcAssetId); diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java index 5146e44de5..33fe3a36c4 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java @@ -43,10 +43,12 @@ import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.tractusx.irs.component.PartChainIdentificationKey; import org.eclipse.tractusx.irs.component.RegisterJob; +import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.data.StringMapper; import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; +import org.eclipse.tractusx.irs.registryclient.util.SerializationHelper; import org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockSupport; import org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport; import org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport; @@ -97,6 +99,14 @@ static String encodedId(final String shellId) { return encodeBase64String(shellId.getBytes(StandardCharsets.UTF_8)); } + static String encodedAssetIds(final String assetIds) { + final IdentifierKeyValuePair globalAssetId = IdentifierKeyValuePair.builder() + .name("globalAssetId") + .value(assetIds) + .build(); + return Base64.getEncoder().encodeToString(new SerializationHelper().serialize(globalAssetId)); + } + static void verifyDiscoveryCalls(final int times) { verify(times, postRequestedFor(urlPathEqualTo(DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_PATH))); verify(times, postRequestedFor(urlPathEqualTo(DiscoveryServiceWiremockSupport.EDC_DISCOVERY_PATH))); diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClient.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClient.java index 1c7a7ed5b3..2ee2e339f9 100644 --- a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClient.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClient.java @@ -32,7 +32,7 @@ import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; -import org.eclipse.tractusx.irs.data.StringMapper; +import org.eclipse.tractusx.irs.registryclient.util.SerializationHelper; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -53,6 +53,8 @@ public class DecentralDigitalTwinRegistryClient { private final String shellDescriptorTemplate; private final String lookupShellsTemplate; + private final SerializationHelper serializationHelper = new SerializationHelper(); + public DecentralDigitalTwinRegistryClient(final RestTemplate edcRestTemplate, @Value("${digitalTwinRegistry.shellDescriptorTemplate:}") final String shellDescriptorTemplate, @Value("${digitalTwinRegistry.lookupShellsTemplate:}") final String lookupShellsTemplate) { @@ -61,10 +63,6 @@ public DecentralDigitalTwinRegistryClient(final RestTemplate edcRestTemplate, this.lookupShellsTemplate = lookupShellsTemplate; } - private static String encodeWithBase64(final String aasIdentifier) { - return Base64.getEncoder().encodeToString(aasIdentifier.getBytes(StandardCharsets.UTF_8)); - } - @Retry(name = "registry") public AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor( final EndpointDataReference endpointDataReference, final String aasIdentifier) { @@ -78,14 +76,22 @@ public AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor( @Retry(name = "registry") public LookupShellsResponse getAllAssetAdministrationShellIdsByAssetLink( - final EndpointDataReference endpointDataReference, final List assetIds) { + final EndpointDataReference endpointDataReference, final IdentifierKeyValuePair assetIds) { final String shellLookupEndpoint = endpointDataReference.getEndpoint() + lookupShellsTemplate; final UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(shellLookupEndpoint); - uriBuilder.uriVariables(Map.of(PLACEHOLDER_ASSET_IDS, StringMapper.mapToString(assetIds))); + uriBuilder.uriVariables(Map.of(PLACEHOLDER_ASSET_IDS, encodeWithBase64(assetIds))); return edcRestTemplate.exchange(uriBuilder.build().toUri(), HttpMethod.GET, new HttpEntity<>(null, headers(endpointDataReference)), LookupShellsResponse.class).getBody(); } + private String encodeWithBase64(final String aasIdentifier) { + return Base64.getEncoder().encodeToString(aasIdentifier.getBytes(StandardCharsets.UTF_8)); + } + + private String encodeWithBase64(final IdentifierKeyValuePair assetIds) { + return Base64.getEncoder().encodeToString(serializationHelper.serialize(assetIds)); + } + private HttpHeaders headers(final EndpointDataReference dataReference) { final HttpHeaders headers = new HttpHeaders(); headers.setAccept(List.of(MediaType.APPLICATION_JSON)); diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryService.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryService.java index 5157d5293c..d7daf1c2f9 100644 --- a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryService.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryService.java @@ -250,7 +250,7 @@ private String mapToShellId(final EndpointDataReference endpointDataReference, f // Try to map the provided ID to the corresponding asset administration shell ID final var mappingResultStream = decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink( - endpointDataReference, List.of(identifierKeyValuePair)).getResult().stream(); + endpointDataReference, identifierKeyValuePair).getResult().stream(); // Special scenario: Multiple DTs with the same globalAssetId in one DTR, see: // docs/arc42/cross-cutting/discovery-DTR--multiple-DTs-with-the-same-globalAssedId-in-one-DTR.puml @@ -340,7 +340,7 @@ private Collection lookupShellIds(final String bpn, final EndpointDataRe try { return decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink( endpointDataReference, - List.of(IdentifierKeyValuePair.builder().name("manufacturerId").value(bpn).build())).getResult(); + IdentifierKeyValuePair.builder().name("manufacturerId").value(bpn).build()).getResult(); } finally { watch.stop(); log.info(TOOK_MS, watch.getLastTaskName(), watch.getLastTaskTimeMillis()); diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/util/SerializationHelper.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/util/SerializationHelper.java new file mode 100644 index 0000000000..ee05e8593b --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/util/SerializationHelper.java @@ -0,0 +1,52 @@ +/******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2021,2024 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.registryclient.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializationFeature; + +/** + * Serializer helper + */ +public class SerializationHelper { + + private static final ObjectWriter WRITER; + static { + final ObjectMapper mapper = new ObjectMapper(); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + WRITER = mapper.writer(); + } + + public byte[] serialize(final Object object) { + final ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + WRITER.writeValue(stream, object); + return stream.toByteArray(); + } catch (final IOException e) { + return new byte[0]; + } + } +} diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClientTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClientTest.java index 823fa5a175..b9599b181f 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClientTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClientTest.java @@ -13,6 +13,7 @@ import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; +import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; @@ -59,7 +60,7 @@ void shouldCallForAllAssetAdministrationShellIdsByAssetLink() { ResponseEntity.of(Optional.of(LookupShellsResponse.builder().result(Collections.emptyList()).build()))); // when - client.getAllAssetAdministrationShellIdsByAssetLink(endpointDataReference, new ArrayList<>()); + client.getAllAssetAdministrationShellIdsByAssetLink(endpointDataReference, IdentifierKeyValuePair.builder().build()); // then verify(restTemplate).exchange(any(), eq(HttpMethod.GET), any(), eq(LookupShellsResponse.class)); diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceTest.java index 74a2197551..7d2d8cd7c1 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceTest.java @@ -103,7 +103,7 @@ void shouldReturnExpectedShell() throws RegistryServiceException { endpointDataRefFutures); when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(), - anyList())).thenReturn(lookupShellsResponse); + any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse); when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn( expectedShell); @@ -132,7 +132,7 @@ void whenInterruptedExceptionOccurs() throws ExecutionException, InterruptedExce connectorEndpoints, "bpn")).thenReturn(dataRefFutures); when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(), - anyList())).thenReturn(lookupShellsResponse); + any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse); when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn( shellDescriptor(emptyList())); @@ -166,7 +166,7 @@ void whenExecutionExceptionOccurs() { connectorEndpoints, "bpn")).thenReturn(dataRefFutures); when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(), - anyList())).thenReturn(lookupShellsResponse); + any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse); when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn( shellDescriptor(emptyList())); @@ -230,7 +230,7 @@ void shouldReturnTheExpectedGlobalAssetId() throws RegistryServiceException { when(endpointDataForConnectorsService.createFindEndpointDataForConnectorsFutures(anyList(), any())).thenReturn( dataRefFutures); when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(), - anyList())).thenReturn(lookupShellsResponse); + any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse); when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn( expectedShell);