diff --git a/.config/owasp-suppressions.xml b/.config/owasp-suppressions.xml index 1aa50a77dc..4f117ce003 100644 --- a/.config/owasp-suppressions.xml +++ b/.config/owasp-suppressions.xml @@ -28,4 +28,18 @@ com\.fasterxml\.jackson\.core:jackson\-databind.* CVE-2023-35116 + + + org\.eclipse\.edc:jetty\-core.* + .* + + + + org\.eclipse\.jetty\.toolchain:jetty\-jakarta\-websocket\-api.* + .* + \ No newline at end of file diff --git a/.config/pmd-rules.xml b/.config/pmd-rules.xml index 7667fc73ee..44227e54cd 100644 --- a/.config/pmd-rules.xml +++ b/.config/pmd-rules.xml @@ -33,6 +33,8 @@ + + @@ -67,4 +69,6 @@ + + diff --git a/.config/spotbugs-excludes.xml b/.config/spotbugs-excludes.xml index fe545bc25e..529d21bd5f 100644 --- a/.config/spotbugs-excludes.xml +++ b/.config/spotbugs-excludes.xml @@ -60,6 +60,14 @@ + + + + + + + + diff --git a/.github/actions/import-gpg-key/action.yaml b/.github/actions/import-gpg-key/action.yaml new file mode 100644 index 0000000000..7302673bf9 --- /dev/null +++ b/.github/actions/import-gpg-key/action.yaml @@ -0,0 +1,46 @@ +# +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 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 +# + +--- +name: "Import GPG Key" +description: "Imports a GPG key given in the input" +inputs: + gpg-private-key: + required: true + description: "The GPG Private Key in plain text. Can be a sub-key." +runs: + using: "composite" + steps: + # this is necessary because it creates gpg.conf, etc. + - name: List Keys + shell: bash + run: | + gpg -K --keyid-format=long + + - name: Import GPG Private Key + shell: bash + run: | + echo "use-agent" >> ~/.gnupg/gpg.conf + echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf + echo -e "${{ inputs.gpg-private-key }}" | gpg --import --batch + for fpr in $(gpg --list-keys --with-colons | awk -F: '/fpr:/ {print $10}' | sort -u); + do + echo -e "5\\ny\\n" | gpg --batch --command-fd 0 --expert --edit-key $fpr trust; + done \ No newline at end of file diff --git a/.github/workflows/helm-test-backwards-compatability.yaml b/.github/workflows/helm-test-backwards-compatability.yaml new file mode 100644 index 0000000000..053ffebef4 --- /dev/null +++ b/.github/workflows/helm-test-backwards-compatability.yaml @@ -0,0 +1,36 @@ +name: Test k8s version compatability + +on: + workflow_dispatch: + inputs: + node_image_latest: + description: 'First version of kindest/node image for k8s kind cluster' + default: 'kindest/node:v1.27.3' + required: false + type: string + node_image_second_latest: + description: 'Second version of kindest/node image for k8s kind cluster' + default: 'kindest/node:v1.26.6' + required: false + type: string + node_image_third_latest: + description: 'Third version of kindest/node image for k8s kind cluster' + default: 'kindest/node:v1.25.11' + required: false + type: string + +jobs: + test-latest: + uses: ./.github/workflows/helm-test.yaml + with: + node_image: ${{ github.event.inputs.node_image_latest || 'kindest/node:v1.27.3' }} + + test-second-latest: + uses: ./.github/workflows/helm-test.yaml + with: + node_image: ${{ github.event.inputs.node_image_second_latest || 'kindest/node:v1.26.6' }} + + test-third-latest: + uses: ./.github/workflows/helm-test.yaml + with: + node_image: ${{ github.event.inputs.node_image_third_latest || 'kindest/node:v1.25.11' }} \ No newline at end of file diff --git a/.github/workflows/helm-test.yaml b/.github/workflows/helm-test.yaml index 4eb2ff6d94..59986ce60c 100644 --- a/.github/workflows/helm-test.yaml +++ b/.github/workflows/helm-test.yaml @@ -5,6 +5,19 @@ on: paths: - 'charts/**' workflow_dispatch: + inputs: + node_image: + description: 'kindest/node image for k8s kind cluster' + default: 'kindest/node:v1.27.3' + required: false + type: string + workflow_call: # Trigger by another workflow + inputs: + node_image: + description: 'kindest/node image for k8s kind cluster' + default: 'kindest/node:v1.27.3' + required: false + type: string jobs: lint-test: @@ -17,6 +30,9 @@ jobs: - name: Kubernetes KinD Cluster uses: container-tools/kind-action@v2 + with: + node_image: ${{ github.event.inputs.node_image || 'kindest/node:v1.27.3' }} + version: v0.20.0 - name: Build image uses: docker/build-push-action@v4 diff --git a/.github/workflows/maven-deploy.yaml b/.github/workflows/maven-deploy.yaml new file mode 100644 index 0000000000..ec189352db --- /dev/null +++ b/.github/workflows/maven-deploy.yaml @@ -0,0 +1,89 @@ +name: Upload to Central Maven Registry + +on: + workflow_dispatch: + push: + branches: + - main + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + secret-presence: + runs-on: ubuntu-latest + outputs: + DOCKER_HUB_TOKEN: ${{ steps.secret-presence.outputs.DOCKER_HUB_TOKEN }} + HAS_OSSRH: ${{ steps.secret-presence.outputs.HAS_OSSRH }} + steps: + - name: Check whether secrets exist + id: secret-presence + run: | + [ ! -z "${{ secrets.DOCKER_HUB_TOKEN }}" ] && echo "DOCKER_HUB_TOKEN=true" >> $GITHUB_OUTPUT + [ ! -z "${{ secrets.ORG_GPG_PASSPHRASE }}" ] && + [ ! -z "${{ secrets.ORG_GPG_PRIVATE_KEY }}" ] && + [ ! -z "${{ secrets.ORG_OSSRH_USERNAME }}" ] && + [ ! -z "${{ secrets.ORG_OSSRH_PASSWORD }}" ] && + echo "HAS_OSSRH=true" >> $GITHUB_OUTPUT + exit 0 + + publish-to-sonatype: + name: "Publish artifacts to OSSRH Snapshots / MavenCentral" + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + needs: [ secret-presence ] + + # do not run on PR branches, do not run on releases + if: | + needs.secret-presence.outputs.HAS_OSSRH && github.event_name != 'pull_request' && github.ref != 'refs/heads/releases' + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Cache maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build with Maven + run: mvn package -pl irs-testing,irs-models,irs-common,irs-edc-client,irs-registry-client --batch-mode + + # Import GPG Key + - uses: ./.github/actions/import-gpg-key + name: "Import GPG Key" + with: + gpg-private-key: ${{ secrets.ORG_GPG_PRIVATE_KEY }} + + - name: Configure Maven settings + run: | + mkdir -p $HOME/.m2 + echo " + + + ossrh + ${{ secrets.ORG_OSSRH_USERNAME }} + ${{ secrets.ORG_OSSRH_PASSWORD }} + + + " > $HOME/.m2/settings.xml + + - uses: ./.github/actions/setup-java + # publish snapshots or releases + - name: Publish version + env: + OSSRH_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} + OSSRH_USER: ${{ secrets.ORG_OSSRH_USERNAME }} + run: |- + VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout -pl irs-registry-client) + echo "Publishing Version $VERSION to Sonatype" + mvn gpg:sign-and-deploy-file -Durl=https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=ossrh -Dfile=irs-registry-client/target/irs-registry-client-$VERSION-jar-with-dependencies.jar -DgroupId=org.eclipse.tractusx.irs -DartifactId=irs-registry-client -Dversion=$VERSION -Dpackaging=jar diff --git a/.github/workflows/publish-documentation.yaml b/.github/workflows/publish-documentation.yaml index 3f50e8b7d2..0623173695 100644 --- a/.github/workflows/publish-documentation.yaml +++ b/.github/workflows/publish-documentation.yaml @@ -44,7 +44,7 @@ jobs: - name: Build API documentation with Maven run: | - mvn clean package -pl irs-common,irs-models,irs-policy-store,irs-testing,irs-ess,irs-edc-client,irs-api -DskipTests --batch-mode + mvn clean package -pl irs-common,irs-models,irs-policy-store,irs-testing,irs-ess,irs-edc-client,irs-registry-client,irs-api -DskipTests --batch-mode cp irs-api/target/generated-sources/openapi/index.html docs/src/docs/api-specification/index.html - name: Build with Maven diff --git a/.github/workflows/tavern.yml b/.github/workflows/tavern.yml index a3f29df602..b1e11ad979 100644 --- a/.github/workflows/tavern.yml +++ b/.github/workflows/tavern.yml @@ -16,10 +16,15 @@ on: description: IRS-ESS environment to test default: 'https://irs-ess.int.demo.catena-x.net' required: true - global-asset-id: + global-asset-id-asPlanned: type: string - description: Global Asset ID to use for the tests - default: 'urn:uuid:513d7be8-e7e4-49f4-a22b-8cd31317e454' + description: Global Asset ID to use for the asPlanned tests + default: 'urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4c79e' + required: true + global-asset-id-asBuild: + type: string + description: Global Asset ID to use for the asBuild tests + default: 'urn:uuid:7940e0cc-7814-41eb-8b04-d984a325deec' required: true execution-ticket: type: string @@ -54,7 +59,8 @@ jobs: KEYCLOAK_HOST: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_TOKEN_URI }} KEYCLOAK_CLIENT_ID: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_ID }} KEYCLOAK_CLIENT_SECRET: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_SECRET }} - GLOBAL_ASSET_ID: ${{ github.event.inputs.global-asset-id || 'urn:uuid:513d7be8-e7e4-49f4-a22b-8cd31317e454' }} + GLOBAL_ASSET_ID_AS_PLANNED: ${{ github.event.inputs.global-asset-id-asPlanned || 'urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4c79e' }} + GLOBAL_ASSET_ID_AS_BUILD: ${{ github.event.inputs.global-asset-id-asBuild || 'urn:uuid:7940e0cc-7814-41eb-8b04-d984a325deec' }} run: | python -m pytest local/testing/api-tests/irs-api-tests.tavern.yaml --junitxml=tavern-results.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bcad8bbc2..a368ec822e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +### Changed +- The client code for accessing the Digital Twin Registry (central and decentral) is now available as a spring boot maven library. See the README in the irs-registry-client module for more information. + ### Known knowns - PLACEHOLDER REMOVE IF EMPTY: risks that were introduced or discovered in the release and are known but not resolved diff --git a/DEPENDENCIES b/DEPENDENCIES index 9883c7c6e4..91f158fcec 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,20 +1,17 @@ -maven/mavencentral/ch.qos.logback/logback-classic/1.4.7, EPL-1.0 OR LGPL-2.1-only, approved, #3435 -maven/mavencentral/ch.qos.logback/logback-core/1.4.7, EPL-1.0 OR LGPL-2.1-only, approved, #3373 +maven/mavencentral/ch.qos.logback/logback-classic/1.4.8, EPL-1.0 OR LGPL-2.1-only, approved, #3435 +maven/mavencentral/ch.qos.logback/logback-core/1.4.8, EPL-1.0 OR LGPL-2.1-only, approved, #3373 maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.2, Apache-2.0, approved, #8912 maven/mavencentral/com.carrotsearch.thirdparty/simple-xml-safe/2.7.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.0, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.2, Apache-2.0, approved, #7947 -maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.0, MIT AND Apache-2.0, approved, #7932 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.2, MIT AND Apache-2.0, approved, #7932 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.2, Apache-2.0, approved, #4105 -maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.0, Apache-2.0, approved, #7934 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.2, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.14.2, Apache-2.0, approved, #5933 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.0, Apache-2.0, approved, #8802 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.15.0, Apache-2.0, approved, #9180 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.15.1, Apache-2.0, approved, #9179 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jdk8/2.15.0, Apache-2.0, approved, #8808 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.0, Apache-2.0, approved, #7930 -maven/mavencentral/com.fasterxml.jackson.module/jackson-module-parameter-names/2.15.0, Apache-2.0, approved, #8803 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.15.2, Apache-2.0, approved, #9179 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jdk8/2.15.2, Apache-2.0, approved, #8808 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 +maven/mavencentral/com.fasterxml.jackson.module/jackson-module-parameter-names/2.15.2, Apache-2.0, approved, #8803 maven/mavencentral/com.fasterxml/classmate/1.5.1, Apache-2.0, approved, clearlydefined maven/mavencentral/com.github.docker-java/docker-java-api/3.2.13, Apache-2.0, approved, clearlydefined maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.2.13, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #3059 @@ -31,7 +28,7 @@ maven/mavencentral/com.jayway.jsonpath/json-path/2.8.0, Apache-2.0, approved, cl maven/mavencentral/com.nimbusds/content-type/2.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.31, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/9.43.2, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/9.43.3, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/okhttp/4.10.0, Apache-2.0 AND MPL-2.0, approved, #3057 maven/mavencentral/com.squareup.okio/okio-jvm/3.0.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.vaadin.external.google/android-json/0.0.20131108.vaadin1, Apache-2.0, approved, CQ21310 @@ -56,9 +53,9 @@ maven/mavencentral/io.github.resilience4j/resilience4j-retry/2.0.2, Apache-2.0, maven/mavencentral/io.github.resilience4j/resilience4j-spring-boot3/2.0.2, Apache-2.0, approved, #7276 maven/mavencentral/io.github.resilience4j/resilience4j-spring6/2.0.2, Apache-2.0, approved, #7277 maven/mavencentral/io.github.resilience4j/resilience4j-timelimiter/2.0.2, Apache-2.0, approved, clearlydefined -maven/mavencentral/io.micrometer/micrometer-commons/1.11.0, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9243 -maven/mavencentral/io.micrometer/micrometer-core/1.11.0, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9238 -maven/mavencentral/io.micrometer/micrometer-observation/1.11.0, Apache-2.0, approved, #9242 +maven/mavencentral/io.micrometer/micrometer-commons/1.11.1, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9243 +maven/mavencentral/io.micrometer/micrometer-core/1.11.1, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9238 +maven/mavencentral/io.micrometer/micrometer-observation/1.11.1, Apache-2.0, approved, #9242 maven/mavencentral/io.micrometer/micrometer-registry-prometheus/1.10.4, Apache-2.0, approved, #4721 maven/mavencentral/io.minio/minio/8.5.4, Apache-2.0, approved, #9097 maven/mavencentral/io.prometheus/simpleclient/0.16.0, Apache-2.0, approved, clearlydefined @@ -67,30 +64,32 @@ maven/mavencentral/io.prometheus/simpleclient_tracer_common/0.16.0, Apache-2.0, maven/mavencentral/io.prometheus/simpleclient_tracer_otel/0.16.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.prometheus/simpleclient_tracer_otel_agent/0.16.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.7, Apache-2.0, approved, #5947 -maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.8, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.7, Apache-2.0, approved, #5929 -maven/mavencentral/io.swagger.core.v3/swagger-core/2.2.0, Apache-2.0, approved, #9265 maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.7, Apache-2.0, approved, #5919 -maven/mavencentral/io.swagger.core.v3/swagger-models/2.2.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger/swagger-annotations/1.6.8, Apache-2.0, approved, #3792 maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.0, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.2, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca maven/mavencentral/jakarta.json/jakarta.json-api/2.1.1, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7907 +maven/mavencentral/jakarta.json/jakarta.json-api/2.1.2, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7907 maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, approved, clearlydefined maven/mavencentral/jakarta.ws.rs/jakarta.ws.rs-api/3.1.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.rest maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.0, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/junit/junit/4.13.2, EPL-2.0, approved, CQ23636 maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.4, Apache-2.0, approved, #7164 +maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.5, Apache-2.0, approved, #7164 maven/mavencentral/net.bytebuddy/byte-buddy/1.12.21, Apache-2.0 AND BSD-3-Clause, approved, #1811 -maven/mavencentral/net.bytebuddy/byte-buddy/1.14.4, Apache-2.0 AND BSD-3-Clause, approved, #7163 +maven/mavencentral/net.bytebuddy/byte-buddy/1.14.5, Apache-2.0 AND BSD-3-Clause, approved, #7163 maven/mavencentral/net.datafaker/datafaker/1.9.0, Apache-2.0, approved, #8797 maven/mavencentral/net.java.dev.jna/jna/5.8.0, Apache-2.0 OR LGPL-2.1-or-later, approved, CQ23217 maven/mavencentral/net.jimblackler.jsonschemafriend/core/0.11.4, Apache-2.0, approved, #3269 maven/mavencentral/net.jimblackler.jsonschemafriend/extra/0.11.4, Apache-2.0, approved, #3270 maven/mavencentral/net.jimblackler/jsonschemafriend/0.11.4, Apache-2.0, approved, #3271 +maven/mavencentral/net.minidev/accessors-smart/2.4.11, Apache-2.0, approved, #7515 maven/mavencentral/net.minidev/accessors-smart/2.4.9, Apache-2.0, approved, #7515 maven/mavencentral/net.minidev/json-smart/2.4.10, Apache-2.0, approved, #3288 +maven/mavencentral/net.minidev/json-smart/2.4.11, Apache-2.0, approved, #3288 maven/mavencentral/org.apache.commons/commons-compress/1.22, Apache-2.0 AND BSD-3-Clause, approved, #4299 maven/mavencentral/org.apache.commons/commons-compress/1.23.0, Apache-2.0 AND BSD-3-Clause, approved, #7506 maven/mavencentral/org.apache.commons/commons-lang3/3.12.0, Apache-2.0, approved, clearlydefined @@ -99,12 +98,15 @@ maven/mavencentral/org.apache.logging.log4j/log4j-core/2.20.0, Apache-2.0 AND (A maven/mavencentral/org.apache.logging.log4j/log4j-jul/2.20.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.logging.log4j/log4j-slf4j2-impl/2.20.0, Apache-2.0, approved, #8801 maven/mavencentral/org.apache.logging.log4j/log4j-to-slf4j/2.20.0, Apache-2.0, approved, #8799 -maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-core/10.1.8, Apache-2.0 AND (EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND (CDDL-1.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND W3C AND CC0-1.0, approved, #5949 -maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-el/10.1.8, Apache-2.0, approved, #6997 -maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-websocket/10.1.8, Apache-2.0, approved, #7920 +maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-core/10.1.10, Apache-2.0 AND (EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND (CDDL-1.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND W3C AND CC0-1.0, approved, #5949 +maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-el/10.1.10, Apache-2.0, approved, #6997 +maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-websocket/10.1.10, Apache-2.0, approved, #7920 maven/mavencentral/org.apiguardian/apiguardian-api/1.1.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.aspectj/aspectjweaver/1.9.19, EPL-1.0, approved, tools.aspectj maven/mavencentral/org.assertj/assertj-core/3.24.2, Apache-2.0, approved, #6161 +maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.75, MIT, approved, #9166 +maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.75, MIT AND CC0-1.0, approved, #9167 +maven/mavencentral/org.bouncycastle/bcutil-jdk18on/1.75, MIT, approved, #9170 maven/mavencentral/org.checkerframework/checker-qual/3.33.0, MIT, approved, clearlydefined maven/mavencentral/org.eclipse.edc/aggregate-service-spi/0.1.0, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/asset-spi/0.1.0, Apache-2.0, approved, technology.edc @@ -153,20 +155,21 @@ maven/mavencentral/org.eclipse.tractusx.irs/irs-edc-client/0.0.2-SNAPSHOT, Apach maven/mavencentral/org.eclipse.tractusx.irs/irs-ess/0.0.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx maven/mavencentral/org.eclipse.tractusx.irs/irs-models/0.0.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx maven/mavencentral/org.eclipse.tractusx.irs/irs-policy-store/0.0.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx +maven/mavencentral/org.eclipse.tractusx.irs/irs-registry-client/1.0.0-SNAPSHOT, Apache-2.0, approved, automotive.tractusx maven/mavencentral/org.glassfish/jakarta.json/2.0.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp maven/mavencentral/org.hamcrest/hamcrest-core/2.2, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.hamcrest/hamcrest/2.2, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.hibernate.validator/hibernate-validator/8.0.0.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/org.jboss.logging/jboss-logging/3.4.1.Final, Apache-2.0, approved, CQ21255 -maven/mavencentral/org.jboss.logging/jboss-logging/3.5.0.Final, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.jboss.logging/jboss-logging/3.5.1.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.31, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.8.21, Apache-2.0, approved, #8910 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.8.22, Apache-2.0, approved, #8910 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.5.31, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.21, Apache-2.0, approved, #8807 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.22, Apache-2.0, approved, #8807 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.5.31, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.21, Apache-2.0, approved, #8919 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.22, Apache-2.0, approved, #8875 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.6.20, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.8.21, Apache-2.0, approved, #8865 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.8.22, Apache-2.0, approved, #8865 maven/mavencentral/org.jetbrains/annotations/13.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.jetbrains/annotations/17.0.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.jetbrains/annotations/24.0.1, Apache-2.0, approved, #7417 @@ -180,52 +183,51 @@ maven/mavencentral/org.mockito/mockito-junit-jupiter/5.3.1, MIT, approved, clear maven/mavencentral/org.opentest4j/opentest4j/1.2.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.ow2.asm/asm/9.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.projectlombok/lombok/1.18.26, MIT AND LicenseRef-Public-Domain, approved, CQ23907 +maven/mavencentral/org.projectlombok/lombok/1.18.28, MIT AND LicenseRef-Public-Domain, approved, CQ23907 maven/mavencentral/org.rnorth.duct-tape/duct-tape/1.0.8, MIT, approved, clearlydefined maven/mavencentral/org.skyscreamer/jsonassert/1.5.1, Apache-2.0, approved, clearlydefined maven/mavencentral/org.slf4j/jul-to-slf4j/2.0.7, MIT, approved, #7698 -maven/mavencentral/org.slf4j/slf4j-api/2.0.2, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.7, MIT, approved, #5915 -maven/mavencentral/org.springdoc/springdoc-openapi-common/1.6.7, Apache-2.0, approved, clearlydefined maven/mavencentral/org.springdoc/springdoc-openapi-starter-common/2.0.2, Apache-2.0, approved, #5920 maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-api/2.0.2, Apache-2.0, approved, #5950 maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-ui/2.0.2, Apache-2.0, approved, #5923 -maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-log4j2/3.1.0, Apache-2.0, approved, #8800 -maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-client/3.1.0, Apache-2.0, approved, #8806 -maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-resource-server/3.1.0, Apache-2.0, approved, #8804 -maven/mavencentral/org.springframework.boot/spring-boot-starter-security/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-test/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-tomcat/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-test-autoconfigure/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-test/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot/3.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.data/spring-data-commons/3.1.0, Apache-2.0, approved, #8805 -maven/mavencentral/org.springframework.security/spring-security-config/6.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.security/spring-security-core/6.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.security/spring-security-crypto/6.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.security/spring-security-oauth2-client/6.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.1.0, Apache-2.0, approved, #8798 -maven/mavencentral/org.springframework.security/spring-security-web/6.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework/spring-aop/6.0.9, Apache-2.0, approved, #5940 -maven/mavencentral/org.springframework/spring-beans/6.0.9, Apache-2.0, approved, #5937 -maven/mavencentral/org.springframework/spring-context/6.0.9, Apache-2.0, approved, #5936 -maven/mavencentral/org.springframework/spring-core/6.0.9, Apache-2.0 AND BSD-3-Clause, approved, #5948 -maven/mavencentral/org.springframework/spring-expression/6.0.9, Apache-2.0, approved, #3284 -maven/mavencentral/org.springframework/spring-jcl/6.0.9, Apache-2.0, approved, #3283 -maven/mavencentral/org.springframework/spring-test/6.0.9, Apache-2.0, approved, #7003 -maven/mavencentral/org.springframework/spring-web/6.0.9, Apache-2.0, approved, #5942 -maven/mavencentral/org.springframework/spring-webmvc/6.0.9, Apache-2.0, approved, #5944 +maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.1.1, Apache-2.0, approved, #9348 +maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.1.1, Apache-2.0, approved, #9342 +maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.1.1, Apache-2.0, approved, #9341 +maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.1.1, Apache-2.0, approved, #9344 +maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.1.1, Apache-2.0, approved, #9338 +maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.1.1, Apache-2.0, approved, #9336 +maven/mavencentral/org.springframework.boot/spring-boot-starter-log4j2/3.1.1, Apache-2.0, approved, #8800 +maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.1.1, Apache-2.0, approved, #9343 +maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-client/3.1.1, Apache-2.0, approved, #8806 +maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-resource-server/3.1.1, Apache-2.0, approved, #8804 +maven/mavencentral/org.springframework.boot/spring-boot-starter-security/3.1.1, Apache-2.0, approved, #9337 +maven/mavencentral/org.springframework.boot/spring-boot-starter-test/3.1.1, Apache-2.0, approved, #9353 +maven/mavencentral/org.springframework.boot/spring-boot-starter-tomcat/3.1.1, Apache-2.0, approved, #9351 +maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.1.1, Apache-2.0, approved, #9335 +maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.1.1, Apache-2.0, approved, #9347 +maven/mavencentral/org.springframework.boot/spring-boot-starter/3.1.1, Apache-2.0, approved, #9349 +maven/mavencentral/org.springframework.boot/spring-boot-test-autoconfigure/3.1.1, Apache-2.0, approved, #9339 +maven/mavencentral/org.springframework.boot/spring-boot-test/3.1.1, Apache-2.0, approved, #9346 +maven/mavencentral/org.springframework.boot/spring-boot/3.1.1, Apache-2.0, approved, #9352 +maven/mavencentral/org.springframework.data/spring-data-commons/3.1.1, Apache-2.0, approved, #8805 +maven/mavencentral/org.springframework.security/spring-security-config/6.1.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.springframework.security/spring-security-core/6.1.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.springframework.security/spring-security-crypto/6.1.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.springframework.security/spring-security-oauth2-client/6.1.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.1.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.1.1, Apache-2.0, approved, #9345 +maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.1.1, Apache-2.0, approved, #8798 +maven/mavencentral/org.springframework.security/spring-security-web/6.1.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.springframework/spring-aop/6.0.10, Apache-2.0, approved, #5940 +maven/mavencentral/org.springframework/spring-beans/6.0.10, Apache-2.0, approved, #5937 +maven/mavencentral/org.springframework/spring-context/6.0.10, Apache-2.0, approved, #5936 +maven/mavencentral/org.springframework/spring-core/6.0.10, Apache-2.0 AND BSD-3-Clause, approved, #5948 +maven/mavencentral/org.springframework/spring-expression/6.0.10, Apache-2.0, approved, #3284 +maven/mavencentral/org.springframework/spring-jcl/6.0.10, Apache-2.0, approved, #3283 +maven/mavencentral/org.springframework/spring-test/6.0.10, Apache-2.0, approved, #7003 +maven/mavencentral/org.springframework/spring-web/6.0.10, Apache-2.0, approved, #5942 +maven/mavencentral/org.springframework/spring-webmvc/6.0.10, Apache-2.0, approved, #5944 maven/mavencentral/org.testcontainers/junit-jupiter/1.17.6, MIT, approved, clearlydefined maven/mavencentral/org.testcontainers/testcontainers/1.17.6, MIT, approved, #3074 maven/mavencentral/org.webjars/swagger-ui/4.15.5, Apache-2.0 AND MIT, approved, #5921 diff --git a/Dockerfile b/Dockerfile index 7511b47437..1f0dab0d79 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,7 @@ COPY irs-integration-tests irs-integration-tests COPY irs-api irs-api COPY irs-common irs-common COPY irs-edc-client irs-edc-client +COPY irs-registry-client irs-registry-client COPY irs-models irs-models COPY irs-parent-spring-boot irs-parent-spring-boot COPY irs-testing irs-testing diff --git a/charts/irs-helm/templates/configmap-spring-app-config.yaml b/charts/irs-helm/templates/configmap-spring-app-config.yaml index d781d24c01..a671e5c609 100644 --- a/charts/irs-helm/templates/configmap-spring-app-config.yaml +++ b/charts/irs-helm/templates/configmap-spring-app-config.yaml @@ -84,7 +84,7 @@ data: bpdm: bpnEndpoint: {{ tpl (.Values.bpdm.bpnEndpoint | default "") . | quote }} - edc: + irs-edc-client: callback-url: {{ tpl (.Values.edc.callbackurl | default (printf "http://%s%s" .Release.Name "-irs-helm:8181/internal/endpoint-data-reference")) . | quote }} controlplane: request-ttl: {{ .Values.edc.controlplane.request.ttl | default "PT10M" | quote }} @@ -106,6 +106,7 @@ data: path: {{ tpl (.Values.edc.submodel.path | default "/submodel") . | quote }} urn-prefix: {{ tpl (.Values.edc.submodel.urnprefix | default "/urn") . | quote }} + edc: catalog: policies: allowedNames: {{ .Values.edc.catalog.policies.allowedNames | default "" | quote }} diff --git a/docs/src/api/irs-v1.0.yaml b/docs/src/api/irs-v1.0.yaml index d505f9278a..b8f8fe7d34 100644 --- a/docs/src/api/irs-v1.0.yaml +++ b/docs/src/api/irs-v1.0.yaml @@ -182,12 +182,14 @@ paths: - description: Zero-based page index (0..N) in: query name: page + required: false schema: type: integer default: 0 - description: The size of the page to be returned in: query name: size + required: false schema: type: integer default: 20 @@ -195,6 +197,7 @@ paths: \ sort order is ascending. Multiple sort criteria are supported." in: query name: sort + required: false schema: type: array items: @@ -1342,6 +1345,7 @@ components: minimum: 0 BatchOrderCreated: type: object + description: Id of the created Batch order. additionalProperties: false properties: id: @@ -1679,6 +1683,7 @@ components: JobHandle: type: object additionalProperties: false + description: The unique jobId handle of the just processed job. properties: id: type: string diff --git a/irs-api/pom.xml b/irs-api/pom.xml index d8a9dd38f6..0eb74e8327 100644 --- a/irs-api/pom.xml +++ b/irs-api/pom.xml @@ -33,6 +33,11 @@ irs-edc-client ${revision} + + org.eclipse.tractusx.irs + irs-registry-client + 1.0.0-SNAPSHOT + org.eclipse.tractusx.irs irs-policy-store @@ -43,7 +48,6 @@ irs-common ${revision} - io.minio minio diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/BpdmDelegate.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/BpdmDelegate.java index ab2b576500..0e084faadd 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/BpdmDelegate.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/BpdmDelegate.java @@ -54,52 +54,54 @@ public BpdmDelegate(final AbstractDelegate nextStep, final BpdmFacade bpdmFacade @Override public ItemContainer process(final ItemContainer.ItemContainerBuilder itemContainerBuilder, final JobParameter jobData, final AASTransferProcess aasTransferProcess, final String itemId) { - final RequestMetric requestMetric = new RequestMetric(); - requestMetric.setType(RequestMetric.RequestType.BPDM); - try { - itemContainerBuilder.build() - .getBpns() - .forEach(bpn -> lookupBPN(itemContainerBuilder, itemId, bpn, jobData.isLookupBPNs(), requestMetric)); - } catch (final RestClientException e) { - log.info("Business Partner endpoint could not be retrieved for Item: {}. Creating Tombstone.", itemId); - requestMetric.incrementFailed(); - itemContainerBuilder.tombstone(Tombstone.from(itemId, null, e, retryCount, ProcessStep.BPDM_REQUEST)) - .metric(requestMetric); + if (jobData.isLookupBPNs()) { + log.debug("BPN Lookup enabled, collecting BPN information"); + + final RequestMetric requestMetric = new RequestMetric(); + requestMetric.setType(RequestMetric.RequestType.BPDM); + itemContainerBuilder.metric(requestMetric); + + try { + itemContainerBuilder.build() + .getBpns() + .forEach(bpn -> lookupBPN(itemContainerBuilder, itemId, bpn, + requestMetric)); + } catch (final RestClientException e) { + log.info("Business Partner endpoint could not be retrieved for Item: {}. Creating Tombstone.", itemId); + requestMetric.incrementFailed(); + itemContainerBuilder.tombstone(Tombstone.from(itemId, null, e, retryCount, ProcessStep.BPDM_REQUEST)); + } + } else { + log.debug("BPN lookup disabled, no BPN information will be collected."); } return next(itemContainerBuilder, jobData, aasTransferProcess, itemId); } private void lookupBPN(final ItemContainer.ItemContainerBuilder itemContainerBuilder, final String itemId, - final Bpn bpn, final boolean bpnLookupEnabled, final RequestMetric metric) { - if (bpnLookupEnabled) { - log.debug("BPN Lookup enabled, collecting BPN information"); - bpdmFacade.findManufacturerName(bpn.getManufacturerId()).ifPresentOrElse(name -> { - if (BPN_RGX.matcher(bpn.getManufacturerId() + bpn.getManufacturerName()).find()) { - bpn.updateManufacturerName(name); - metric.incrementCompleted(); - itemContainerBuilder.metric(metric); - } else { - final String message = String.format("BPN: \"%s\" for CatenaXId: %s is not valid.", - bpn.getManufacturerId() + bpn.getManufacturerName(), itemId); - log.warn(message); - metric.incrementFailed(); - itemContainerBuilder.tombstone( - Tombstone.from(itemId, null, new BpdmDelegateProcessingException(message), 0, - ProcessStep.BPDM_VALIDATION)).metric(metric); - } - }, () -> { - final String message = String.format("BPN not exist for given ManufacturerId: %s and for CatenaXId: %s.", - bpn.getManufacturerId(), itemId); + final Bpn bpn, final RequestMetric metric) { + bpdmFacade.findManufacturerName(bpn.getManufacturerId()).ifPresentOrElse(name -> { + if (BPN_RGX.matcher(bpn.getManufacturerId() + bpn.getManufacturerName()).find()) { + bpn.updateManufacturerName(name); + metric.incrementCompleted(); + } else { + final String message = String.format("BPN: \"%s\" for CatenaXId: %s is not valid.", + bpn.getManufacturerId() + bpn.getManufacturerName(), itemId); log.warn(message); metric.incrementFailed(); - itemContainerBuilder.tombstone(Tombstone.from(itemId, null, new BpdmDelegateProcessingException(message), 0, - ProcessStep.BPDM_REQUEST)).metric(metric); - }); - } else { - log.debug("BPN lookup disabled, no BPN information will be collected."); - } + itemContainerBuilder.tombstone( + Tombstone.from(itemId, null, new BpdmDelegateProcessingException(message), 0, + ProcessStep.BPDM_VALIDATION)); + } + }, () -> { + final String message = String.format("BPN not exist for given ManufacturerId: %s and for CatenaXId: %s.", + bpn.getManufacturerId(), itemId); + log.warn(message); + metric.incrementFailed(); + itemContainerBuilder.tombstone(Tombstone.from(itemId, null, new BpdmDelegateProcessingException(message), 0, + ProcessStep.BPDM_REQUEST)); + }); } } diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegate.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegate.java index def439f8bc..1f07fa6b03 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegate.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegate.java @@ -22,14 +22,17 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.aaswrapper.job.delegate; +import java.util.List; + import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.irs.aaswrapper.job.AASTransferProcess; import org.eclipse.tractusx.irs.aaswrapper.job.ItemContainer; -import org.eclipse.tractusx.irs.aaswrapper.registry.domain.DigitalTwinRegistryKey; -import org.eclipse.tractusx.irs.aaswrapper.registry.domain.DigitalTwinRegistryService; import org.eclipse.tractusx.irs.component.JobParameter; import org.eclipse.tractusx.irs.component.Tombstone; import org.eclipse.tractusx.irs.component.enums.ProcessStep; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryKey; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; import org.springframework.web.client.RestClientException; /** @@ -52,9 +55,10 @@ public ItemContainer process(final ItemContainer.ItemContainerBuilder itemContai final AASTransferProcess aasTransferProcess, final String itemId) { try { - itemContainerBuilder.shell(digitalTwinRegistryService.getAAShellDescriptor( - new DigitalTwinRegistryKey(itemId, jobData.getBpn()))); - } catch (final RestClientException e) { + itemContainerBuilder.shell(digitalTwinRegistryService.fetchShells( + List.of(new DigitalTwinRegistryKey(itemId, jobData.getBpn())) + ).stream().findFirst().orElseThrow()); + } catch (final RestClientException | RegistryServiceException e) { log.info("Shell Endpoint could not be retrieved for Item: {}. Creating Tombstone.", itemId); itemContainerBuilder.tombstone(Tombstone.from(itemId, null, e, retryCount, ProcessStep.DIGITAL_TWIN_REQUEST)); } diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/RelationshipDelegate.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/RelationshipDelegate.java index fef30bddfb..a490b0c08c 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/RelationshipDelegate.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/RelationshipDelegate.java @@ -39,7 +39,7 @@ import org.eclipse.tractusx.irs.component.enums.AspectType; import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.component.enums.ProcessStep; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; /** * Builds relationship array for AAShell from previous step. diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegate.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegate.java index 54957b45e3..4a8ca6b77c 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegate.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegate.java @@ -38,7 +38,7 @@ import org.eclipse.tractusx.irs.component.assetadministrationshell.Endpoint; import org.eclipse.tractusx.irs.component.assetadministrationshell.SubmodelDescriptor; import org.eclipse.tractusx.irs.component.enums.ProcessStep; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException; import org.eclipse.tractusx.irs.semanticshub.SemanticsHubFacade; import org.eclipse.tractusx.irs.services.validation.InvalidSchemaException; 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 deleted file mode 100644 index 616ea73a88..0000000000 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryService.java +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************** - * 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 java.util.List; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -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.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Service; - -/** - * Decentral implementation of DigitalTwinRegistryService - */ -@Service -@ConditionalOnProperty(prefix = "digitalTwinRegistry", name = "type", havingValue = "decentral") -@RequiredArgsConstructor -@Slf4j -public class DecentralDigitalTwinRegistryService implements DigitalTwinRegistryService { - - private final DiscoveryFinderClient discoveryFinderClient; - private final EndpointDataForConnectorsService endpointDataForConnectorsService; - private final DecentralDigitalTwinRegistryClient decentralDigitalTwinRegistryClient; - - @Override - public AssetAdministrationShellDescriptor getAAShellDescriptor(final DigitalTwinRegistryKey key) { - 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) - .endpoints(); - final List connectorEndpoints = discoveryEndpoints.stream() - .map(discoveryEndpoint -> discoveryFinderClient.findConnectorEndpoints( - discoveryEndpoint.endpointAddress(), - providedBpn) - .stream() - .filter(edcDiscoveryResult -> edcDiscoveryResult.bpn() - .equals(key.bpn())) - .map(EdcDiscoveryResult::connectorEndpoint) - .toList()) - .flatMap(List::stream) - .flatMap(List::stream) - .toList(); - - final EndpointDataReference endpointDataReference = endpointDataForConnectorsService.findEndpointDataForConnectors( - connectorEndpoints); - final IdentifierKeyValuePair identifierKeyValuePair = IdentifierKeyValuePair.builder() - .key("globalAssetId") - .value(key.globalAssetId()) - .build(); - final String aaShellIdentification = decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink( - endpointDataReference, List.of(identifierKeyValuePair)) - .stream() - .findFirst() - .orElse(key.globalAssetId()); - log.info("Retrieved AAS Identification {} for globalAssetId {}", aaShellIdentification, key.globalAssetId()); - - return decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(endpointDataReference, - aaShellIdentification); - - } - -} diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/JobConfiguration.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/JobConfiguration.java index 2a82846832..c36cbc0a86 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/JobConfiguration.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/JobConfiguration.java @@ -30,7 +30,6 @@ import io.github.resilience4j.retry.RetryRegistry; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; -import org.eclipse.tractusx.irs.aaswrapper.registry.domain.DigitalTwinRegistryService; import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade; import org.eclipse.tractusx.irs.aaswrapper.job.AASRecursiveJobHandler; import org.eclipse.tractusx.irs.aaswrapper.job.AASTransferProcess; @@ -50,6 +49,7 @@ import org.eclipse.tractusx.irs.common.persistence.BlobPersistence; import org.eclipse.tractusx.irs.common.persistence.BlobPersistenceException; import org.eclipse.tractusx.irs.common.persistence.MinioBlobPersistence; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryService; import org.eclipse.tractusx.irs.semanticshub.SemanticsHubFacade; import org.eclipse.tractusx.irs.services.MeterRegistryService; import org.eclipse.tractusx.irs.services.validation.JsonValidatorService; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RegistryConfiguration.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RegistryConfiguration.java new file mode 100644 index 0000000000..27a4000e1f --- /dev/null +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RegistryConfiguration.java @@ -0,0 +1,82 @@ +/******************************************************************************** + * 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.configuration; + +import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade; +import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; +import org.eclipse.tractusx.irs.registryclient.central.CentralDigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.central.DigitalTwinRegistryClient; +import org.eclipse.tractusx.irs.registryclient.central.DigitalTwinRegistryClientImpl; +import org.eclipse.tractusx.irs.registryclient.decentral.DecentralDigitalTwinRegistryClient; +import org.eclipse.tractusx.irs.registryclient.decentral.DecentralDigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.decentral.EdcRetrieverException; +import org.eclipse.tractusx.irs.registryclient.decentral.EndpointDataForConnectorsService; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderClientImpl; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.web.client.RestTemplate; + +/** + * IRS configuration settings. Sets up the digital twin registry client. + */ +@Configuration +public class RegistryConfiguration { + + @Bean + @ConditionalOnProperty(prefix = "digitalTwinRegistry", name = "type", havingValue = "central") + public CentralDigitalTwinRegistryService centralDigitalTwinRegistryService(final DigitalTwinRegistryClient client) { + return new CentralDigitalTwinRegistryService(client); + } + + @Bean + @Profile({ "!local && !stubtest" }) + @ConditionalOnProperty(prefix = "digitalTwinRegistry", name = "type", havingValue = "central") + public DigitalTwinRegistryClient digitalTwinRegistryClientImpl( + @Qualifier(RestTemplateConfig.DTR_REST_TEMPLATE) final RestTemplate restTemplate, + @Value("${digitalTwinRegistry.descriptorEndpoint:}") final String descriptorEndpoint, + @Value("${digitalTwinRegistry.shellLookupEndpoint:}") final String shellLookupEndpoint) { + return new DigitalTwinRegistryClientImpl(restTemplate, descriptorEndpoint, shellLookupEndpoint); + } + + @Bean + @ConditionalOnProperty(prefix = "digitalTwinRegistry", name = "type", havingValue = "decentral") + public DecentralDigitalTwinRegistryService decentralDigitalTwinRegistryService( + @Qualifier(RestTemplateConfig.EDC_REST_TEMPLATE) final RestTemplate edcRestTemplate, + @Qualifier(RestTemplateConfig.DTR_REST_TEMPLATE) final RestTemplate dtrRestTemplate, + final EdcSubmodelFacade facade, + @Value("${digitalTwinRegistry.discoveryFinderUrl:}") final String finderUrl) { + return new DecentralDigitalTwinRegistryService(new DiscoveryFinderClientImpl(finderUrl, dtrRestTemplate), + new EndpointDataForConnectorsService((edcConnectorEndpoint, assetType, assetValue) -> { + try { + return facade.getEndpointReferenceForAsset(edcConnectorEndpoint, assetType, assetValue); + } catch (EdcClientException e) { + throw new EdcRetrieverException(e); + } + }), new DecentralDigitalTwinRegistryClient(edcRestTemplate)); + } + +} diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java index 0272c15066..4e04e88db0 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java @@ -25,6 +25,7 @@ import static java.util.Objects.isNull; import java.io.IOException; +import java.net.SocketTimeoutException; import java.time.Duration; import java.util.List; @@ -32,7 +33,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; +import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; @@ -69,28 +72,43 @@ public class RestTemplateConfig { public static final String SEMHUB_REST_TEMPLATE = "oAuthRestTemplate"; public static final String NO_ERROR_REST_TEMPLATE = "noErrorRestTemplate"; public static final String DISCOVERY_REST_TEMPLATE = "discoveryRestTemplate"; - public static final String EDC_REST_TEMPLATE = "edcRestTemplate"; + public static final String EDC_REST_TEMPLATE = "edcClientRestTemplate"; private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService; private final ClientRegistrationRepository clientRegistrationRepository; - private RestTemplate oAuthRestTemplate(final RestTemplateBuilder restTemplateBuilder, final Duration readTimeout, - final Duration connectTimeout, final String clientRegistrationId) { + private RestTemplateBuilder oAuthRestTemplate(final RestTemplateBuilder restTemplateBuilder, + final Duration readTimeout, final Duration connectTimeout, final String clientRegistrationId) { final var clientRegistration = clientRegistrationRepository.findByRegistrationId(clientRegistrationId); return restTemplateBuilder.additionalInterceptors( new OAuthClientCredentialsRestTemplateInterceptor(authorizedClientManager(), clientRegistration)) .setReadTimeout(readTimeout) - .setConnectTimeout(connectTimeout) - .build(); + .setConnectTimeout(connectTimeout); } @Bean(DTR_REST_TEMPLATE) /* package */ RestTemplate digitalTwinRegistryRestTemplate(final RestTemplateBuilder restTemplateBuilder, @Value("${digitalTwinRegistry.timeout.read}") final Duration readTimeout, @Value("${digitalTwinRegistry.timeout.connect}") final Duration connectTimeout, - @Value("${digitalTwinRegistry.oAuthClientId}") final String clientRegistrationId) { - return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, clientRegistrationId); + @Value("${digitalTwinRegistry.oAuthClientId}") final String clientRegistrationId, + final OutboundMeterRegistryService meterRegistryService) { + + return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, + clientRegistrationId).additionalInterceptors(getRegistryInterceptor(meterRegistryService)).build(); + } + + @NotNull + private static ClientHttpRequestInterceptor getRegistryInterceptor( + final OutboundMeterRegistryService meterRegistryService) { + return (request, body, execution) -> { + try { + return execution.execute(request, body); + } catch (SocketTimeoutException e) { + meterRegistryService.incrementRegistryTimeoutCounter(); + throw e; + } + }; } @Bean(SEMHUB_REST_TEMPLATE) @@ -98,7 +116,7 @@ private RestTemplate oAuthRestTemplate(final RestTemplateBuilder restTemplateBui @Value("${semanticshub.timeout.read}") final Duration readTimeout, @Value("${semanticshub.timeout.connect}") final Duration connectTimeout, @Value("${semanticshub.oAuthClientId}") final String clientRegistrationId) { - return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, clientRegistrationId); + return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, clientRegistrationId).build(); } @Bean(BPDM_REST_TEMPLATE) @@ -106,7 +124,7 @@ private RestTemplate oAuthRestTemplate(final RestTemplateBuilder restTemplateBui @Value("${bpdm.timeout.read}") final Duration readTimeout, @Value("${bpdm.timeout.connect}") final Duration connectTimeout, @Value("${bpdm.oAuthClientId}") final String clientRegistrationId) { - return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, clientRegistrationId); + return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, clientRegistrationId).build(); } @Bean(DISCOVERY_REST_TEMPLATE) @@ -114,7 +132,7 @@ private RestTemplate oAuthRestTemplate(final RestTemplateBuilder restTemplateBui @Value("${ess.discovery.timeout.read}") final Duration readTimeout, @Value("${ess.discovery.timeout.connect}") final Duration connectTimeout, @Value("${ess.discovery.oAuthClientId}") final String clientRegistrationId) { - return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, clientRegistrationId); + return oAuthRestTemplate(restTemplateBuilder, readTimeout, connectTimeout, clientRegistrationId).build(); } @Bean(NO_ERROR_REST_TEMPLATE) @@ -154,11 +172,15 @@ public boolean hasError(final ClientHttpResponse statusCode) { } @Bean(EDC_REST_TEMPLATE) + @Qualifier(EDC_REST_TEMPLATE) /* package */ RestTemplate edcRestTemplate(final RestTemplateBuilder restTemplateBuilder, - @Value("${edc.submodel.timeout.read}") final Duration readTimeout, - @Value("${edc.submodel.timeout.connect}") final Duration connectTimeout) { + @Value("${irs-edc-client.submodel.timeout.read}") final Duration readTimeout, + @Value("${irs-edc-client.submodel.timeout.connect}") final Duration connectTimeout, + final OutboundMeterRegistryService meterRegistryService) { final RestTemplate restTemplate = restTemplateBuilder.setReadTimeout(readTimeout) .setConnectTimeout(connectTimeout) + .additionalInterceptors( + getEdcInterceptor(meterRegistryService)) .build(); final List> messageConverters = restTemplate.getMessageConverters(); for (final HttpMessageConverter converter : messageConverters) { @@ -171,6 +193,19 @@ public boolean hasError(final ClientHttpResponse statusCode) { return restTemplate; } + @NotNull + private static ClientHttpRequestInterceptor getEdcInterceptor( + final OutboundMeterRegistryService meterRegistryService) { + return (request, body, execution) -> { + try { + return execution.execute(request, body); + } catch (SocketTimeoutException e) { + meterRegistryService.incrementSubmodelTimeoutCounter(request.getURI().getHost()); + throw e; + } + }; + } + /** * Interceptor to add Authorization header to every call done via Rest template */ diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchOrderStore.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchOrderStore.java index e9ff95544a..878c243487 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchOrderStore.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchOrderStore.java @@ -32,7 +32,7 @@ import java.util.UUID; import lombok.extern.slf4j.Slf4j; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; import org.eclipse.tractusx.irs.common.persistence.BlobPersistence; import org.eclipse.tractusx.irs.common.persistence.BlobPersistenceException; import org.eclipse.tractusx.irs.util.JsonUtil; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchStore.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchStore.java index 34f1bf24db..e0d031e9bc 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchStore.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/PersistentBatchStore.java @@ -32,7 +32,7 @@ import java.util.UUID; import lombok.extern.slf4j.Slf4j; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; import org.eclipse.tractusx.irs.common.persistence.BlobPersistence; import org.eclipse.tractusx.irs.common.persistence.BlobPersistenceException; import org.eclipse.tractusx.irs.util.JsonUtil; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java index 24b0ec9acd..573a4b26fa 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java @@ -34,7 +34,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.irs.component.enums.JobState; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; import org.eclipse.tractusx.irs.common.persistence.BlobPersistence; import org.eclipse.tractusx.irs.common.persistence.BlobPersistenceException; import org.eclipse.tractusx.irs.services.MeterRegistryService; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java index 536317cfe3..b053bdd728 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java @@ -59,7 +59,7 @@ import org.eclipse.tractusx.irs.services.IrsItemGraphQueryService; import org.eclipse.tractusx.irs.services.SemanticHubService; import org.eclipse.tractusx.irs.services.validation.SchemaNotFoundException; -import org.springdoc.api.annotations.ParameterObject; +import org.springdoc.core.annotations.ParameterObject; import org.springdoc.core.converters.models.PageableAsQueryParam; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/validation/JsonValidatorService.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/validation/JsonValidatorService.java index 298df13315..5b919081c1 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/validation/JsonValidatorService.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/validation/JsonValidatorService.java @@ -26,7 +26,7 @@ import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; import org.eclipse.tractusx.irs.util.JsonUtil; import net.jimblackler.jsonschemafriend.GenerationException; import net.jimblackler.jsonschemafriend.Schema; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/util/JsonUtil.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/util/JsonUtil.java index 838b6cf61f..3441be1311 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/util/JsonUtil.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/util/JsonUtil.java @@ -32,7 +32,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.irs.aaswrapper.job.AASTransferProcess; import org.eclipse.tractusx.irs.connector.job.TransferProcess; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; /** * JSON object mapper. diff --git a/irs-api/src/main/resources/application.yml b/irs-api/src/main/resources/application.yml index 80bea39048..52fd3b88c3 100644 --- a/irs-api/src/main/resources/application.yml +++ b/irs-api/src/main/resources/application.yml @@ -122,7 +122,7 @@ resilience4j: registry: baseConfig: default -edc: +irs-edc-client: callback-url: ${EDC_TRANSFER_CALLBACK_URL:} # The URL where the EDR token callback will be sent to. controlplane: request-ttl: ${EDC_CONTROLPLANE_REQUEST_TTL:PT10M} # How long to wait for an async EDC negotiation request to finish, ISO 8601 Duration @@ -155,6 +155,8 @@ edc: enabled: true # Set to false to disable caching ttl: P1D # Time after which a cached Item is no longer valid and the real catalog is called instead maxCachedItems: 64000 # Maximum amount of cached catalog items +edc: + catalog: policies: # IRS will only negotiate contracts for offers with a policy as defined in the allowedNames list. # If a requested asset does not provide one of these policies, a tombstone will be created and this node will not be processed. diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegateTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegateTest.java index beefa5f1f0..7e3df757a2 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegateTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/DigitalTwinDelegateTest.java @@ -35,8 +35,9 @@ import io.github.resilience4j.retry.RetryRegistry; import org.eclipse.tractusx.irs.aaswrapper.job.AASTransferProcess; import org.eclipse.tractusx.irs.aaswrapper.job.ItemContainer; -import org.eclipse.tractusx.irs.aaswrapper.registry.domain.DigitalTwinRegistryService; import org.eclipse.tractusx.irs.component.enums.ProcessStep; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; import org.junit.jupiter.api.Test; import org.springframework.web.client.RestClientException; @@ -46,10 +47,10 @@ class DigitalTwinDelegateTest { final DigitalTwinDelegate digitalTwinDelegate = new DigitalTwinDelegate(null, digitalTwinRegistryService); @Test - void shouldFillItemContainerWithShell() { + void shouldFillItemContainerWithShell() throws RegistryServiceException { // given - when(digitalTwinRegistryService.getAAShellDescriptor(any())).thenReturn(shellDescriptor( - List.of(submodelDescriptorWithoutEndpoint("any")))); + when(digitalTwinRegistryService.fetchShells(any())).thenReturn(List.of(shellDescriptor( + List.of(submodelDescriptorWithoutEndpoint("any"))))); // when final ItemContainer result = digitalTwinDelegate.process(ItemContainer.builder(), jobParameter(), @@ -61,9 +62,9 @@ void shouldFillItemContainerWithShell() { } @Test - void shouldCatchRestClientExceptionAndPutTombstone() { + void shouldCatchRestClientExceptionAndPutTombstone() throws RegistryServiceException { // given - when(digitalTwinRegistryService.getAAShellDescriptor(any())).thenThrow( + when(digitalTwinRegistryService.fetchShells(any())).thenThrow( new RestClientException("Unable to call endpoint")); // when diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegateTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegateTest.java index 9616d50adc..c467f86b50 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegateTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/job/delegate/SubmodelDelegateTest.java @@ -37,7 +37,7 @@ import org.eclipse.tractusx.irs.aaswrapper.job.AASTransferProcess; import org.eclipse.tractusx.irs.aaswrapper.job.ItemContainer; import org.eclipse.tractusx.irs.component.enums.ProcessStep; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException; import org.eclipse.tractusx.irs.semanticshub.SemanticsHubFacade; 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 deleted file mode 100644 index 7f92a55c4c..0000000000 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryServiceTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************** - * 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.eclipse.tractusx.irs.util.TestMother.shellDescriptor; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.Collections; -import java.util.List; - -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; -import org.junit.jupiter.api.Test; - -class DecentralDigitalTwinRegistryServiceTest { - - private final DiscoveryFinderClient discoveryFinderClient = mock(DiscoveryFinderClient.class); - private final EndpointDataForConnectorsService endpointDataForConnectorsService = mock( - EndpointDataForConnectorsService.class); - - private final DecentralDigitalTwinRegistryClient decentralDigitalTwinRegistryClient = mock( - DecentralDigitalTwinRegistryClient.class); - - 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 AssetAdministrationShellDescriptor expectedShell = shellDescriptor(Collections.emptyList()); - EndpointDataReference endpointDataReference = EndpointDataReference.Builder.newInstance() - .endpoint("url.to.host") - .build(); - 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( - endpointDataReference); - when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(), - anyList())).thenReturn(Collections.emptyList()); - when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn( - expectedShell); - - // when - final AssetAdministrationShellDescriptor actualShell = decentralDigitalTwinRegistryService.getAAShellDescriptor( - digitalTwinRegistryKey); - - // then - assertThat(actualShell).isEqualTo(expectedShell); - } - -} diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/util/JsonUtilTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/util/JsonUtilTest.java index 67c298c0b1..95ab6eb289 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/util/JsonUtilTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/util/JsonUtilTest.java @@ -29,7 +29,7 @@ import java.util.HashMap; -import org.eclipse.tractusx.irs.common.JsonParseException; +import org.eclipse.tractusx.irs.data.JsonParseException; import org.junit.jupiter.api.Test; class JsonUtilTest { diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/util/StringMapperTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/util/StringMapperTest.java new file mode 100644 index 0000000000..18bc7ea704 --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/util/StringMapperTest.java @@ -0,0 +1,63 @@ +/******************************************************************************** + * 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.util; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.eclipse.tractusx.irs.component.Bpn; +import org.eclipse.tractusx.irs.component.Description; +import org.eclipse.tractusx.irs.data.JsonParseException; +import org.eclipse.tractusx.irs.data.StringMapper; +import org.junit.jupiter.api.Test; + +class StringMapperTest { + + @Test + void mapToString() { + final var serialized = StringMapper.mapToString(Bpn.withManufacturerId("test")); + + assertThat(serialized).isEqualTo("{\"manufacturerId\":\"test\",\"manufacturerName\":null}"); + } + + @Test + void shouldThrowParseExceptionWhenMappingToString() { + final var object = new Object(); + assertThatThrownBy(() -> StringMapper.mapToString(object)).isInstanceOf( + JsonParseException.class); + } + + @Test + void mapFromString() { + final var bpn = StringMapper.mapFromString("{\"manufacturerId\":\"test\",\"manufacturerName\":null}", + Bpn.class); + + assertThat(bpn.getManufacturerId()).isEqualTo("test"); + } + + @Test + void shouldThrowParseExceptionWhenMappingFromString() { + assertThatThrownBy(() -> StringMapper.mapFromString("test", Description.class)).isInstanceOf( + JsonParseException.class); + } +} \ No newline at end of file diff --git a/irs-common/pom.xml b/irs-common/pom.xml index 228707716b..0102c690a2 100644 --- a/irs-common/pom.xml +++ b/irs-common/pom.xml @@ -15,7 +15,10 @@ Contains classes shared across the different modules - + + org.slf4j + slf4j-api + org.projectlombok lombok @@ -41,6 +44,7 @@ snakeyaml + provided diff --git a/irs-cucumber-tests/pom.xml b/irs-cucumber-tests/pom.xml index e7e239ca87..d1cb0b6c36 100644 --- a/irs-cucumber-tests/pom.xml +++ b/irs-cucumber-tests/pom.xml @@ -38,6 +38,18 @@ + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + + + org.springframework.boot + spring-boot-starter-web + net.javacrumbs.json-unit json-unit-assertj diff --git a/irs-edc-client/pom.xml b/irs-edc-client/pom.xml index 520a4cae06..a907c9bd5c 100644 --- a/irs-edc-client/pom.xml +++ b/irs-edc-client/pom.xml @@ -27,25 +27,66 @@ - org.eclipse.tractusx.irs - irs-common - ${project.version} + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-logging + + + jakarta.annotation + jakarta.annotation-api + + + org.yaml + snakeyaml + + + provided commons-validator commons-validator 1.7 + + org.apache.commons + commons-lang3 + + + io.github.resilience4j + resilience4j-annotations + 2.0.2 + + + io.github.resilience4j + resilience4j-retry + 2.0.2 + org.springframework.boot spring-boot-starter-web + provided org.projectlombok lombok true - + + org.slf4j + slf4j-api + + + jakarta.validation + jakarta.validation-api + + + io.swagger.core.v3 + swagger-annotations + 2.2.8 + org.eclipse.edc @@ -56,8 +97,26 @@ runtime-metamodel org.eclipse.edc + + org.bouncycastle + bcprov-jdk18on + + + org.bouncycastle + bcpkix-jdk18on + + + org.bouncycastle + bcpkix-jdk18on + 1.75 + + + org.bouncycastle + bcprov-jdk18on + 1.75 + org.eclipse.edc dsp diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/AsyncPollingService.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/AsyncPollingService.java index fe22d216a9..2552e4804b 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/AsyncPollingService.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/AsyncPollingService.java @@ -31,7 +31,7 @@ /** * Provides scheduling services for asynchronous polling. */ -@Service +@Service("irsEdcClientAsyncPollingService") @RequiredArgsConstructor public class AsyncPollingService { diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/CatalogCacheConfiguration.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/CatalogCacheConfiguration.java index 77fb68a63b..8174f9d24b 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/CatalogCacheConfiguration.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/CatalogCacheConfiguration.java @@ -32,7 +32,7 @@ * EDC catalog cache configuration. Automatically populated by Spring from application.yml * and other configuration sources. */ -@Component +@Component("irsEdcClientCatalogCacheConfig") @ConfigurationProperties(prefix = "edc.catalog.cache") @Data public class CatalogCacheConfiguration { 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 0d640fd5fb..9d79edf13e 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 @@ -49,7 +49,7 @@ * Negotiates contracts using the EDC resulting in a data transfer endpoint being sent to the IRS. */ @Slf4j -@Service +@Service("irsEdcClientContractNegotiationService") @RequiredArgsConstructor public class ContractNegotiationService { diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EDCCatalogFacade.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EDCCatalogFacade.java index 9e27e1b2bb..69ee8e7317 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EDCCatalogFacade.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EDCCatalogFacade.java @@ -44,7 +44,7 @@ * EDC Catalog facade which handles pagination of the catalog, aggregation of contract offers * and transformation into {@link CatalogItem}. */ -@Component +@Component("irsEdcClientEdcCatalogFacade") @RequiredArgsConstructor @Slf4j public class EDCCatalogFacade { diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcCallbackController.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcCallbackController.java index e94ca65892..d289d3f690 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcCallbackController.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcCallbackController.java @@ -26,8 +26,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.irs.common.ApiConstants; -import org.eclipse.tractusx.irs.common.Masker; +import org.eclipse.tractusx.irs.data.StringMapper; +import org.eclipse.tractusx.irs.edc.client.util.Masker; import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -38,15 +38,15 @@ * Endpoint used by the EDC ControlPlane to provide the endpoint data reference. */ @Slf4j -@RestController -@RequestMapping(ApiConstants.API_PREFIX_INTERNAL) +@RestController("irsEdcClientEdcCallbackController") +@RequestMapping("${irs-edc-client.callback.mapping:internal/endpoint-data-reference}") @Hidden @RequiredArgsConstructor public class EdcCallbackController { private final EndpointDataReferenceStorage storage; - @PostMapping("/endpoint-data-reference") + @PostMapping public void receiveEdcCallback(final @RequestBody EndpointDataReference dataReference) { log.debug("Received EndpointDataReference: {}", StringMapper.mapToString(dataReference)); log.debug("Received EndpointDataReference with ID {} and endpoint {}", dataReference.getId(), diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcConfiguration.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcConfiguration.java index 2e34a70c9e..f235813006 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcConfiguration.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcConfiguration.java @@ -26,14 +26,14 @@ import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; +import org.springframework.context.annotation.Configuration; /** * EDC configuration settings. Automatically populated by Spring from application.yml * and other configuration sources. */ -@Component -@ConfigurationProperties(prefix = "edc") +@Configuration("irsEdcClientEdcConfiguration") +@ConfigurationProperties(prefix = "irs-edc-client") @Data public class EdcConfiguration { 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 dd902086b0..3383993051 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 @@ -27,7 +27,6 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.edc.catalog.spi.Catalog; import org.eclipse.edc.catalog.spi.CatalogRequest; @@ -40,6 +39,7 @@ import org.eclipse.tractusx.irs.edc.client.model.TransferProcessRequest; import org.eclipse.tractusx.irs.edc.client.model.TransferProcessResponse; import org.eclipse.tractusx.irs.edc.client.transformer.EdcTransformer; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -52,8 +52,7 @@ * Communicates with the EDC ControlPlane */ @Slf4j -@Service -@RequiredArgsConstructor +@Service("irsEdcClientEdcControlPlaneClient") @SuppressWarnings({ "PMD.TooManyMethods" }) public class EdcControlPlaneClient { @@ -67,6 +66,14 @@ public class EdcControlPlaneClient { private final EdcConfiguration config; private final EdcTransformer edcTransformer; + public EdcControlPlaneClient(@Qualifier("edcClientRestTemplate") final RestTemplate edcRestTemplate, final AsyncPollingService pollingService, + final EdcConfiguration config, final EdcTransformer edcTransformer) { + this.edcRestTemplate = edcRestTemplate; + this.pollingService = pollingService; + this.config = config; + this.edcTransformer = edcTransformer; + } + private static String getResponseBody(final ResponseEntity response) { String responseBody = ""; if (response.hasBody() && response.getBody() != null) { @@ -87,7 +94,7 @@ private static String getResponseBody(final ResponseEntity response) { final var url = endpoint.getData() + endpoint.getCatalog(); final String requestJson = edcTransformer.transformCatalogRequestToJson(requestBody).toString(); - + log.info("Requesting catalog with payload: {}", requestJson); final ResponseEntity response = edcRestTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(requestJson, headers()), String.class); final String catalog = getResponseBody(response); diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcDataPlaneClient.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcDataPlaneClient.java index bf2c0de837..ff738fa280 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcDataPlaneClient.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcDataPlaneClient.java @@ -26,11 +26,12 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.data.StringMapper; import org.eclipse.tractusx.irs.edc.client.model.notification.EdcNotification; import org.eclipse.tractusx.irs.edc.client.model.notification.EdcNotificationResponse; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -43,13 +44,16 @@ * Communicates with the EDC DataPlane. */ @Slf4j -@Service -@RequiredArgsConstructor +@Service("irsEdcClientEdcDataPlaneClient") public class EdcDataPlaneClient { private static final Pattern RESPONSE_PATTERN = Pattern.compile("\\{\"data\":\"(?.*)\"\\}"); private final RestTemplate edcRestTemplate; + public EdcDataPlaneClient(@Qualifier("edcClientRestTemplate") final RestTemplate edcRestTemplate) { + this.edcRestTemplate = edcRestTemplate; + } + public String getData(final EndpointDataReference dataReference, final String subUrl) { final String url = getUrl(dataReference.getEndpoint(), subUrl); 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 8bd894ec2b..3af62b446c 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 @@ -22,7 +22,6 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.edc.client; -import java.net.SocketTimeoutException; import java.net.URI; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; @@ -39,9 +38,9 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.validator.routines.UrlValidator; import org.eclipse.edc.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.data.CxTestDataContainer; +import org.eclipse.tractusx.irs.data.StringMapper; +import org.eclipse.tractusx.irs.edc.client.util.Masker; 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; @@ -51,7 +50,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; import org.springframework.util.StopWatch; -import org.springframework.web.client.ResourceAccessException; /** * Public API facade for EDC domain @@ -120,7 +118,7 @@ public CompletableFuture getEndpointReferenceForAsset(fin /** * Public API facade for EDC domain */ -@Service +@Service("irsEdcClientEdcSubmodelClientImpl") @Slf4j @RequiredArgsConstructor @Profile({ "!local && !stubtest" }) @@ -133,7 +131,6 @@ class EdcSubmodelClientImpl implements EdcSubmodelClient { private final EdcDataPlaneClient edcDataPlaneClient; private final EndpointDataReferenceStorage endpointDataReferenceStorage; private final AsyncPollingService pollingService; - private final OutboundMeterRegistryService meterRegistryService; private final RetryRegistry retryRegistry; private final EDCCatalogFacade catalogFacade; private final UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); @@ -351,16 +348,7 @@ private T execute(final String endpointAddress, final CheckedSupplier sup final String host = URI.create(endpointAddress).getHost(); final Retry retry = retryRegistry.retry(host, "default"); try { - return Retry.decorateCallable(retry, () -> { - try { - return supplier.get(); - } catch (ResourceAccessException e) { - if (e.getCause() instanceof SocketTimeoutException) { - meterRegistryService.incrementSubmodelTimeoutCounter(endpointAddress); - } - throw e; - } - }).call(); + return Retry.decorateCallable(retry, supplier::get).call(); } catch (EdcClientException e) { throw e; } catch (Exception e) { diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelFacade.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelFacade.java index dbed5c458d..591c2080ab 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelFacade.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EdcSubmodelFacade.java @@ -38,7 +38,7 @@ /** * Public API Facade for submodel domain */ -@Service +@Service("irsEdcClientEdcSubmodelFacade") @Slf4j @RequiredArgsConstructor @SuppressWarnings("PMD.AvoidDuplicateLiterals") diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EndpointDataReferenceStorage.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EndpointDataReferenceStorage.java index 58e64fbeca..742b3d5105 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EndpointDataReferenceStorage.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/EndpointDataReferenceStorage.java @@ -38,14 +38,14 @@ /** * InMemory storage for endpoint data references. */ -@Service +@Service("irsEdcClientEndpointDataReferenceStorage") public class EndpointDataReferenceStorage { private final Map storageMap = new ConcurrentHashMap<>(); private final Duration storageDuration; public EndpointDataReferenceStorage( - @Value("${edc.controlplane.datareference.storage.duration}") final Duration storageDuration) { + @Value("${irs-edc-client.controlplane.datareference.storage.duration}") final Duration storageDuration) { this.storageDuration = storageDuration; } diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/SubmodelTestdataCreator.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/SubmodelTestdataCreator.java index 7ad12254e0..c8d49342c2 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/SubmodelTestdataCreator.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/SubmodelTestdataCreator.java @@ -30,7 +30,7 @@ import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.apache.commons.lang3.StringUtils; -import org.eclipse.tractusx.irs.common.CxTestDataContainer; +import org.eclipse.tractusx.irs.data.CxTestDataContainer; /** * Class to create Submodel Testdata diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/configuration/JsonLdConfiguration.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/configuration/JsonLdConfiguration.java index e41d5b3f2a..04f1f12904 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/configuration/JsonLdConfiguration.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/configuration/JsonLdConfiguration.java @@ -33,13 +33,14 @@ import org.eclipse.edc.policy.model.LiteralExpression; import org.eclipse.edc.spi.monitor.ConsoleMonitor; import org.eclipse.edc.spi.monitor.Monitor; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * JsonLD configuration and namespace constants. */ -@Configuration +@Configuration("irsEdcClientJsonLdConfiguration") public class JsonLdConfiguration { public static final String NAMESPACE_ODRL = "http://www.w3.org/ns/odrl/2/"; @@ -67,7 +68,9 @@ public class JsonLdConfiguration { return new ConsoleMonitor(); } - @Bean /* package */ ObjectMapper objectMapper() { + @Bean + @Qualifier("jsonLdObjectMapper") + /* package */ ObjectMapper objectMapper() { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); objectMapper.registerModule(new Jdk8Module()); diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/AcceptedPoliciesProvider.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/AcceptedPoliciesProvider.java index 75a77a02a1..d453b29263 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/AcceptedPoliciesProvider.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/AcceptedPoliciesProvider.java @@ -22,11 +22,40 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.edc.client.policy; +import java.util.ArrayList; import java.util.List; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Service; + /** * Provides policies to be accepted during EDC negotiation */ public interface AcceptedPoliciesProvider { List getAcceptedPolicies(); + + /** + * Default provider if no other beans are loaded. + * Can be filled with accepted policies programmatically. + */ + @Service + @ConditionalOnMissingBean(value = AcceptedPoliciesProvider.class, ignored = DefaultAcceptedPoliciesProvider.class) + class DefaultAcceptedPoliciesProvider implements AcceptedPoliciesProvider { + + private final List acceptedPolicies = new ArrayList<>(); + + @Override + public List getAcceptedPolicies() { + return List.copyOf(acceptedPolicies); + } + + public void addAcceptedPolicies(final List policies) { + acceptedPolicies.addAll(policies); + } + + public void removeAcceptedPolicies(final List policies) { + acceptedPolicies.removeAll(policies); + } + } } + diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/PolicyCheckerService.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/PolicyCheckerService.java index c2bc06a989..8e62b525e7 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/PolicyCheckerService.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/policy/PolicyCheckerService.java @@ -34,7 +34,7 @@ import org.eclipse.edc.policy.model.OrConstraint; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.policy.model.Policy; -import org.eclipse.tractusx.irs.edc.client.StringMapper; +import org.eclipse.tractusx.irs.data.StringMapper; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; import org.springframework.web.util.UriUtils; @@ -43,7 +43,7 @@ * Check and validate Policy in Catalog fetch from EDC providers. */ @Slf4j -@Service +@Service("irsEdcClientPolicyCheckerService") @RequiredArgsConstructor public class PolicyCheckerService { diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/transformer/EdcTransformer.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/transformer/EdcTransformer.java index ab9481a330..b6d4b1fad9 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/transformer/EdcTransformer.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/transformer/EdcTransformer.java @@ -67,12 +67,13 @@ import org.eclipse.tractusx.irs.edc.client.model.NegotiationResponse; import org.eclipse.tractusx.irs.edc.client.model.NegotiationState; import org.eclipse.tractusx.irs.edc.client.model.TransferProcessRequest; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** * Transformer to convert between EDC models and JSON-LD. */ -@Component +@Component("irsEdcClientEdcTransformer") @SuppressWarnings("PMD.ExcessiveImports") public class EdcTransformer { private final JsonObjectToCatalogTransformer jsonObjectToCatalogTransformer; @@ -85,7 +86,7 @@ public class EdcTransformer { private final JsonObjectToNegotiationResponseTransformer jsonObjectToNegotiationResponseTransformer; private final JsonObjectToNegotiationStateTransformer jsonObjectToNegotiationStateTransformer; - public EdcTransformer(final ObjectMapper objectMapper, final TitaniumJsonLd titaniumJsonLd) { + public EdcTransformer(@Qualifier("jsonLdObjectMapper") final ObjectMapper objectMapper, final TitaniumJsonLd titaniumJsonLd) { this.titaniumJsonLd = titaniumJsonLd; final JsonBuilderFactory jsonBuilderFactory = Json.createBuilderFactory(Map.of()); diff --git a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/Masker.java b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/util/Masker.java similarity index 97% rename from irs-common/src/main/java/org/eclipse/tractusx/irs/common/Masker.java rename to irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/util/Masker.java index 1a04b8d1ea..e0f2085976 100644 --- a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/Masker.java +++ b/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/util/Masker.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.common; +package org.eclipse.tractusx.irs.edc.client.util; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/CxTestDataAnalyzerTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/CxTestDataAnalyzerTest.java index 80adc23e36..e1c3cf6980 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/CxTestDataAnalyzerTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/CxTestDataAnalyzerTest.java @@ -23,7 +23,7 @@ package org.eclipse.tractusx.irs.edc.client; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.irs.common.CxTestDataContainer.CxTestData.*; +import static org.eclipse.tractusx.irs.data.CxTestDataContainer.CxTestData.*; import java.io.File; import java.io.IOException; @@ -36,7 +36,7 @@ import lombok.Builder; import lombok.extern.slf4j.Slf4j; -import org.eclipse.tractusx.irs.common.CxTestDataContainer; +import org.eclipse.tractusx.irs.data.CxTestDataContainer; import org.eclipse.tractusx.irs.component.Relationship; import org.eclipse.tractusx.irs.component.Submodel; import org.eclipse.tractusx.irs.component.enums.BomLifecycle; 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 374a12ed8a..94caaec2ca 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 @@ -50,12 +50,12 @@ import io.github.resilience4j.retry.RetryRegistry; import org.eclipse.edc.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.data.StringMapper; 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; @@ -95,8 +95,6 @@ class EdcSubmodelClientTest extends LocalTestDataConfigurationAware { @Mock private EDCCatalogFacade catalogFacade; private EdcSubmodelClient testee; - @Mock - private OutboundMeterRegistryService meterRegistry; EdcSubmodelClientTest() throws IOException { super(); @@ -115,7 +113,7 @@ void setUp() { config.getSubmodel().setUrnPrefix("/urn"); config.getSubmodel().setRequestTtl(Duration.ofMinutes(10)); testee = new EdcSubmodelClientImpl(config, contractNegotiationService, edcDataPlaneClient, - endpointDataReferenceStorage, pollingService, meterRegistry, retryRegistry, catalogFacade); + endpointDataReferenceStorage, pollingService, retryRegistry, catalogFacade); } @Test 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 d56cf880c1..4bdd4a8f84 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 @@ -51,7 +51,6 @@ import org.assertj.core.api.ThrowableAssert; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; import org.eclipse.tractusx.irs.edc.client.policy.PolicyCheckerService; import org.junit.jupiter.api.AfterEach; @@ -115,10 +114,9 @@ void configureSystemUnderTest() { final ContractNegotiationService contractNegotiationService = new ContractNegotiationService(controlPlaneClient, policyCheckerService, config); - final OutboundMeterRegistryService meterRegistry = mock(OutboundMeterRegistryService.class); final RetryRegistry retryRegistry = RetryRegistry.ofDefaults(); this.edcSubmodelClient = new EdcSubmodelClientImpl(config, contractNegotiationService, dataPlaneClient, storage, - pollingService, meterRegistry, retryRegistry, catalogFacade); + pollingService, retryRegistry, catalogFacade); } @AfterEach 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 fd4e4f0460..747193fea7 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 @@ -36,7 +36,6 @@ import io.github.resilience4j.retry.RetryRegistry; import io.github.resilience4j.retry.internal.InMemoryRetryRegistry; -import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; import org.eclipse.tractusx.irs.edc.client.policy.PolicyCheckerService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -79,10 +78,8 @@ void setUp() { final EdcDataPlaneClient dataPlaneClient = new EdcDataPlaneClient(restTemplate); final EndpointDataReferenceStorage storage = new EndpointDataReferenceStorage(Duration.ofMinutes(1)); - final OutboundMeterRegistryService meterRegistry = mock(OutboundMeterRegistryService.class); - final EdcSubmodelClient client = new EdcSubmodelClientImpl(config, negotiationService, dataPlaneClient, storage, - pollingService, meterRegistry, retryRegistry, catalogFacade); + pollingService, retryRegistry, catalogFacade); testee = new EdcSubmodelFacade(client); } diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/policy/AcceptedPoliciesProviderTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/policy/AcceptedPoliciesProviderTest.java new file mode 100644 index 0000000000..96031ea2c6 --- /dev/null +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/policy/AcceptedPoliciesProviderTest.java @@ -0,0 +1,66 @@ +/******************************************************************************** + * 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.edc.client.policy; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.OffsetDateTime; +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; + +class AcceptedPoliciesProviderTest { + + private final AcceptedPoliciesProvider.DefaultAcceptedPoliciesProvider testee = new AcceptedPoliciesProvider.DefaultAcceptedPoliciesProvider(); + + @Test + void getAcceptedPolicies() { + final var acceptedPolicies = testee.getAcceptedPolicies(); + + assertThat(acceptedPolicies).isEmpty(); + } + + @Test + void shouldReturnStoredPolicies() { + testee.addAcceptedPolicies(List.of(policy())); + final var acceptedPolicies = testee.getAcceptedPolicies(); + + assertThat(acceptedPolicies).hasSize(1); + } + @Test + void shouldRemoveStoredPolicies() { + testee.addAcceptedPolicies(List.of(policy())); + final var acceptedPolicies = testee.getAcceptedPolicies(); + + assertThat(acceptedPolicies).hasSize(1); + + testee.removeAcceptedPolicies(acceptedPolicies); + + assertThat(testee.getAcceptedPolicies()).isEmpty(); + } + @NotNull + private static AcceptedPolicy policy() { + return new AcceptedPolicy("", OffsetDateTime.now()); + } +} \ No newline at end of file diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/util/MaskerTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/util/MaskerTest.java similarity index 94% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/util/MaskerTest.java rename to irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/util/MaskerTest.java index 5030caea94..3848a35fa2 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/util/MaskerTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/util/MaskerTest.java @@ -20,11 +20,11 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.util; +package org.eclipse.tractusx.irs.edc.client.util; import static org.assertj.core.api.Assertions.assertThat; -import org.eclipse.tractusx.irs.common.Masker; +import org.eclipse.tractusx.irs.edc.client.util.Masker; import org.junit.jupiter.api.Test; class MaskerTest { diff --git a/irs-ess/pom.xml b/irs-ess/pom.xml index c704c2df5c..c400e02936 100644 --- a/irs-ess/pom.xml +++ b/irs-ess/pom.xml @@ -31,6 +31,11 @@ irs-edc-client ${revision} + + org.eclipse.tractusx.irs + irs-common + ${revision} + org.springframework.boot spring-boot-starter diff --git a/irs-ess/src/main/java/org/eclipse/tractusx/ess/service/EdcRegistration.java b/irs-ess/src/main/java/org/eclipse/tractusx/ess/service/EdcRegistration.java index 06e5ae601a..d2dd7a0c57 100644 --- a/irs-ess/src/main/java/org/eclipse/tractusx/ess/service/EdcRegistration.java +++ b/irs-ess/src/main/java/org/eclipse/tractusx/ess/service/EdcRegistration.java @@ -28,7 +28,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.eclipse.tractusx.irs.edc.client.StringMapper; +import org.eclipse.tractusx.irs.data.StringMapper; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; @@ -60,8 +60,8 @@ public class EdcRegistration { public EdcRegistration(@Qualifier("noErrorRestTemplate") final RestTemplate restTemplate, @Value("${ess.localEdcEndpoint}") final String edcProviderUrl, @Value("${ess.irs.url}") final String essBaseUrl, - @Value("${edc.controlplane.api-key.header}") final String apiKeyHeader, - @Value("${edc.controlplane.api-key.secret}") final String apiKeySecret, + @Value("${irs-edc-client.controlplane.api-key.header}") final String apiKeyHeader, + @Value("${irs-edc-client.controlplane.api-key.secret}") final String apiKeySecret, @Value("${ess.managementPath}") final String managementPath) { this.restTemplate = restTemplate; this.edcProviderUrl = edcProviderUrl; diff --git a/irs-integration-tests/pom.xml b/irs-integration-tests/pom.xml index 9333717ffd..8323748a65 100644 --- a/irs-integration-tests/pom.xml +++ b/irs-integration-tests/pom.xml @@ -68,6 +68,10 @@ + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-log4j2 diff --git a/irs-models/pom.xml b/irs-models/pom.xml index f0548be521..3941257471 100644 --- a/irs-models/pom.xml +++ b/irs-models/pom.xml @@ -34,6 +34,7 @@ snakeyaml + provided org.springframework.boot @@ -44,16 +45,23 @@ snakeyaml + provided - org.springdoc - springdoc-openapi-common + org.springframework.boot + spring-boot-starter-web org.yaml snakeyaml + provided + + + io.swagger.core.v3 + swagger-annotations + 2.2.8 @@ -67,12 +75,13 @@ true - io.swagger - swagger-annotations - 1.6.8 - compile + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 - diff --git a/irs-models/src/main/java/org/eclipse/tractusx/irs/component/BatchOrderCreated.java b/irs-models/src/main/java/org/eclipse/tractusx/irs/component/BatchOrderCreated.java index 58f75d73ee..eb275132d8 100644 --- a/irs-models/src/main/java/org/eclipse/tractusx/irs/component/BatchOrderCreated.java +++ b/irs-models/src/main/java/org/eclipse/tractusx/irs/component/BatchOrderCreated.java @@ -24,14 +24,13 @@ import java.util.UUID; -import io.swagger.annotations.ApiModel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; /** * Id of the created Batch order */ -@ApiModel(description = "Id of the created Batch order.") +@Schema(description = "Id of the created Batch order.") @Builder @SuppressWarnings("PMD.ShortVariable") public record BatchOrderCreated(@Schema(description = "Id of the Batch Order.", implementation = UUID.class) UUID id) { diff --git a/irs-models/src/main/java/org/eclipse/tractusx/irs/component/JobHandle.java b/irs-models/src/main/java/org/eclipse/tractusx/irs/component/JobHandle.java index a5d8743a38..977cde40ae 100644 --- a/irs-models/src/main/java/org/eclipse/tractusx/irs/component/JobHandle.java +++ b/irs-models/src/main/java/org/eclipse/tractusx/irs/component/JobHandle.java @@ -25,7 +25,6 @@ import java.util.UUID; import com.fasterxml.jackson.annotation.JsonAlias; -import io.swagger.annotations.ApiModel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Value; @@ -34,7 +33,7 @@ /** * The unique jobId handle of the just processed job. */ -@ApiModel(description = "The unique jobId handle of the just processed job.") +@Schema(description = "The unique jobId handle of the just processed job.") @Value @Jacksonized @Builder(toBuilder = true) diff --git a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/CxTestDataContainer.java b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/CxTestDataContainer.java similarity index 99% rename from irs-common/src/main/java/org/eclipse/tractusx/irs/common/CxTestDataContainer.java rename to irs-models/src/main/java/org/eclipse/tractusx/irs/data/CxTestDataContainer.java index 13a863e6d8..5f22c559cb 100644 --- a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/CxTestDataContainer.java +++ b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/CxTestDataContainer.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.common; +package org.eclipse.tractusx.irs.data; import java.util.List; import java.util.Map; diff --git a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/JsonParseException.java b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/JsonParseException.java similarity index 96% rename from irs-common/src/main/java/org/eclipse/tractusx/irs/common/JsonParseException.java rename to irs-models/src/main/java/org/eclipse/tractusx/irs/data/JsonParseException.java index 85e0a4773e..2faecbc1e0 100644 --- a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/JsonParseException.java +++ b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/JsonParseException.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.common; +package org.eclipse.tractusx.irs.data; /** * Exception when parsing JSON diff --git a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/LocalTestDataConfiguration.java b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/LocalTestDataConfiguration.java similarity index 98% rename from irs-common/src/main/java/org/eclipse/tractusx/irs/common/LocalTestDataConfiguration.java rename to irs-models/src/main/java/org/eclipse/tractusx/irs/data/LocalTestDataConfiguration.java index bd5d8a4348..4204282294 100644 --- a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/LocalTestDataConfiguration.java +++ b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/LocalTestDataConfiguration.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.common; +package org.eclipse.tractusx.irs.data; import java.io.IOException; diff --git a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/StringMapper.java b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/StringMapper.java similarity index 96% rename from irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/StringMapper.java rename to irs-models/src/main/java/org/eclipse/tractusx/irs/data/StringMapper.java index c1dd44ed1a..b4ea354379 100644 --- a/irs-edc-client/src/main/java/org/eclipse/tractusx/irs/edc/client/StringMapper.java +++ b/irs-models/src/main/java/org/eclipse/tractusx/irs/data/StringMapper.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.edc.client; +package org.eclipse.tractusx.irs.data; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -31,7 +31,6 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.eclipse.tractusx.irs.common.JsonParseException; /** * Maps objects to strings and vice-versa. diff --git a/irs-common/src/main/resources/test_data/CX_Testdata.json b/irs-models/src/main/resources/test_data/CX_Testdata.json similarity index 100% rename from irs-common/src/main/resources/test_data/CX_Testdata.json rename to irs-models/src/main/resources/test_data/CX_Testdata.json diff --git a/irs-registry-client/README.md b/irs-registry-client/README.md new file mode 100644 index 0000000000..6a9c3deff0 --- /dev/null +++ b/irs-registry-client/README.md @@ -0,0 +1,107 @@ +# Digital Twin Registry Client Library + +This library assists in communicating with the Digital Twin Registry in a central or decentral approach. + +In the decentral approach, it also handles the communication via the Discovery Finder and EDC. + +The library is based on Spring Boot and uses its configuration features. + +## Usage + +### Auto setup + +Include the library into your project: + +``` + + + github + GitHub Packages + https://maven.pkg.github.com/catenax-ng/tx-item-relationship-service + + + + + + org.eclipse.tractusx.irs + irs-registry-client + 1.0.0-SNAPSHOT + + +``` +**Note**: Since the library is currently only available on GitHub Packages, you need to provide a personal access token (PAT) for local builds. Update your Maven settings.xml (usually located at ~/.m2/settings.xml) like this: +``` + + + github + enter-your-github-username + enter-your-generated-personal-access-token + + +``` + +Add the following configuration to your `application.yaml`: + +```yaml +digitalTwinRegistryClient: + type: "central" # or "decentral" + + discoveryFinderUrl: "" # required if type is "decentral" + + descriptorEndpoint: "" # required if type is "central", must contain the placeholder {aasIdentifier} + shellLookupEndpoint: "" # required if type is "central", must contain the placeholder {assetIds} + +irs-edc-client: + callback-url: "" # The URL where the EDR token callback will be sent to. This defaults to {BASE_URL}/internal/endpoint-data-reference. If you want to use a different mapping, you can override it with irs-edc-client.callback.mapping. + controlplane: + request-ttl: PT10M # How long to wait for an async EDC negotiation request to finish, ISO 8601 Duration + endpoint: + data: "" # URL of the EDC consumer controlplane data endpoint + catalog: /v2/catalog/request # EDC consumer controlplane catalog path + contract-negotiation: /v2/contractnegotiations # EDC consumer controlplane contract negotiation path + transfer-process: /v2/transferprocesses # EDC consumer controlplane transfer process path + state-suffix: /state # Path of the state suffix for contract negotiation and transfer process + provider-suffix: /api/v1/dsp # Suffix to add to data requests to the EDC provider controlplane + catalog-limit: 1000 # Max number of items to fetch from the EDC provider catalog + catalog-page-size: 50 # Number of items to fetch at one page from the EDC provider catalog when using pagination + api-key: + header: "" # API header key to use in communication with the EDC consumer controlplane + secret: "" # API header secret to use in communication with the EDC consumer controlplane + datareference: + storage: + duration: PT1H # Time after which stored data references will be cleaned up, ISO 8601 Duration + + submodel: + request-ttl: PT10M # How long to wait for an async EDC submodel retrieval to finish, ISO 8601 Duration + path: /submodel # The path to append to the submodel data reference endpoint + urn-prefix: /urn # A prefix used to identify URNs correctly in the submodel endpoint address + + + catalog: + cache: + enabled: false # Set to false to disable caching + ttl: P1D # Time after which a cached Item is no longer valid and the real catalog is called instead + maxCachedItems: 64000 # Maximum amount of cached catalog items + +``` + +Please note that you also need to provide a `RestTemplate` bean for the **Qualifier** `digitalTwinRegistryRestTemplate` (central approach) or `edcClientRestTemplate` (decentral approach). + +You also need to tell the EDC client which policies are acceptable. You can either implement a bean with the interface `org.eclipse.tractusx.irs.edc.client.policy.AcceptedPoliciesProvider` or use the fallback `org.eclipse.tractusx.irs.edc.client.policy.AcceptedPoliciesProvider.DefaultAcceptedPoliciesProvider` bean directly and add the accepted policies there. + +As a last step, add this annotation to your Application class: + +``` +@ComponentScan({ "", + "org.eclipse.tractusx.irs.registryclient", + "org.eclipse.tractusx.irs.edc.client" +}) +``` + +Now you can start using the client by injecting a bean of the `DigitalTwinRegistryService` interface. Depending on the configured mode, it will be central or decentral. + +### Manual setup + +You can set up the beans by yourself. This can be useful if you want to override some default implementations or +programmatically provide the right dependencies. Please refer to +the `org.eclipse.tractusx.irs.registryclient.DefaultConfiguration` for an example. \ No newline at end of file diff --git a/irs-registry-client/pom.xml b/irs-registry-client/pom.xml new file mode 100644 index 0000000000..50ecb0c717 --- /dev/null +++ b/irs-registry-client/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + + org.eclipse.tractusx.irs + irs-parent-spring-boot + ${revision} + ../irs-parent-spring-boot + + + irs-registry-client + Digital Twin Registry Client + 1.0.0-SNAPSHOT + Client library to easily talk to the DTR + + + + org.eclipse.tractusx.irs + irs-edc-client + ${revision} + + + org.eclipse.tractusx.irs + irs-models + ${revision} + + + org.projectlombok + lombok + true + + + io.github.resilience4j + resilience4j-annotations + 2.0.2 + + + org.apache.commons + commons-lang3 + 3.12.0 + + + org.springframework.boot + spring-boot-starter-web + provided + + + org.yaml + snakeyaml + 2.0 + + + org.eclipse.tractusx.irs + irs-testing + ${revision} + test + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DefaultConfiguration.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DefaultConfiguration.java new file mode 100644 index 0000000000..177b9442eb --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DefaultConfiguration.java @@ -0,0 +1,126 @@ +/******************************************************************************** + * 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.registryclient; + +import java.time.Clock; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade; +import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; +import org.eclipse.tractusx.irs.registryclient.central.CentralDigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.central.DigitalTwinRegistryClient; +import org.eclipse.tractusx.irs.registryclient.central.DigitalTwinRegistryClientImpl; +import org.eclipse.tractusx.irs.registryclient.decentral.DecentralDigitalTwinRegistryClient; +import org.eclipse.tractusx.irs.registryclient.decentral.DecentralDigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.decentral.EdcRetrieverException; +import org.eclipse.tractusx.irs.registryclient.decentral.EndpointDataForConnectorsService; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderClient; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderClientImpl; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * IRS configuration settings. Sets up the digital twin registry client. + */ +@Configuration +public class DefaultConfiguration { + + public static final String DIGITAL_TWIN_REGISTRY_REST_TEMPLATE = "digitalTwinRegistryRestTemplate"; + public static final String EDC_REST_TEMPLATE = "edcRestTemplate"; + private static final String CONFIG_PREFIX = "digitalTwinRegistryClient"; + private static final String CONFIG_FIELD_TYPE = "type"; + private static final String CONFIG_VALUE_DECENTRAL = "decentral"; + private static final String CONFIG_VALUE_CENTRAL = "central"; + private static final int POOL_SIZE = 20; + + @Bean + @ConditionalOnProperty(prefix = CONFIG_PREFIX, name = CONFIG_FIELD_TYPE, havingValue = CONFIG_VALUE_CENTRAL) + public CentralDigitalTwinRegistryService centralDigitalTwinRegistryService(final DigitalTwinRegistryClient client) { + return new CentralDigitalTwinRegistryService(client); + } + + @Bean + @ConditionalOnProperty(prefix = CONFIG_PREFIX, name = CONFIG_FIELD_TYPE, havingValue = CONFIG_VALUE_CENTRAL) + public DigitalTwinRegistryClient digitalTwinRegistryClientImpl( + @Qualifier(DIGITAL_TWIN_REGISTRY_REST_TEMPLATE) final RestTemplate restTemplate, + @Value("${digitalTwinRegistryClient.descriptorEndpoint:}") final String descriptorEndpoint, + @Value("${digitalTwinRegistryClient.shellLookupEndpoint:}") final String shellLookupEndpoint) { + return new DigitalTwinRegistryClientImpl(restTemplate, descriptorEndpoint, shellLookupEndpoint); + } + + @Bean + @ConditionalOnProperty(prefix = CONFIG_PREFIX, name = CONFIG_FIELD_TYPE, havingValue = CONFIG_VALUE_DECENTRAL) + public DecentralDigitalTwinRegistryService decentralDigitalTwinRegistryService( + final DiscoveryFinderClient discoveryFinderClient, + final EndpointDataForConnectorsService endpointDataForConnectorsService, + final DecentralDigitalTwinRegistryClient decentralDigitalTwinRegistryClient) { + return new DecentralDigitalTwinRegistryService(discoveryFinderClient, endpointDataForConnectorsService, + decentralDigitalTwinRegistryClient); + } + + @Bean + @ConditionalOnProperty(prefix = CONFIG_PREFIX, name = CONFIG_FIELD_TYPE, havingValue = CONFIG_VALUE_DECENTRAL) + public DiscoveryFinderClient discoveryFinderClient( + @Qualifier(DIGITAL_TWIN_REGISTRY_REST_TEMPLATE) final RestTemplate dtrRestTemplate, + @Value("${digitalTwinRegistryClient.discoveryFinderUrl:}") final String finderUrl) { + return new DiscoveryFinderClientImpl(finderUrl, dtrRestTemplate); + } + + @Bean + @ConditionalOnProperty(prefix = CONFIG_PREFIX, name = CONFIG_FIELD_TYPE, havingValue = CONFIG_VALUE_DECENTRAL) + public EndpointDataForConnectorsService endpointDataForConnectorsService(final EdcSubmodelFacade facade) { + return new EndpointDataForConnectorsService((edcConnectorEndpoint, assetType, assetValue) -> { + try { + return facade.getEndpointReferenceForAsset(edcConnectorEndpoint, assetType, assetValue); + } catch (EdcClientException e) { + throw new EdcRetrieverException(e); + } + }); + } + + @Bean + @ConditionalOnProperty(prefix = CONFIG_PREFIX, name = CONFIG_FIELD_TYPE, havingValue = CONFIG_VALUE_DECENTRAL) + public DecentralDigitalTwinRegistryClient decentralDigitalTwinRegistryClient( + @Qualifier(EDC_REST_TEMPLATE) final RestTemplate edcRestTemplate) { + return new DecentralDigitalTwinRegistryClient(edcRestTemplate); + } + + @Bean + @ConditionalOnMissingBean(Clock.class) + public Clock clock() { + return Clock.systemUTC(); + } + + @Bean + @ConditionalOnMissingBean(ScheduledExecutorService.class) + public ScheduledExecutorService scheduledExecutorService() { + return Executors.newScheduledThreadPool(POOL_SIZE); + } + +} diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryKey.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DigitalTwinRegistryKey.java similarity index 95% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryKey.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DigitalTwinRegistryKey.java index 5f92a284b8..17be0c3c5c 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryKey.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DigitalTwinRegistryKey.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient; /** * Key object contains required attributes for identify part chain entry node diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryService.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DigitalTwinRegistryService.java similarity index 64% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryService.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DigitalTwinRegistryService.java index c6ee24adc1..087d32f8b9 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryService.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/DigitalTwinRegistryService.java @@ -20,9 +20,12 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient; + +import java.util.Collection; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; /** * Public API Service for digital twin registry domain @@ -30,12 +33,19 @@ public interface DigitalTwinRegistryService { /** - * Retrieves {@link AssetAdministrationShellDescriptor} from Digital Twin Registry Service. - * As a first step id of shell is being retrieved by DigitalTwinRegistryKey. + * Retrieves all registered shell identifiers for a given BPN. * - * @param key The Asset Administration Shell's DigitalTwinRegistryKey - * @return AAShell + * @param bpn the BPN to retrieve the shells for + * @return the collection of shell identifiers */ - AssetAdministrationShellDescriptor getAAShellDescriptor(DigitalTwinRegistryKey key); + Collection lookupShells(String bpn) throws RegistryServiceException; + /** + * Retrieves the shell details for the given identifiers. + * + * @param identifiers the shell identifiers + * @return the shell descriptors + */ + Collection fetchShells(Collection identifiers) + throws RegistryServiceException; } diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/AssetAdministrationShellTestdataCreator.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/AssetAdministrationShellTestdataCreator.java similarity index 98% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/AssetAdministrationShellTestdataCreator.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/AssetAdministrationShellTestdataCreator.java index 1ec8dfb149..20068e903c 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/AssetAdministrationShellTestdataCreator.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/AssetAdministrationShellTestdataCreator.java @@ -20,13 +20,13 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.central; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import org.eclipse.tractusx.irs.common.CxTestDataContainer; +import org.eclipse.tractusx.irs.data.CxTestDataContainer; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; import org.eclipse.tractusx.irs.component.assetadministrationshell.Endpoint; import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/CentralDigitalTwinRegistryService.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/CentralDigitalTwinRegistryService.java similarity index 62% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/CentralDigitalTwinRegistryService.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/CentralDigitalTwinRegistryService.java index 62849e03d4..500fefac53 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/CentralDigitalTwinRegistryService.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/CentralDigitalTwinRegistryService.java @@ -20,8 +20,9 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.central; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -29,14 +30,13 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Service; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryKey; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; /** * Central implementation of DigitalTwinRegistryService */ -@Service -@ConditionalOnProperty(prefix = "digitalTwinRegistry", name = "type", havingValue = "central") @RequiredArgsConstructor @Slf4j public class CentralDigitalTwinRegistryService implements DigitalTwinRegistryService { @@ -44,18 +44,29 @@ public class CentralDigitalTwinRegistryService implements DigitalTwinRegistrySer private final DigitalTwinRegistryClient digitalTwinRegistryClient; @Override - public AssetAdministrationShellDescriptor getAAShellDescriptor(final DigitalTwinRegistryKey key) { - final String aaShellIdentification = getAAShellIdentificationOrGlobalAssetId(key.globalAssetId()); - log.info("Retrieved AAS Identification {} for globalAssetId {}", aaShellIdentification, key.globalAssetId()); + public Collection fetchShells(final Collection keys) { + return keys.stream().map(key -> { + final String aaShellIdentification = getAAShellIdentificationOrGlobalAssetId(key.globalAssetId()); + log.info("Retrieved AAS Identification {} for globalAssetId {}", aaShellIdentification, + key.globalAssetId()); - return digitalTwinRegistryClient.getAssetAdministrationShellDescriptor(aaShellIdentification); + return digitalTwinRegistryClient.getAssetAdministrationShellDescriptor(aaShellIdentification); + }).toList(); + } + + @Override + public Collection lookupShells(final String bpn) throws RegistryServiceException { + log.info("Looking up shells for bpn {}", bpn); + final var shellIds = digitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(List.of()); + log.info("Found {} shells in total", shellIds.size()); + return shellIds.stream().map(id -> new DigitalTwinRegistryKey(id, bpn)).toList(); } private String getAAShellIdentificationOrGlobalAssetId(final String globalAssetId) { final IdentifierKeyValuePair identifierKeyValuePair = IdentifierKeyValuePair.builder() - .key("globalAssetId") - .value(globalAssetId) - .build(); + .key("globalAssetId") + .value(globalAssetId) + .build(); final List allAssetAdministrationShellIdsByAssetLink = digitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink( Collections.singletonList(identifierKeyValuePair)); diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClient.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClient.java new file mode 100644 index 0000000000..c51faa9c9b --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClient.java @@ -0,0 +1,51 @@ +/******************************************************************************** + * 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.registryclient.central; + +import java.util.List; + +import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; +import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; + +/** + * Digital Twin Registry Rest Client + */ +public interface DigitalTwinRegistryClient { + + /** + * @param aasIdentifier The Asset Administration Shell’s unique id + * @return Returns a specific Asset Administration Shell Descriptor + */ + AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor(String aasIdentifier); + + /** + * Returns a list of Asset Administration Shell ids based on Asset identifier key-value-pairs. + * Only the Shell ids are returned when all provided key-value pairs match. + * + * @param assetIds The key-value-pair of an Asset identifier + * @return urn uuid string list + */ + List getAllAssetAdministrationShellIdsByAssetLink(List assetIds); + +} + diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryClient.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientImpl.java similarity index 53% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryClient.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientImpl.java index a4b3a5f21c..d7b9aa9081 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryClient.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientImpl.java @@ -20,101 +20,39 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.central; -import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DTR_REST_TEMPLATE; - -import java.net.SocketTimeoutException; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import io.github.resilience4j.retry.annotation.Retry; import org.apache.commons.lang3.StringUtils; -import org.eclipse.tractusx.irs.common.CxTestDataContainer; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; -import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; -import org.eclipse.tractusx.irs.util.JsonUtil; -import org.springframework.beans.factory.annotation.Qualifier; +import org.eclipse.tractusx.irs.data.StringMapper; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Service; -import org.springframework.web.client.ResourceAccessException; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; -/** - * Digital Twin Registry Rest Client - */ -interface DigitalTwinRegistryClient { - - /** - * @param aasIdentifier The Asset Administration Shell’s unique id - * @return Returns a specific Asset Administration Shell Descriptor - */ - AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor(String aasIdentifier); - - /** - * Returns a list of Asset Administration Shell ids based on Asset identifier key-value-pairs. - * Only the Shell ids are returned when all provided key-value pairs match. - * - * @param assetIds The key-value-pair of an Asset identifier - * @return urn uuid string list - */ - List getAllAssetAdministrationShellIdsByAssetLink(List assetIds); - -} - -/** - * Digital Twin Registry Rest Client Stub used in local environment - */ -@Service -@Profile({ "local", - "stubtest" -}) -class DigitalTwinRegistryClientLocalStub implements DigitalTwinRegistryClient { - - private final AssetAdministrationShellTestdataCreator testdataCreator; - - /* package */ DigitalTwinRegistryClientLocalStub(final CxTestDataContainer cxTestDataContainer) { - this.testdataCreator = new AssetAdministrationShellTestdataCreator(cxTestDataContainer); - } - - @Override - public AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor(final String aasIdentifier) { - return testdataCreator.createDummyAssetAdministrationShellDescriptorForId(aasIdentifier); - } - - @Override - public List getAllAssetAdministrationShellIdsByAssetLink(final List assetIds) { - return Collections.emptyList(); - } -} - /** * Digital Twin Registry Rest Client Implementation */ -@Service -@Profile({ "!local && !stubtest" }) -class DigitalTwinRegistryClientImpl implements DigitalTwinRegistryClient { +public class DigitalTwinRegistryClientImpl implements DigitalTwinRegistryClient { private static final String PLACEHOLDER_AAS_IDENTIFIER = "aasIdentifier"; private static final String PLACEHOLDER_ASSET_IDS = "assetIds"; private final RestTemplate restTemplate; private final String descriptorEndpoint; private final String shellLookupEndpoint; - private final OutboundMeterRegistryService meterRegistryService; - /* package */ DigitalTwinRegistryClientImpl(@Qualifier(DTR_REST_TEMPLATE) final RestTemplate restTemplate, + public DigitalTwinRegistryClientImpl(final RestTemplate restTemplate, @Value("${digitalTwinRegistry.descriptorEndpoint:}") final String descriptorEndpoint, - @Value("${digitalTwinRegistry.shellLookupEndpoint:}") final String shellLookupEndpoint, - final OutboundMeterRegistryService meterRegistryService) { + @Value("${digitalTwinRegistry.shellLookupEndpoint:}") final String shellLookupEndpoint) { this.restTemplate = restTemplate; this.descriptorEndpoint = descriptorEndpoint; this.shellLookupEndpoint = shellLookupEndpoint; - this.meterRegistryService = meterRegistryService; ensureUrlContainsPlaceholders(descriptorEndpoint, "digitalTwinRegistry.descriptorEndpoint", PLACEHOLDER_AAS_IDENTIFIER); @@ -148,27 +86,17 @@ private static String wrap(final String placeholderIdType) { public AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor(final String aasIdentifier) { final UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(descriptorEndpoint); final Map values = Map.of(PLACEHOLDER_AAS_IDENTIFIER, aasIdentifier); - return execute( - () -> restTemplate.getForObject(uriBuilder.build(values), AssetAdministrationShellDescriptor.class)); + return restTemplate.getForObject(uriBuilder.build(values), AssetAdministrationShellDescriptor.class); } @Override @Retry(name = "registry") public List getAllAssetAdministrationShellIdsByAssetLink(final List assetIds) { final UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(shellLookupEndpoint); - final var values = Map.of(PLACEHOLDER_ASSET_IDS, new JsonUtil().asString(assetIds)); - return execute(() -> restTemplate.getForObject(uriBuilder.build(values), List.class)); - } - - private T execute(final Supplier supplier) { - try { - return supplier.get(); - } catch (ResourceAccessException e) { - if (e.getCause() instanceof SocketTimeoutException) { - meterRegistryService.incrementRegistryTimeoutCounter(); - } - throw e; - } + final var values = Map.of(PLACEHOLDER_ASSET_IDS, StringMapper.mapToString(assetIds)); + return restTemplate.exchange(uriBuilder.build(values), HttpMethod.GET, null, + new ParameterizedTypeReference>() { + }).getBody(); } } diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientLocalStub.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientLocalStub.java new file mode 100644 index 0000000000..c299324403 --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientLocalStub.java @@ -0,0 +1,58 @@ +/******************************************************************************** + * 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.registryclient.central; + +import java.util.Collections; +import java.util.List; + +import org.eclipse.tractusx.irs.data.CxTestDataContainer; +import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; +import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +/** + * Digital Twin Registry Rest Client Stub used in local environment + */ +@Service +@Profile({ "local", + "stubtest" +}) +class DigitalTwinRegistryClientLocalStub implements DigitalTwinRegistryClient { + + private final AssetAdministrationShellTestdataCreator testdataCreator; + + /* package */ DigitalTwinRegistryClientLocalStub(final CxTestDataContainer cxTestDataContainer) { + this.testdataCreator = new AssetAdministrationShellTestdataCreator(cxTestDataContainer); + } + + @Override + public AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor(final String aasIdentifier) { + return testdataCreator.createDummyAssetAdministrationShellDescriptorForId(aasIdentifier); + } + + @Override + public List getAllAssetAdministrationShellIdsByAssetLink(final List assetIds) { + return Collections.emptyList(); + } +} diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryClient.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClient.java similarity index 92% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryClient.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClient.java index 3320401189..a663301f32 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryClient.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClient.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.decentral; import java.util.List; import java.util.Map; @@ -30,19 +30,18 @@ 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.util.JsonUtil; +import org.eclipse.tractusx.irs.data.StringMapper; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; -import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; /** * Digital Twin Registry Rest Client */ -@Service @RequiredArgsConstructor public class DecentralDigitalTwinRegistryClient { @@ -68,9 +67,10 @@ public List getAllAssetAdministrationShellIdsByAssetLink(final EndpointD final List assetIds) { final String shellLookupEndpoint = endpointDataReference.getEndpoint() + LOOKUP_SHELLS_TEMPLATE; final UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(shellLookupEndpoint); - final var values = Map.of(PLACEHOLDER_ASSET_IDS, new JsonUtil().asString(assetIds)); + final var values = Map.of(PLACEHOLDER_ASSET_IDS, StringMapper.mapToString(assetIds)); return edcRestTemplate.exchange(uriBuilder.build(values), HttpMethod.GET, - new HttpEntity<>(null, headers(endpointDataReference)), List.class).getBody(); + new HttpEntity<>(null, headers(endpointDataReference)), new ParameterizedTypeReference>() { + }).getBody(); } private HttpHeaders headers(final EndpointDataReference dataReference) { 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 new file mode 100644 index 0000000000..b6487adb8e --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryService.java @@ -0,0 +1,127 @@ +/******************************************************************************** + * 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.registryclient.decentral; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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.registryclient.DigitalTwinRegistryKey; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryEndpoint; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderClient; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderRequest; +import org.eclipse.tractusx.irs.registryclient.discovery.EdcDiscoveryResult; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; +import org.eclipse.tractusx.irs.registryclient.exceptions.ShellNotFoundException; +import org.jetbrains.annotations.NotNull; + +/** + * Decentral implementation of DigitalTwinRegistryService + */ +@RequiredArgsConstructor +@Slf4j +public class DecentralDigitalTwinRegistryService implements DigitalTwinRegistryService { + + private final DiscoveryFinderClient discoveryFinderClient; + private final EndpointDataForConnectorsService endpointDataForConnectorsService; + private final DecentralDigitalTwinRegistryClient decentralDigitalTwinRegistryClient; + + @Override + public Collection fetchShells(final Collection keys) + throws RegistryServiceException { + final Set calledEndpoints = new HashSet<>(); + + final var shells = keys.stream().map(key -> { + log.info("Retrieved AAS Identification for DigitalTwinRegistryKey: {}", key); + final List connectorEndpoints = getConnectorEndpoints(key.bpn()); + calledEndpoints.addAll(connectorEndpoints); + final EndpointDataReference endpointDataReference = getEndpointDataReference(connectorEndpoints); + final IdentifierKeyValuePair identifierKeyValuePair = IdentifierKeyValuePair.builder() + .key("globalAssetId") + .value(key.globalAssetId()) + .build(); + final String aaShellIdentification = decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink( + endpointDataReference, List.of(identifierKeyValuePair)) + .stream() + .findFirst() + .orElse(key.globalAssetId()); + log.info("Retrieved AAS Identification {} for globalAssetId {}", aaShellIdentification, + key.globalAssetId()); + + return decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(endpointDataReference, + aaShellIdentification); + }).toList(); + + if (shells.isEmpty()) { + throw new ShellNotFoundException("Unable to find any of the requested shells", calledEndpoints); + } else { + return shells; + } + } + + @NotNull + private EndpointDataReference getEndpointDataReference(final List connectorEndpoints) { + return endpointDataForConnectorsService.findEndpointDataForConnectors(connectorEndpoints); + } + + @NotNull + private List getConnectorEndpoints(final String bpn) { + log.info("Requesting connector endpoints for BPN {}", bpn); + final DiscoveryFinderRequest onlyBpn = new DiscoveryFinderRequest(List.of("bpn")); + final List providedBpn = List.of(bpn); + final List discoveryEndpoints = discoveryFinderClient.findDiscoveryEndpoints(onlyBpn) + .endpoints(); + final var endpoints = discoveryEndpoints.stream() + .flatMap( + discoveryEndpoint -> discoveryFinderClient.findConnectorEndpoints( + discoveryEndpoint.endpointAddress(), providedBpn) + .stream() + .filter(edcDiscoveryResult -> edcDiscoveryResult.bpn() + .equals(bpn)) + .map(EdcDiscoveryResult::connectorEndpoint)) + .flatMap(List::stream) + .toList(); + log.info("Discovered the following endpoints for BPN {}: {}", bpn, String.join(", ", endpoints)); + return endpoints; + } + + @Override + public Collection lookupShells(final String bpn) throws RegistryServiceException { + log.info("Looking up shells for bpn {}", bpn); + final var connectorEndpoints = getConnectorEndpoints(bpn); + final var endpointDataReference = getEndpointDataReference(connectorEndpoints); + final var shellIds = decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink( + endpointDataReference, + List.of(IdentifierKeyValuePair.builder().key("manufacturerId").value(bpn).build())); + log.info("Found {} shells in total", shellIds.size()); + return shellIds.stream().map(id -> new DigitalTwinRegistryKey(id, bpn)).toList(); + } + +} diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EdcEndpointReferenceRetriever.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EdcEndpointReferenceRetriever.java new file mode 100644 index 0000000000..829aace4fb --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EdcEndpointReferenceRetriever.java @@ -0,0 +1,42 @@ +/******************************************************************************** + * 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.registryclient.decentral; + +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; + +/** + * Interface for EDC endpoint reference retrieval + */ +public interface EdcEndpointReferenceRetriever { + + /** + * Retrieves the EDC endpoint reference from the specified connector endpoint and asset combination + * @param edcConnectorEndpoint the endpoint URL + * @param assetType the asset type id + * @param assetValue the asset type value + * @return the endpoint data reference + * @throws EdcRetrieverException on any EDC errors + */ + EndpointDataReference getEndpointReferenceForAsset(String edcConnectorEndpoint, String assetType, String assetValue) + throws EdcRetrieverException; +} diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EdcRetrieverException.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EdcRetrieverException.java new file mode 100644 index 0000000000..5a9a7c58d3 --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EdcRetrieverException.java @@ -0,0 +1,32 @@ +/******************************************************************************** + * 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.registryclient.decentral; + +/** + * Thrown in case of error in EDC communication + */ +public class EdcRetrieverException extends Exception { + public EdcRetrieverException(final Throwable cause) { + super(cause); + } +} diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EndpointDataForConnectorsService.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EndpointDataForConnectorsService.java similarity index 72% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EndpointDataForConnectorsService.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EndpointDataForConnectorsService.java index 61a492edd3..459f4aed16 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EndpointDataForConnectorsService.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/decentral/EndpointDataForConnectorsService.java @@ -20,23 +20,19 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.decentral; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade; -import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; -import org.springframework.stereotype.Service; import org.springframework.web.client.RestClientException; /** * Service that use edc client to make calls to edc connector endpoints * to find DigitalTwinRegistry asset */ -@Service @Slf4j @RequiredArgsConstructor public class EndpointDataForConnectorsService { @@ -44,18 +40,21 @@ public class EndpointDataForConnectorsService { private static final String DT_REGISTRY_ASSET_TYPE = "https://w3id.org/edc/v0.0.1/ns/type"; private static final String DT_REGISTRY_ASSET_VALUE = "data.core.digitalTwinRegistry"; - private final EdcSubmodelFacade edcSubmodelFacade; + private final EdcEndpointReferenceRetriever edcSubmodelFacade; - /* package */ EndpointDataReference findEndpointDataForConnectors(final List connectorEndpoints) { + public EndpointDataReference findEndpointDataForConnectors(final List connectorEndpoints) { for (final String connector : connectorEndpoints) { + log.info("Trying to retrieve EndpointDataReference for connector {}", connector); try { - return edcSubmodelFacade.getEndpointReferenceForAsset( - connector, DT_REGISTRY_ASSET_TYPE, DT_REGISTRY_ASSET_VALUE); - } catch (EdcClientException e) { - log.warn("Exception occurred when retrieving EndpointDataReference from " + connector); + return edcSubmodelFacade.getEndpointReferenceForAsset(connector, DT_REGISTRY_ASSET_TYPE, + DT_REGISTRY_ASSET_VALUE); + } catch (EdcRetrieverException e) { + log.warn("Exception occurred when retrieving EndpointDataReference from connector {}", connector, e); } } - throw new RestClientException("EndpointDataReference was not found. Requested connectorEndpoints: " + String.join(", ", connectorEndpoints)); + throw new RestClientException( + "EndpointDataReference was not found. Requested connectorEndpoints: " + String.join(", ", + connectorEndpoints)); } } diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryEndpoint.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryEndpoint.java similarity index 95% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryEndpoint.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryEndpoint.java index 12c46abe0a..632eda77c3 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryEndpoint.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryEndpoint.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.discovery; /** * A single Discovery Endpoint. diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClient.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClient.java new file mode 100644 index 0000000000..ad1a6916f8 --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClient.java @@ -0,0 +1,37 @@ +/******************************************************************************** + * 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.registryclient.discovery; + +import java.util.List; + +/** + * + */ +public interface DiscoveryFinderClient { + + DiscoveryResponse findDiscoveryEndpoints(DiscoveryFinderRequest request); + + List findConnectorEndpoints(String endpointAddress, List bpns); + +} + diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClient.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClientImpl.java similarity index 71% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClient.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClientImpl.java index eb0ff504a5..c90c0e717c 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClient.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClientImpl.java @@ -20,42 +20,25 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; - -import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DTR_REST_TEMPLATE; +package org.eclipse.tractusx.irs.registryclient.discovery; import java.util.List; import io.github.resilience4j.retry.annotation.Retry; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; /** * */ -public interface DiscoveryFinderClient { - - DiscoveryResponse findDiscoveryEndpoints(DiscoveryFinderRequest request); - - List findConnectorEndpoints(String endpointAddress, List bpns); - -} - -/** - * - */ -@Service -class DiscoveryFinderClientImpl implements DiscoveryFinderClient { +public class DiscoveryFinderClientImpl implements DiscoveryFinderClient { private final String discoveryFinderUrl; private final RestTemplate restTemplate; - /* package */ DiscoveryFinderClientImpl( - @Value("${digitalTwinRegistry.discoveryFinderUrl:}") final String discoveryFinderUrl, - @Qualifier(DTR_REST_TEMPLATE) final RestTemplate restTemplate) { + public DiscoveryFinderClientImpl( + final String discoveryFinderUrl, + final RestTemplate restTemplate) { this.discoveryFinderUrl = discoveryFinderUrl; this.restTemplate = restTemplate; } diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderRequest.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderRequest.java similarity index 95% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderRequest.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderRequest.java index eae60895ec..3d5800abeb 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderRequest.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderRequest.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.discovery; import java.util.List; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryResponse.java similarity index 95% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryResponse.java index 03423dec69..118be8f2a8 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryResponse.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryResponse.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.discovery; import java.util.List; diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EdcDiscoveryResult.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/EdcDiscoveryResult.java similarity index 95% rename from irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EdcDiscoveryResult.java rename to irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/EdcDiscoveryResult.java index e25fd791fd..69a558b8ce 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EdcDiscoveryResult.java +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/EdcDiscoveryResult.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.discovery; import java.util.List; diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/LocalDataDiscovery.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/LocalDataDiscovery.java new file mode 100644 index 0000000000..00f7e469d5 --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/discovery/LocalDataDiscovery.java @@ -0,0 +1,54 @@ +/******************************************************************************** + * 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.registryclient.discovery; + +import java.util.List; +import java.util.Map; + +import lombok.RequiredArgsConstructor; + +/** + * Alternative discovery client which uses local data instead. + */ +@RequiredArgsConstructor +public class LocalDataDiscovery implements DiscoveryFinderClient { + + private final Map bpnToEdcMapping; + + @Override + public DiscoveryResponse findDiscoveryEndpoints(final DiscoveryFinderRequest request) { + return new DiscoveryResponse(List.of(new DiscoveryEndpoint("local", "", "", "", ""))); + } + + @Override + public List findConnectorEndpoints(final String endpointAddress, final List bpns) { + return bpns.stream() + .filter(bpnToEdcMapping::containsKey) + .map(bpn -> toDiscoveryResult(bpn, bpnToEdcMapping.get(bpn))) + .toList(); + } + + private EdcDiscoveryResult toDiscoveryResult(final String bpn, final String endpoint) { + return new EdcDiscoveryResult(bpn, List.of(endpoint)); + } +} diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/exceptions/RegistryServiceException.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/exceptions/RegistryServiceException.java new file mode 100644 index 0000000000..a5ce6dd7a0 --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/exceptions/RegistryServiceException.java @@ -0,0 +1,33 @@ +/******************************************************************************** + * 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.registryclient.exceptions; + +/** + * Base exception for the registry client + */ +public class RegistryServiceException extends Exception { + + public RegistryServiceException(final String msg) { + super(msg); + } +} diff --git a/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/exceptions/ShellNotFoundException.java b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/exceptions/ShellNotFoundException.java new file mode 100644 index 0000000000..397cca6b63 --- /dev/null +++ b/irs-registry-client/src/main/java/org/eclipse/tractusx/irs/registryclient/exceptions/ShellNotFoundException.java @@ -0,0 +1,41 @@ +/******************************************************************************** + * 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.registryclient.exceptions; + +import java.util.Collection; + +import lombok.Getter; + +/** + * Exception to handle missing asset administration shells + */ +@Getter +public class ShellNotFoundException extends RegistryServiceException { + private final Collection calledEndpoints; + + public ShellNotFoundException(final String msg, final Collection calledEndpoints) { + super(msg); + this.calledEndpoints = calledEndpoints; + } + +} diff --git a/irs-registry-client/src/main/resources/META-INF/spring.factories b/irs-registry-client/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000..f8d89ad415 --- /dev/null +++ b/irs-registry-client/src/main/resources/META-INF/spring.factories @@ -0,0 +1,4 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.eclipse.tractusx.irs.registryclient.DefaultConfiguration,\ +org.eclipse.tractusx.irs.edc.client.EdcConfiguration + diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/DefaultConfigurationTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/DefaultConfigurationTest.java new file mode 100644 index 0000000000..a70c290fb5 --- /dev/null +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/DefaultConfigurationTest.java @@ -0,0 +1,86 @@ +/******************************************************************************** + * 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.registryclient; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade; +import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; +import org.junit.jupiter.api.Test; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +class DefaultConfigurationTest { + + private final DefaultConfiguration testee = new DefaultConfiguration(); + + @Test + void centralDigitalTwinRegistryService() { + final var service = testee.centralDigitalTwinRegistryService( + testee.digitalTwinRegistryClientImpl(new RestTemplate(), "descriptor/{aasIdentifier}", + "shell?{assetIds}")); + + assertThat(service).isNotNull(); + } + + @Test + void decentralDigitalTwinRegistryService() { + final EdcSubmodelFacade facadeMock = mock(EdcSubmodelFacade.class); + final var service = testee.decentralDigitalTwinRegistryService( + testee.discoveryFinderClient(new RestTemplate(), "finder"), + testee.endpointDataForConnectorsService(facadeMock), + testee.decentralDigitalTwinRegistryClient(new RestTemplate())); + + assertThat(service).isNotNull(); + } + + @Test + void endpointDataForConnectorsService() throws EdcClientException { + final var mock = mock(EdcSubmodelFacade.class); + + final var endpointDataForConnectorsService = testee.endpointDataForConnectorsService(mock); + endpointDataForConnectorsService.findEndpointDataForConnectors(List.of("test")); + + verify(mock).getEndpointReferenceForAsset(any(), any(), any()); + } + + @Test + void endpointDataForConnectorsService_withException() throws EdcClientException { + final var mock = mock(EdcSubmodelFacade.class); + when(mock.getEndpointReferenceForAsset(any(), any(), any())).thenThrow(new EdcClientException("test")); + + final var endpointDataForConnectorsService = testee.endpointDataForConnectorsService(mock); + final var dummyEndpoints = List.of("test"); + assertThatThrownBy( + () -> endpointDataForConnectorsService.findEndpointDataForConnectors(dummyEndpoints)).isInstanceOf( + RestClientException.class); + + } +} \ No newline at end of file diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/AssetAdministrationShellTestdataCreatorTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/AssetAdministrationShellTestdataCreatorTest.java similarity index 98% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/AssetAdministrationShellTestdataCreatorTest.java rename to irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/AssetAdministrationShellTestdataCreatorTest.java index d9aa6fffeb..cfc72de784 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/AssetAdministrationShellTestdataCreatorTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/AssetAdministrationShellTestdataCreatorTest.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.central; import static org.assertj.core.api.Assertions.assertThat; diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/CentralDigitalTwinRegistryServiceTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/CentralDigitalTwinRegistryServiceTest.java similarity index 72% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/CentralDigitalTwinRegistryServiceTest.java rename to irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/CentralDigitalTwinRegistryServiceTest.java index 5070d5dac1..d8a583e817 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/CentralDigitalTwinRegistryServiceTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/CentralDigitalTwinRegistryServiceTest.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.central; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -31,13 +31,17 @@ import static org.mockito.Mockito.when; import java.io.IOException; +import java.util.Collection; import java.util.Collections; import java.util.List; -import org.eclipse.tractusx.irs.common.CxTestDataContainer; +import org.eclipse.tractusx.irs.data.CxTestDataContainer; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; import org.eclipse.tractusx.irs.component.assetadministrationshell.Endpoint; import org.eclipse.tractusx.irs.component.assetadministrationshell.SubmodelDescriptor; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryKey; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryService; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; import org.eclipse.tractusx.irs.testing.containers.LocalTestDataConfigurationAware; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -62,17 +66,21 @@ class CentralDigitalTwinRegistryServiceTest extends LocalTestDataConfigurationAw @BeforeEach void setUp() throws IOException { - digitalTwinRegistryService = new CentralDigitalTwinRegistryService(new DigitalTwinRegistryClientLocalStub(localTestDataConfiguration.cxTestDataContainer())); + digitalTwinRegistryService = new CentralDigitalTwinRegistryService( + new DigitalTwinRegistryClientLocalStub(localTestDataConfiguration.cxTestDataContainer())); dtRegistryFacadeWithMock = new CentralDigitalTwinRegistryService(dtRegistryClientMock); } @Test - void shouldReturnSubmodelEndpointsWhenRequestingWithCatenaXId() { + void shouldReturnSubmodelEndpointsWhenRequestingWithCatenaXId() throws RegistryServiceException { final String existingCatenaXId = "urn:uuid:bdadc54c-9ac3-478b-95e6-f968580d85b3"; - final AssetAdministrationShellDescriptor aasShellDescriptor = digitalTwinRegistryService.getAAShellDescriptor( - new DigitalTwinRegistryKey(existingCatenaXId, "")); - final List shellEndpoints = aasShellDescriptor.getSubmodelDescriptors(); + final Collection aasShellDescriptor = digitalTwinRegistryService.fetchShells( + List.of(new DigitalTwinRegistryKey(existingCatenaXId, ""))); + final List shellEndpoints = aasShellDescriptor.stream() + .findFirst() + .get() + .getSubmodelDescriptors(); assertThat(shellEndpoints).isNotNull().isNotEmpty(); final Endpoint endpoint = shellEndpoints.get(0).getEndpoints().get(0); @@ -89,8 +97,9 @@ void shouldThrowExceptionWhenRequestError() { when(dtRegistryClientMock.getAssetAdministrationShellDescriptor(catenaXId)).thenThrow( new RestClientException("Dummy")); + final var keys = List.of(key); assertThatExceptionOfType(RestClientException.class).isThrownBy( - () -> dtRegistryFacadeWithMock.getAAShellDescriptor(key)); + () -> dtRegistryFacadeWithMock.fetchShells(keys)); } @Test @@ -101,7 +110,8 @@ void shouldReturnTombstoneWhenClientReturnsEmptyDescriptor() { when(dtRegistryClientMock.getAssetAdministrationShellDescriptor(catenaXId)).thenReturn(shellDescriptor); - final List submodelEndpoints = dtRegistryFacadeWithMock.getAAShellDescriptor(new DigitalTwinRegistryKey(catenaXId, "")).getSubmodelDescriptors(); + final List submodelEndpoints = dtRegistryFacadeWithMock.fetchShells( + List.of(new DigitalTwinRegistryKey(catenaXId, ""))).stream().findFirst().get().getSubmodelDescriptors(); assertThat(submodelEndpoints).isEmpty(); } @@ -113,7 +123,7 @@ void verifyExecutionOfRegistryClientMethods() { when(dtRegistryClientMock.getAssetAdministrationShellDescriptor(catenaXId)).thenReturn(shellDescriptor); - dtRegistryFacadeWithMock.getAAShellDescriptor(new DigitalTwinRegistryKey(catenaXId, "")); + dtRegistryFacadeWithMock.fetchShells(List.of(new DigitalTwinRegistryKey(catenaXId, ""))); verify(this.dtRegistryClientMock, times(1)).getAllAssetAdministrationShellIdsByAssetLink(anyList()); verify(this.dtRegistryClientMock, times(1)).getAssetAdministrationShellDescriptor(catenaXId); @@ -130,25 +140,35 @@ void shouldReturnAssetAdministrationShellDescriptorForFoundIdentification() { Collections.singletonList(identification)); when(dtRegistryClientMock.getAssetAdministrationShellDescriptor(identification)).thenReturn(shellDescriptor); - final List submodelEndpoints = dtRegistryFacadeWithMock.getAAShellDescriptor(new DigitalTwinRegistryKey(globalAssetId, "")).getSubmodelDescriptors(); + final List submodelEndpoints = dtRegistryFacadeWithMock.fetchShells( + List.of(new DigitalTwinRegistryKey(globalAssetId, ""))) + .stream() + .findFirst() + .get() + .getSubmodelDescriptors(); assertThat(submodelEndpoints).isEmpty(); } @Test void shouldThrowErrorWhenCallingTestId() { final String globalAssetId = "urn:uuid:9ea14fbe-0401-4ad0-93b6-dad46b5b6e3d"; - final DigitalTwinRegistryClientLocalStub client = new DigitalTwinRegistryClientLocalStub(mock( - CxTestDataContainer.class)); + final DigitalTwinRegistryClientLocalStub client = new DigitalTwinRegistryClientLocalStub( + mock(CxTestDataContainer.class)); assertThatExceptionOfType(RestClientException.class).isThrownBy( () -> client.getAssetAdministrationShellDescriptor(globalAssetId)); } @Test - void shouldReturnSubmodelEndpointsWhenFilteringByAspectType() { + void shouldReturnSubmodelEndpointsWhenFilteringByAspectType() throws RegistryServiceException { final String existingCatenaXId = "urn:uuid:bdadc54c-9ac3-478b-95e6-f968580d85b3"; - final List shellEndpoints = digitalTwinRegistryService.getAAShellDescriptor(new DigitalTwinRegistryKey(existingCatenaXId, "")).getSubmodelDescriptors(); + final List shellEndpoints = digitalTwinRegistryService.fetchShells( + List.of(new DigitalTwinRegistryKey(existingCatenaXId, ""))) + .stream() + .findFirst() + .get() + .getSubmodelDescriptors(); assertThat(shellEndpoints).isNotNull().isNotEmpty(); final SubmodelDescriptor endpoint = shellEndpoints.get(0); diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryClientImplTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientImplTest.java similarity index 83% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryClientImplTest.java rename to irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientImplTest.java index ea6b1d2917..8e9b532e2c 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryClientImplTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryClientImplTest.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.central; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -33,14 +33,14 @@ import static org.mockito.Mockito.verify; import java.net.SocketTimeoutException; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair; -import org.eclipse.tractusx.irs.common.OutboundMeterRegistryService; import org.junit.jupiter.api.Test; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.ResponseEntity; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @@ -48,10 +48,8 @@ class DigitalTwinRegistryClientImplTest { private final RestTemplate restTemplate = mock(RestTemplate.class); - private final OutboundMeterRegistryService meterRegistry = mock(OutboundMeterRegistryService.class); - private final DigitalTwinRegistryClientImpl digitalTwinRegistryClient = new DigitalTwinRegistryClientImpl( - restTemplate, "url/{aasIdentifier}", "url/{assetIds}", meterRegistry); + restTemplate, "url/{aasIdentifier}", "url/{assetIds}"); @Test void shouldCallExternalServiceOnceAndGetAssetAdministrationShellDescriptor() { @@ -69,26 +67,27 @@ void shouldCallExternalServiceOnceAndGetAssetAdministrationShellDescriptor() { @Test void shouldCallExternalServiceOnceAndGetAssetAdministrationShellIds() { - doReturn(new ArrayList<>()).when(restTemplate).getForObject(any(), eq(List.class)); + doReturn(ResponseEntity.ok(List.of("testId"))).when(restTemplate) + .exchange(any(), any(), any(), + any(ParameterizedTypeReference.class)); final List empty = digitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink( Collections.emptyList()); assertNotNull(empty); - verify(this.restTemplate, times(1)).getForObject(any(), eq(List.class)); + verify(this.restTemplate, times(1)).exchange(any(), any(), any(), any(ParameterizedTypeReference.class)); } @Test void shouldCallExternalServiceOnceAndRunIntoTimeout() { final SocketTimeoutException timeoutException = new SocketTimeoutException("UnitTestTimeout"); Throwable ex = new ResourceAccessException("UnitTest", timeoutException); - doThrow(ex).when(restTemplate).getForObject(any(), eq(List.class)); + doThrow(ex).when(restTemplate).exchange(any(), any(), any(), any(ParameterizedTypeReference.class)); final List emptyList = Collections.emptyList(); assertThrows(ResourceAccessException.class, () -> digitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(emptyList)); - verify(this.restTemplate, times(1)).getForObject(any(), eq(List.class)); - verify(meterRegistry).incrementRegistryTimeoutCounter(); + verify(this.restTemplate, times(1)).exchange(any(), any(), any(), any(ParameterizedTypeReference.class)); } } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryExponentialRetryTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryExponentialRetryTest.java similarity index 57% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryExponentialRetryTest.java rename to irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryExponentialRetryTest.java index 182c658aaf..231d62b4c1 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DigitalTwinRegistryExponentialRetryTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/central/DigitalTwinRegistryExponentialRetryTest.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.central; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; @@ -30,35 +30,43 @@ import java.nio.charset.StandardCharsets; +import io.github.resilience4j.retry.RetryConfig; import io.github.resilience4j.retry.RetryRegistry; -import org.eclipse.tractusx.irs.TestConfig; +import io.github.resilience4j.retry.internal.InMemoryRetryRegistry; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; -import org.springframework.test.context.ActiveProfiles; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles(profiles = { "test" }) -@Import(TestConfig.class) +@ExtendWith(MockitoExtension.class) class DigitalTwinRegistryExponentialRetryTest { - @Autowired + private static final int MAX_ATTEMPTS = 3; + private static final String CONFIG_NAME = "registry"; private DigitalTwinRegistryClient digitalTwinRegistryClient; - @MockBean - @Qualifier("oAuthRestTemplate") + @Mock private RestTemplate restTemplate; - @Autowired - private RetryRegistry retryRegistry; + private final RetryRegistry retryRegistry = new InMemoryRetryRegistry(); + + @BeforeEach + void setUp() { + retryRegistry.addConfiguration(CONFIG_NAME, RetryConfig.from(RetryConfig.ofDefaults()) + .maxAttempts(MAX_ATTEMPTS) + .ignoreExceptions( + HttpClientErrorException.NotFound.class) + .build()); + + digitalTwinRegistryClient = new DigitalTwinRegistryClientImpl(restTemplate, "http://localhost/{aasIdentifier}", + "http://localhost?{assetIds}"); + } @Test void shouldRetryExecutionOfShellRetrievalMaxAttemptTimes() { @@ -67,22 +75,27 @@ void shouldRetryExecutionOfShellRetrievalMaxAttemptTimes() { new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "AASWrapper remote exception")); // Act - assertThrows(HttpServerErrorException.class, - () -> digitalTwinRegistryClient.getAssetAdministrationShellDescriptor("urn:uuid:12345")); + final var retry = retryRegistry.retry(CONFIG_NAME, CONFIG_NAME); + assertThrows(HttpServerErrorException.class, () -> retry.executeCallable( + () -> digitalTwinRegistryClient.getAssetAdministrationShellDescriptor("urn:uuid:12345"))); // Assert - verify(restTemplate, times(retryRegistry.getDefaultConfig().getMaxAttempts())).getForObject(any(), any()); + verify(restTemplate, times(retryRegistry.getConfiguration(CONFIG_NAME) + .map(RetryConfig::getMaxAttempts) + .orElse(MAX_ATTEMPTS))).getForObject(any(), any()); } @Test void shouldNotRetryExecutionOfShellRetrievalForNotFoundException() { // Arrange given(restTemplate.getForObject(any(), any())).willThrow( - HttpClientErrorException.create(HttpStatus.NOT_FOUND, "Not found", new HttpHeaders(), new byte[0], StandardCharsets.UTF_8)); + HttpClientErrorException.create(HttpStatus.NOT_FOUND, "Not found", new HttpHeaders(), new byte[0], + StandardCharsets.UTF_8)); // Act - assertThrows(HttpClientErrorException.NotFound.class, - () -> digitalTwinRegistryClient.getAssetAdministrationShellDescriptor("urn:uuid:12345")); + final var retry = retryRegistry.retry(CONFIG_NAME, CONFIG_NAME); + assertThrows(HttpClientErrorException.NotFound.class, () -> retry.executeCallable( + () -> digitalTwinRegistryClient.getAssetAdministrationShellDescriptor("urn:uuid:12345"))); // Assert verify(restTemplate, times(1)).getForObject(any(), any()); diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryClientTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClientTest.java similarity index 73% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryClientTest.java rename to irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClientTest.java index c442da5c1a..7af223b350 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DecentralDigitalTwinRegistryClientTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryClientTest.java @@ -1,24 +1,25 @@ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.decentral; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.ArrayList; -import java.util.List; import java.util.Optional; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; class DecentralDigitalTwinRegistryClientTest { - RestTemplate restTemplate = Mockito.mock(RestTemplate.class); + RestTemplate restTemplate = mock(RestTemplate.class); @Test void shouldCallForAssetAdministrationShellDescriptor() { @@ -27,9 +28,9 @@ void shouldCallForAssetAdministrationShellDescriptor() { EndpointDataReference endpointDataReference = EndpointDataReference.Builder.newInstance() .endpoint("url.to.host") .build(); - Mockito.when( - restTemplate.exchange(any(), eq(HttpMethod.GET), any(), eq(AssetAdministrationShellDescriptor.class))) - .thenReturn(ResponseEntity.of(Optional.of(AssetAdministrationShellDescriptor.builder().build()))); + when(restTemplate.exchange(any(), eq(HttpMethod.GET), any(), + eq(AssetAdministrationShellDescriptor.class))).thenReturn( + ResponseEntity.of(Optional.of(AssetAdministrationShellDescriptor.builder().build()))); // when client.getAssetAdministrationShellDescriptor(endpointDataReference, "aas-id"); @@ -45,14 +46,14 @@ void shouldCallForAllAssetAdministrationShellIdsByAssetLink() { EndpointDataReference endpointDataReference = EndpointDataReference.Builder.newInstance() .endpoint("url.to.host") .build(); - Mockito.when(restTemplate.exchange(any(), eq(HttpMethod.GET), any(), eq(List.class))) - .thenReturn(ResponseEntity.of(Optional.of(new ArrayList<>()))); + when(restTemplate.exchange(any(), eq(HttpMethod.GET), any(), any(ParameterizedTypeReference.class))).thenReturn( + ResponseEntity.of(Optional.of(new ArrayList<>()))); // when client.getAllAssetAdministrationShellIdsByAssetLink(endpointDataReference, new ArrayList<>()); // then - verify(restTemplate).exchange(any(), eq(HttpMethod.GET), any(), eq(List.class)); + verify(restTemplate).exchange(any(), eq(HttpMethod.GET), any(), any(ParameterizedTypeReference.class)); } } \ No newline at end of file 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 new file mode 100644 index 0000000000..26cfd22d4a --- /dev/null +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceTest.java @@ -0,0 +1,96 @@ +/******************************************************************************** + * 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.registryclient.decentral; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.assertj.core.api.Assertions; +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.component.assetadministrationshell.SubmodelDescriptor; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryKey; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryEndpoint; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderClient; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderRequest; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryResponse; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; + +class DecentralDigitalTwinRegistryServiceTest { + + private final DiscoveryFinderClient discoveryFinderClient = Mockito.mock(DiscoveryFinderClient.class); + private final EndpointDataForConnectorsService endpointDataForConnectorsService = Mockito.mock( + EndpointDataForConnectorsService.class); + + private final DecentralDigitalTwinRegistryClient decentralDigitalTwinRegistryClient = Mockito.mock( + DecentralDigitalTwinRegistryClient.class); + + private final DecentralDigitalTwinRegistryService decentralDigitalTwinRegistryService = new DecentralDigitalTwinRegistryService( + discoveryFinderClient, endpointDataForConnectorsService, decentralDigitalTwinRegistryClient); + + @Test + void shouldReturnExpectedShell() throws RegistryServiceException { + // given + 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(); + final List discoveryEndpoints = List.of( + new DiscoveryEndpoint("type", "desc", "address", "doc", "resId")); + Mockito.when(discoveryFinderClient.findDiscoveryEndpoints(ArgumentMatchers.any(DiscoveryFinderRequest.class))) + .thenReturn(new DiscoveryResponse(discoveryEndpoints)); + Mockito.when(endpointDataForConnectorsService.findEndpointDataForConnectors(ArgumentMatchers.anyList())) + .thenReturn(endpointDataReference); + Mockito.when( + decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(ArgumentMatchers.any(), + ArgumentMatchers.anyList())).thenReturn(Collections.emptyList()); + Mockito.when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(ArgumentMatchers.any(), + ArgumentMatchers.any())).thenReturn(expectedShell); + + // when + final Collection actualShell = decentralDigitalTwinRegistryService.fetchShells( + List.of(digitalTwinRegistryKey)); + + // then + Assertions.assertThat(actualShell).containsExactly(expectedShell); + } + + public static AssetAdministrationShellDescriptor shellDescriptor( + final List submodelDescriptors) { + return AssetAdministrationShellDescriptor.builder() + .specificAssetIds(List.of(IdentifierKeyValuePair.builder() + .key("ManufacturerId") + .value("BPNL00000003AYRE") + .build())) + .submodelDescriptors(submodelDescriptors) + .build(); + } + +} diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EndpointDataForConnectorsServiceTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/EndpointDataForConnectorsServiceTest.java similarity index 74% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EndpointDataForConnectorsServiceTest.java rename to irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/EndpointDataForConnectorsServiceTest.java index e21d289b2c..589d28508e 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/EndpointDataForConnectorsServiceTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/EndpointDataForConnectorsServiceTest.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.decentral; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -33,7 +33,6 @@ import java.util.List; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade; import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; import org.junit.jupiter.api.Test; import org.springframework.web.client.RestClientException; @@ -46,14 +45,16 @@ class EndpointDataForConnectorsServiceTest { private static final String connectionOneAddress = "connectionOneAddress"; private static final String connectionTwoAddress = "connectionTwoAddress"; - private final EdcSubmodelFacade edcSubmodelFacade = mock(EdcSubmodelFacade.class); + private final EdcEndpointReferenceRetriever edcSubmodelFacade = mock(EdcEndpointReferenceRetriever.class); - private final EndpointDataForConnectorsService endpointDataForConnectorsService = new EndpointDataForConnectorsService(edcSubmodelFacade); + private final EndpointDataForConnectorsService endpointDataForConnectorsService = new EndpointDataForConnectorsService( + edcSubmodelFacade); @Test - void shouldReturnExpectedEndpointDataReference() throws EdcClientException { + void shouldReturnExpectedEndpointDataReference() throws EdcRetrieverException { // given - when(edcSubmodelFacade.getEndpointReferenceForAsset(connectionOneAddress, DT_REGISTRY_ASSET_TYPE, DT_REGISTRY_ASSET_VALUE)).thenReturn( + when(edcSubmodelFacade.getEndpointReferenceForAsset(connectionOneAddress, DT_REGISTRY_ASSET_TYPE, + DT_REGISTRY_ASSET_VALUE)).thenReturn( EndpointDataReference.Builder.newInstance().endpoint(connectionOneAddress).build()); // when @@ -66,11 +67,13 @@ void shouldReturnExpectedEndpointDataReference() throws EdcClientException { } @Test - void shouldReturnExpectedEndpointDataReferenceFromSecondConnectionEndpoint() throws EdcClientException { + void shouldReturnExpectedEndpointDataReferenceFromSecondConnectionEndpoint() throws EdcRetrieverException { // given - when(edcSubmodelFacade.getEndpointReferenceForAsset(connectionOneAddress, DT_REGISTRY_ASSET_TYPE, DT_REGISTRY_ASSET_VALUE)) - .thenThrow(new EdcClientException("EdcClientException")); - when(edcSubmodelFacade.getEndpointReferenceForAsset(connectionTwoAddress, DT_REGISTRY_ASSET_TYPE, DT_REGISTRY_ASSET_VALUE)).thenReturn( + when(edcSubmodelFacade.getEndpointReferenceForAsset(connectionOneAddress, DT_REGISTRY_ASSET_TYPE, + DT_REGISTRY_ASSET_VALUE)).thenThrow( + new EdcRetrieverException(new EdcClientException("EdcClientException"))); + when(edcSubmodelFacade.getEndpointReferenceForAsset(connectionTwoAddress, DT_REGISTRY_ASSET_TYPE, + DT_REGISTRY_ASSET_VALUE)).thenReturn( EndpointDataReference.Builder.newInstance().endpoint(connectionTwoAddress).build()); // when @@ -83,15 +86,17 @@ void shouldReturnExpectedEndpointDataReferenceFromSecondConnectionEndpoint() thr } @Test - void shouldThrowExceptionWhenConnectorEndpointsNotReachable() throws EdcClientException { + void shouldThrowExceptionWhenConnectorEndpointsNotReachable() throws EdcRetrieverException { // given - when(edcSubmodelFacade.getEndpointReferenceForAsset(anyString(), eq(DT_REGISTRY_ASSET_TYPE), eq(DT_REGISTRY_ASSET_VALUE))) - .thenThrow(new EdcClientException("EdcClientException")); + when(edcSubmodelFacade.getEndpointReferenceForAsset(anyString(), eq(DT_REGISTRY_ASSET_TYPE), + eq(DT_REGISTRY_ASSET_VALUE))).thenThrow( + new EdcRetrieverException(new EdcClientException("EdcClientException"))); final List connectorEndpoints = List.of(connectionOneAddress, connectionTwoAddress); // when + then - assertThatThrownBy(() -> endpointDataForConnectorsService.findEndpointDataForConnectors(connectorEndpoints)) - .isInstanceOf(RestClientException.class).hasMessageContainingAll(connectionOneAddress, connectionTwoAddress); + assertThatThrownBy( + () -> endpointDataForConnectorsService.findEndpointDataForConnectors(connectorEndpoints)).isInstanceOf( + RestClientException.class).hasMessageContainingAll(connectionOneAddress, connectionTwoAddress); } } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClientImplTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClientImplTest.java similarity index 98% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClientImplTest.java rename to irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClientImplTest.java index 7702d2a137..d46039cbf4 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/aaswrapper/registry/domain/DiscoveryFinderClientImplTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/discovery/DiscoveryFinderClientImplTest.java @@ -20,7 +20,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.aaswrapper.registry.domain; +package org.eclipse.tractusx.irs.registryclient.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/discovery/LocalDataDiscoveryTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/discovery/LocalDataDiscoveryTest.java new file mode 100644 index 0000000000..40e42cfa2a --- /dev/null +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/discovery/LocalDataDiscoveryTest.java @@ -0,0 +1,63 @@ +/******************************************************************************** + * 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.registryclient.discovery; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +class LocalDataDiscoveryTest { + + private final LocalDataDiscovery testee = new LocalDataDiscovery(Map.of("bpn1", "endpoint1", "bpn2", "endpoint2")); + + @Test + void findDiscoveryEndpoints() { + final var result = testee.findDiscoveryEndpoints(new DiscoveryFinderRequest(List.of())); + + assertThat(result.endpoints()).hasSize(1); + } + + @Test + void shouldFindNoEndpointsForEmptyBpnList() { + final var result = testee.findConnectorEndpoints("", List.of("")); + + assertThat(result).isEmpty(); + } + + @Test + void shouldFindOneEndpointForOneBpn() { + final var result = testee.findConnectorEndpoints("", List.of("bpn1")); + + assertThat(result).hasSize(1); + } + + @Test + void shouldFindTwoEndpointForTwoBpns() { + final var result = testee.findConnectorEndpoints("", List.of("bpn1", "bpn2")); + + assertThat(result).hasSize(2); + } +} \ No newline at end of file diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/exceptions/ShellNotFoundExceptionTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/exceptions/ShellNotFoundExceptionTest.java new file mode 100644 index 0000000000..acb36bc31b --- /dev/null +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/exceptions/ShellNotFoundExceptionTest.java @@ -0,0 +1,39 @@ +/******************************************************************************** + * 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.registryclient.exceptions; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +class ShellNotFoundExceptionTest { + + @Test + void getCalledEndpoints() { + final ShellNotFoundException testee = new ShellNotFoundException("dummyMessage", List.of("test")); + + assertThat(testee.getCalledEndpoints()).containsExactly("test"); + } +} \ No newline at end of file diff --git a/irs-api/src/test/resources/AASShellTestdata.json b/irs-registry-client/src/test/resources/AASShellTestdata.json similarity index 100% rename from irs-api/src/test/resources/AASShellTestdata.json rename to irs-registry-client/src/test/resources/AASShellTestdata.json diff --git a/irs-testing/pom.xml b/irs-testing/pom.xml index 476953a548..8c70c204ce 100644 --- a/irs-testing/pom.xml +++ b/irs-testing/pom.xml @@ -71,6 +71,10 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + org.eclipse.tractusx.irs irs-common diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/containers/LocalTestDataConfigurationAware.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/containers/LocalTestDataConfigurationAware.java index 2517d1750a..0f0e503364 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/containers/LocalTestDataConfigurationAware.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/containers/LocalTestDataConfigurationAware.java @@ -29,8 +29,8 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.eclipse.tractusx.irs.common.CxTestDataContainer; -import org.eclipse.tractusx.irs.common.LocalTestDataConfiguration; +import org.eclipse.tractusx.irs.data.CxTestDataContainer; +import org.eclipse.tractusx.irs.data.LocalTestDataConfiguration; import org.mockito.Mockito; /** diff --git a/local/testing/api-tests/irs-api-tests.tavern.yaml b/local/testing/api-tests/irs-api-tests.tavern.yaml index 466c3ccb0e..171973579d 100644 --- a/local/testing/api-tests/irs-api-tests.tavern.yaml +++ b/local/testing/api-tests/irs-api-tests.tavern.yaml @@ -262,8 +262,6 @@ stages: # - json:off # #stages: -# - *authenticate_and_fetch_token -# # - name: register a BPN investigation with valid globalAssetId to T-Systems # request: # url: "{tavern.env_vars.IRS_ESS_HOST}/ess/bpn/investigations" @@ -378,7 +376,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_PLANNED}" bpn: "BPNL00000003AYRE" method: POST headers: @@ -413,7 +411,7 @@ stages: --- -test_name: Make sure job with submodels process with status COMPLETED +test_name: Make sure job with submodels process with status COMPLETED with asPlanned-id strict: - headers:off @@ -425,10 +423,13 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_PLANNED}" bpn: "BPNL00000003AYRE" collectAspects: true - depth: 1 + bomLifecycle: asPlanned + depth: 2 + aspects: + - SingleLevelUsageAsPlanned direction: "downward" method: POST headers: @@ -484,6 +485,65 @@ stages: --- +test_name: Make sure job with submodels process with status COMPLETED with asBuild-id + +strict: + - headers:off + - json:off + +stages: + - name: create a job and check for success + request: + url: "{tavern.env_vars.IRS_HOST}/irs/jobs" + json: + key: + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" + bpn: "BPNL00000003AYRE" + collectAspects: true + depth: 2 + aspects: + - ProductDescription + - CertificateOfDestruction + - SerialPart + - SingleLevelUsageAsBuilt + direction: "downward" + method: POST + headers: + content-type: application/json + $ext: + function: local.testing.api-tests.tavern_helpers:create_bearer_token + response: + status_code: 201 + headers: + content-type: application/json + save: + json: + job_id: id + + - *verify_job_is_running_and_wait_up_to_15_minutes_for_COMPLETED + + - name: verify job response with desired test steps + request: + url: "{tavern.env_vars.IRS_HOST}/irs/jobs/{job_id}" + params: + returnUncompletedJob: true + method: GET + headers: + content-type: application/json + $ext: + function: local.testing.api-tests.tavern_helpers:create_bearer_token + response: + status_code: 200 + verify_response_with: + - function: local.testing.api-tests.tavern_helpers:submodels_are_not_empty + - function: local.testing.api-tests.tavern_helpers:check_timestamps_for_completed_jobs + headers: + content-type: application/json + + +--- + + test_name: Make sure job without submodels process with status COMPLETED strict: @@ -496,7 +556,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_PLANNED}" bpn: "BPNL00000003AYRE" collectAspects: false depth: 1 @@ -586,9 +646,9 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_PLANNED}" bpn: "BPNL00000003AYRE" - bomLifecycle: "asBuilt" + bomLifecycle: "asPlanned" depth: 2 collectAspects: true method: POST @@ -632,7 +692,7 @@ stages: --- -test_name: Make sure job with aspect serialPartTypization is processed (1.3.0) +test_name: Make sure job with aspect SerialPart is processed (1.3.0) strict: - headers:off @@ -644,10 +704,10 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" aspects: - - SerialPartTypization + - SerialPart collectAspects: true depth: 1 method: POST @@ -691,7 +751,7 @@ stages: --- -test_name: Make sure job with aspects SerialPartTypization and AssemblyPartRelationship is processed (1.3.1) +test_name: Make sure job with aspects SerialPart and ProductDescription is processed (1.3.1) strict: - headers:off @@ -703,11 +763,11 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" aspects: - - SerialPartTypization - - AssemblyPartRelationship + - SerialPart + - ProductDescription collectAspects: true depth: 2 method: POST @@ -751,7 +811,7 @@ stages: --- -test_name: Make sure job with aspects BatteryPass and MaterialForRecycling is processed (1.3.2) +test_name: Make sure job with aspects MaterialForRecycling is processed (1.3.2) strict: - headers:off @@ -763,10 +823,9 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "urn:uuid:0ce413e9-4e3a-4040-a529-7e10d7c61b93" bpn: "BPNL00000003AYRE" aspects: - - BatteryPass - MaterialForRecycling collectAspects: true depth: 2 @@ -811,7 +870,7 @@ stages: --- -test_name: Make sure job with aspects Batch and CertificateOfDestruction is processed (1.3.3) +test_name: Make sure job with aspect Batch is processed (1.3.3) strict: - headers:off @@ -823,12 +882,12 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" - bpn: "BPNL00000003AYRE" + globalAssetId: "urn:uuid:acf437c1-1f20-4a1b-95f6-23f711cd65f6" + bpn: "BPNL00000003AXS3" aspects: - Batch - - CertificateOfDestruction collectAspects: true + bomLifecycle: "asBuilt" depth: 2 method: POST headers: @@ -871,7 +930,7 @@ stages: --- -test_name: Make sure job with aspects SerialPartTypization and DiagnosticData is processed (1.3.4) +test_name: Make sure job with aspects SerialPart and CertificateOfDestruction is processed (1.3.4) strict: - headers:off @@ -883,11 +942,11 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" aspects: - - SerialPartTypization - - DiagnosticData + - SerialPart + - CertificateOfDestruction collectAspects: true depth: 2 method: POST @@ -943,7 +1002,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_PLANNED}" bpn: "BPNL00000003AYRE" aspects: - UnknownAspect @@ -978,13 +1037,14 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" aspects: - - SerialPartTypization - - AssemblyPartRelationship - - Batch - ProductDescription + - CertificateOfDestruction + - SerialPart + - SingleLevelUsageAsBuilt + - BatteryPass - IdConversion - MarketplaceOffer - MaterialForRecycling @@ -1007,7 +1067,7 @@ stages: save: json: job_id: id - delay_after: 200 + delay_after: 60 - name: fetch response for running job and check existence of submodels and relationships request: @@ -1082,11 +1142,11 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" aspects: - - SerialPartTypization - - AssemblyPartRelationship + - SerialPart + - SingleLevelBomAsBuilt - Batch - ProductDescription - IdConversion @@ -1122,6 +1182,7 @@ stages: save: json: job_id: id + delay_after: 300 - *verify_job_is_running_and_wait_up_to_15_minutes_for_COMPLETED @@ -1172,7 +1233,7 @@ stages: # url: "{tavern.env_vars.IRS_HOST}/irs/jobs" # json: # key: - # globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + # globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" # bpn: "BPNL00000003AYRE" # aspects: # - "{deprecated_aspect}" @@ -1291,10 +1352,10 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" aspects: - - SerialPartTypization + - SerialPart - DiagnosticData collectAspects: true method: POST @@ -1448,7 +1509,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" method: POST headers: @@ -1593,7 +1654,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" collectAspects: true depth: 1 @@ -1737,7 +1798,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_PLANNED}" bpn: "BPNL00000003AYRE" collectAspects: true depth: 2 @@ -1746,7 +1807,7 @@ stages: lookupBPNs: true callbackUrl: "https://www.check123.com" aspects: - - SerialPartTypization + - SerialPart - PartAsPlanned method: POST headers: @@ -1795,7 +1856,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" collectAspects: false depth: 1 @@ -1848,7 +1909,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" collectAspects: false lookupBPNs: true @@ -1902,7 +1963,7 @@ stages: url: "{tavern.env_vars.IRS_HOST}/irs/jobs" json: key: - globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID}" + globalAssetId: "{tavern.env_vars.GLOBAL_ASSET_ID_AS_BUILD}" bpn: "BPNL00000003AYRE" collectAspects: false lookupBPNs: true @@ -1984,8 +2045,8 @@ stages: - urn:uuid:492781f5-62ff-4fb2-876c-3498e2844d13 - urn:uuid:d6142601-5e09-45fe-9b42-e53cf8cd458c aspects: - - "AssemblyPartRelationship" - - "SerialPartTypization" + - "SingleLevelBomAsBuilt" + - "SerialPart" collectAspects: true lookupBPNs: true batchSize: 10 @@ -2044,8 +2105,8 @@ stages: - urn:uuid:3db730be-9de5-4db5-a58d-684de36484e7 - urn:uuid:73173bf5-08df-4898-9d6d-8899015c161e aspects: - - "AssemblyPartRelationship" - - "SerialPartTypization" + - "SingleLevelBomAsBuilt" + - "SerialPart" collectAspects: true lookupBPNs: true batchSize: 2 diff --git a/local/testing/api-tests/tavern_helpers.py b/local/testing/api-tests/tavern_helpers.py index 4467d08d78..8b0fd6b134 100644 --- a/local/testing/api-tests/tavern_helpers.py +++ b/local/testing/api-tests/tavern_helpers.py @@ -94,8 +94,8 @@ def submodels_are_not_empty(response): def errors_for_invalid_globalAssetId_are_correct(response): print(response.json().get("messages")) error_list = response.json().get("messages") - assert 'globalAssetId:size must be between 45 and 45' in error_list - assert 'globalAssetId:must match \"^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$\"' in error_list + assert 'key.globalAssetId:size must be between 45 and 45' in error_list + assert 'key.globalAssetId:must match \"^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$\"' in error_list def errors_for_invalid_depth_are_correct(response): @@ -121,8 +121,7 @@ def errors_for_unknown_globalAssetId_are_correct(response): print("RetryCounter: ", processingErrorRetryCounter) assert 'urn:uuid:cce14502-958a-42e1-8bb7-f4f41aaaaaaa' in catenaXId assert 'DigitalTwinRequest' in processingErrorStep - assert 'Shell for identifier urn:uuid:cce14502-958a-42e1-8bb7-f4f41aaaaaaa not found' in processingErrorDetail - #assert '404 : \"{\"error\":{\"message\":\"Shell for identifier urn:uuid:cce14502-958a-42e1-8bb7-f4f41aaaaaaa not found\",\"path\":\"/registry/shell-descriptors/urn%3Auuid%3Acce14502-958a-42e1-8bb7-f4f41aaaaaaa\",\"details\":{}}}\"' in processingErrorDetail + #assert 'Shell for identifier urn:uuid:cce14502-958a-42e1-8bb7-f4f41aaaaaaa not found' in processingErrorDetail ##commented out since this error message is not possible currently after DTR changes assert processingErrorLastAttempt is not None assert 3 is processingErrorRetryCounter @@ -286,7 +285,7 @@ def job_parameter_are_as_requested(response): assert parameter.get('lookupBPNs') is True assert parameter.get('callbackUrl') == 'https://www.check123.com' aspects_list = parameter.get("aspects") - assert 'SerialPartTypization' in aspects_list + assert 'SerialPart' in aspects_list assert 'PartAsPlanned' in aspects_list diff --git a/pom.xml b/pom.xml index b93b12ec47..2084316aac 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ irs-testing irs-common irs-edc-client + irs-registry-client irs-ess irs-policy-store irs-api @@ -38,7 +39,7 @@ - 3.1.0 + 3.1.1 3.1.5 1.6.7 1.10.4