diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java index 1cdeba11..e9455d4c 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java @@ -22,20 +22,20 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.squareup.okhttp.*; import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.puris.backend.common.api.logic.service.VariablesService; -import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.CreateAssetDto; import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.EDR_Dto; +import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.datatype.DT_ApiMethodEnum; import org.eclipse.tractusx.puris.backend.common.edc.logic.util.EDCRequestBodyBuilder; -import org.eclipse.tractusx.puris.backend.model.repo.OrderRepository; +import org.eclipse.tractusx.puris.backend.masterdata.domain.model.Partner; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.IOException; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Service Layer of EDC Adapter. Builds and sends requests to a productEDC. @@ -45,39 +45,11 @@ @Slf4j public class EdcAdapterService { private static final OkHttpClient CLIENT = new OkHttpClient(); - @Autowired - private OrderRepository orderRepository; - - @Autowired - VariablesService variablesService; - - @Value("${edc.controlplane.host}") - private String edcHost; - - @Value("${edc.controlplane.data.port}") - private Integer dataPort; - - /** - * Path to data management api - */ - @Value("${edc.controlplane.data.path}") - private String dataPath; - - @Value("${edc.controlplane.key}") - private String edcApiKey; - - @Value("${server.port}") - private String serverPort; - - @Value("${minikube.ip}") - private String minikubeIp; - + private VariablesService variablesService; private ObjectMapper objectMapper; - @Autowired private EDCRequestBodyBuilder edcRequestBodyBuilder; - @Autowired private EndpointDataReferenceService edrService; @@ -85,449 +57,371 @@ public EdcAdapterService(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } - /** - * Publish an order at own EDC. - * - * @param orderId id of the order to publish. - * @return true, if order was published. - * @throws IOException if the connection to the EDC failed. - */ - public boolean publishOrderAtEDC(String orderId) throws IOException { - var order = orderRepository.findByOrderId(orderId); - if (order.isPresent()) { - var orderUrl = "http://" + minikubeIp + ":" + serverPort + "/catena/orders/order/id/" + orderId; - var assetBody = edcRequestBodyBuilder.buildAssetRequestBody(orderUrl, orderId); - var policyBody = edcRequestBodyBuilder.buildPolicyRequestBody(orderId); - var contractBody = edcRequestBodyBuilder.buildContractRequestBody(orderId); - - var response = sendEdcRequest(assetBody, "/assets"); - var success = response.isSuccessful(); - response.body().close(); - response = sendEdcRequest(policyBody, "/policydefinitions"); - success &= response.isSuccessful(); - response.body().close(); - response = sendEdcRequest(contractBody, "/contractdefinitions"); - success &= response.isSuccessful(); - response.body().close(); - return success; - } - return false; - } /** - * Publish an Asset (ContractDefinition) using an {@link CreateAssetDto} with a public policy. + * Call this method at startup to register the necessary request and + * response apis, including unrestricted policy- and contract-definitions + * that allow any external Partner to contract them. * - * @param createAssetDto asset creation dto to use. - * @return true, if ContractDefinition has been created successfully - * @throws IOException if REST calls for creation could not be sent + * @return true if all registrations were successful, otherwise false */ - public boolean publishAssetAtEDC(CreateAssetDto createAssetDto) throws IOException { - - String assetId = createAssetDto.getAssetDto().getPropertiesDto().getId(); - - boolean success = true; - JsonNode assetBody = objectMapper.valueToTree(createAssetDto); - JsonNode policyBody = - edcRequestBodyBuilder.buildPolicyRequestBody(assetId); - log.info(String.format("Policy Body: \n%s", policyBody.toPrettyString())); - JsonNode contractBody = edcRequestBodyBuilder.buildContractRequestBody(assetId); - log.info(String.format("Contract Body: \n%s", contractBody.toPrettyString())); - log.info(String.format("Asset Body: \n%s", assetBody.toPrettyString())); - var response = sendEdcRequest(assetBody, "/assets"); - success &= response.isSuccessful(); - log.info(String.format("Creation of asset was successfull: %b", success)); - response.body().close(); - response = sendEdcRequest(policyBody, "/policydefinitions"); - log.info(String.format("Creation of policy was successfull: %b", response.isSuccessful())); - success &= response.isSuccessful(); - response.body().close(); - response = sendEdcRequest(contractBody, "/contractdefinitions"); - success &= response.isSuccessful(); - log.info(String.format("Created Contract Definition (%b) for Asset %s", response.isSuccessful(), - objectMapper.writeValueAsString(createAssetDto))); - response.body().close(); - return success; + public boolean doInitialAssetRegistration() { + boolean result; + log.info("Registration of product-stock request api successful " + (result = registerDSPApiAsset(DT_ApiMethodEnum.REQUEST))); + if (!result) return false; + log.info("Registration of product-stock response api successful " + (result = registerDSPApiAsset(DT_ApiMethodEnum.RESPONSE))); + if (!result) return false; + log.info("Registration of policy successful " + (result = registerDSPSimplePolicy())); + if (!result) return false; + log.info("Registration of contract definition successful " + (result = registerDSPSimpleContractDefinition())); + return result; } - /** - * Get catalog from an EDC. + * Util method to register a simple contract definition without restrictions + * regarding the asset selector. Will therefore be applicable to all assets + * that were registered previously. Must be called after registerDSPSimplePolicy() * - * @param idsUrl url of the EDC to get catalog from. - * @return catalog of the requested EDC. - * @throws IOException if the connection to the EDC failed. + * @return true if successful */ - public String getCatalog(String idsUrl) throws IOException { - return getCatalog(idsUrl, Optional.empty()); + private boolean registerDSPSimpleContractDefinition() { + var body = edcRequestBodyBuilder.buildDSPContractDefinitionWithPublicPolicy(); + try { + var response = sendDspPostRequest(body, List.of("v2", "contractdefinitions")); + boolean result = response.isSuccessful(); + if (!result) { + log.warn("Contract definition registration failed \n" + response.body().string()); + } + response.body().close(); + return result; + } catch (Exception e) { + log.error("Failed to register contract definition ", e); + return false; + } } /** - * Get catalog from an EDC. + * Util method to register a policy without any restrictions to + * your control plane. Should be called after asset creation. * - * @param idsUrl url of the EDC to get catalog from. - * @param filterProperties maps with key = asset property and value = filter value - * @return catalog of the requested EDC. - * @throws IOException if the connection to the EDC failed. + * @return true if successful */ - public String getCatalog(String idsUrl, Optional> filterProperties) throws IOException { - - HttpUrl.Builder urlBuilder = new HttpUrl.Builder(); - urlBuilder.scheme("http") - .host(edcHost) - .port(dataPort) - .addPathSegment("api") - .addPathSegment("v1") - .addPathSegment("data") - .addPathSegment("catalog") - .addEncodedQueryParameter("providerUrl", idsUrl + "/data"); - - HttpUrl httpUrl = urlBuilder.build(); - - // workaround EDC 0.3 takes filter=key=value, but HttpUrlBuilder encodes = to %3D - // which is not recognized - if (filterProperties.isPresent() && filterProperties.get().size() >= 1) { - String url = urlBuilder.build().toString(); - - for (Map.Entry entry : filterProperties.get().entrySet()) { - url = url + String.format("&filter=%s=%s", entry.getKey(), entry.getValue()); + private boolean registerDSPSimplePolicy() { + var body = edcRequestBodyBuilder.buildPublicDSPPolicy(); + try { + var response = sendDspPostRequest(body, List.of("v2", "policydefinitions")); + boolean result = response.isSuccessful(); + if (!result) { + log.warn("Policy registration failed \n" + response.body().string()); } - httpUrl = HttpUrl.parse(url); - } - log.debug(String.format("catalog request url: %s", httpUrl)); - - var request = new Request.Builder() - .get() - .url(httpUrl) - .header("X-Api-Key", edcApiKey) - .header("Content-Type", "application/json") - .build(); - var response = CLIENT.newCall(request).execute(); - String stringData = response.body().string(); - if (!response.isSuccessful()) { - throw new IOException(stringData); + response.body().close(); + return result; + } catch (Exception e) { + log.error("Failed to register policy definition ", e); + return false; } - response.body().close(); - return stringData; } /** - * Get a catalog from EDC. This method accepts a set of key/value - * pairs which are to be applied on the asset.properties level of - * the catalog. - * @param idsUrl url of the EDC to get catalog from. - * @param propertyObjectFilter the filter to be applied - * @return the catalog as JsonNode - * @throws IOException + * Util method to register an API asset to your control plane. + * + * @param apiMethod the api method to register. + * @return true if successful. */ - public JsonNode getCatalogFilteredByAssetPropertyObjectFilter(String idsUrl, Map propertyObjectFilter) throws IOException { - var catalogObject = objectMapper.readTree(getCatalog(idsUrl)); - var outputNode = objectMapper.createObjectNode(); - outputNode.put("id", catalogObject.get("id").asText()); - var contractOffersArray = objectMapper.createArrayNode(); - outputNode.set("contractOffers", contractOffersArray); - List catalogItems = objectMapper.readerForListOf(ObjectNode.class).readValue(catalogObject.get("contractOffers")); - for (var catalogItem : catalogItems) { - var properties = catalogItem.get("asset").get("properties"); - boolean testPassed = true; - for(var entry : propertyObjectFilter.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - testPassed = testPassed && properties.get(key) != null && value.equals(properties.get(key).asText()); - } - if (testPassed) { - contractOffersArray.add(catalogItem); + private boolean registerDSPApiAsset(DT_ApiMethodEnum apiMethod) { + var body = edcRequestBodyBuilder.buildDSPCreateAssetBody(apiMethod); + try { + var response = sendDspPostRequest(body, List.of("v3", "assets")); + boolean result = response.isSuccessful(); + if (!result) { + log.warn("Asset registration failed \n" + response.body().string()); } + response.body().close(); + return result; + } catch (Exception e) { + log.error("Failed to register api asset " + apiMethod.PURPOSE, e); + return false; } - return outputNode; } + /** - * Orders your own EDC Connector Controlplane to negotiate a contract with - * the owner of the given connector address for an asset (specified by the - * assetId) under conditions as stated in the contract defintion with the - * given contractDefinitionId - * @param connectorAddress - * @param contractDefinitionId - * @param assetId - * @return the response body as String - * @throws IOException + * Retrieve an (unfiltered) catalog from the partner with the + * given dspUrl + * + * @param dspUrl The dspUrl of your partner + * @return The full catalog + * @throws IOException If the connection to the partners control plane fails */ - public String startNegotiation(String connectorAddress, - String contractDefinitionId, String assetId) throws IOException { - var negotiationRequestBody = - edcRequestBodyBuilder.buildNegotiationRequestBody(connectorAddress, - contractDefinitionId, assetId); - var response = sendEdcRequest(negotiationRequestBody, "/contractnegotiations"); + public JsonNode getDSPCatalog(String dspUrl) throws IOException { + var response = sendDspPostRequest(edcRequestBodyBuilder.buildBasicDSPCatalogRequestBody(dspUrl, null), List.of("v2", "catalog", "request")); String stringData = response.body().string(); response.body().close(); - return stringData; + return objectMapper.readTree(stringData); } /** - * Sends a request to the own EDC Connector Controlplane in order to receive - * the current status of the previously initiated contractNegotiations as - * specified by the parameter. - * @param negotiationId - * @return the response body as String - * @throws IOException + * Retrieve the content of the catalog from a remote EDC Connector as an + * array of catalog items. + * You may specify filter criteria, consisting of a map of key-value-pairs. + * Catalog items that don't have these filter criteria will be removed from the output array. + * + * @param dspUrl The Protocol URL of the other EDC Connector + * @param filter A map of key-value-pairs. May be empty or null. + * @return An array of Catalog items. + * @throws IOException If the connection to the partners control plane fails */ - public String getNegotiationState(String negotiationId) throws IOException { - var response = sendEdcRequest("/contractnegotiations/" + negotiationId); + private JsonNode getDSPCatalogItems(String dspUrl, Map filter) throws IOException { + var response = sendDspPostRequest(edcRequestBodyBuilder. + buildBasicDSPCatalogRequestBody(dspUrl, filter), List.of("v2", "catalog", "request")); String stringData = response.body().string(); + if (!response.isSuccessful()) { + throw new IOException("Http Catalog Request unsuccessful"); + } response.body().close(); - return stringData; + JsonNode responseNode = objectMapper.readTree(stringData); + + var catalogArray = responseNode.get("dcat:dataset"); + // If there is exactly one asset, the catalogContent will be a JSON object. + // In all other cases catalogContent will be a JSON array. + // For the sake of uniformity we will embed a single object in an array. + if (catalogArray.isObject()) { + catalogArray = objectMapper.createArrayNode().add(catalogArray); + } + if (filter == null || filter.isEmpty()) { + return catalogArray; + } + var filteredNode = objectMapper.createArrayNode(); + for (var catalogEntry : catalogArray) { + boolean testPassed = true; + for (var filterEntry : filter.entrySet()) { + testPassed = testPassed && catalogEntry.has(filterEntry.getKey()) + && catalogEntry.get(filterEntry.getKey()).asText().equals(filterEntry.getValue()); + } + if (testPassed) { + filteredNode.add(catalogEntry); + } + } + return filteredNode; } /** - * Start a data transfer with another EDC. + * Helper method for contracting a certain asset as specified in the catalog item from + * a specific Partner. * - * @param transferId id created for the transferprocess. - * @param connectorAddress ids url of the transfer counterparty. - * @param contractId id of the negotiated contract. - * @param orderId id of the transfers target asset. - * @return response body received from the EDC. - * @throws IOException if the connection to the EDC failed. + * @param partner The Partner to negotiate with + * @param catalogItem An excerpt from a catalog. + * @return The JSON response to your contract offer. + * @throws IOException If the connection to the partners control plane fails */ - public String startTransfer(String transferId, - String connectorAddress, - String contractId, - String orderId) throws IOException { - var transferNode = edcRequestBodyBuilder.buildTransferRequestBody(transferId, connectorAddress, contractId, orderId); - log.debug("TransferRequestBody:\n" + transferNode.toPrettyString()); - var response = sendEdcRequest(transferNode, "/transferprocess"); - String stringData = response.body().string(); + private JsonNode startDspNegotiation(Partner partner, JsonNode catalogItem) throws IOException { + var requestBody = edcRequestBodyBuilder.buildDSPAssetNegotiation(partner, catalogItem); + var response = sendDspPostRequest(requestBody, List.of("v2", "contractnegotiations")); + String responseString = response.body().string(); response.body().close(); - return stringData; + return objectMapper.readTree(responseString); } + /** - * Sends a request to the own EDC Connector Controlplane in order to receive - * the current status of the previously initiated transfer as specified by - * the parameter. - * @param transferId - * @return - * @throws IOException + * Util method for issuing a GET request to the management api of your control plane. + * + * @param pathSegments The path segments + * @return The response + * @throws IOException If the connection to your control plane fails */ - public String getTransferState(String transferId) throws IOException { - var response = sendEdcRequest("/transferprocess/" + transferId); - String stringData = response.body().string(); - response.body().close(); - return stringData; + public Response sendDspGetRequest(List pathSegments) throws IOException { + HttpUrl.Builder urlBuilder = HttpUrl.parse(variablesService.getEdcManagementUrl()).newBuilder(); + for (var pathSegment : pathSegments) { + urlBuilder.addPathSegment(pathSegment); + } + var request = new Request.Builder() + .get() + .url(urlBuilder.build()) + .header("X-Api-Key", variablesService.getEdcApiKey()) + .build(); + return CLIENT.newCall(request).execute(); } /** - * Delete an asset from the own EDC. + * Util method for issuing a POST request to the management api of your control plane. * - * @param assetId id of the asset to delete. - * @return response body received from the EDC. - * @throws IOException if the connection to the EDC failed. + * @param requestBody The request body + * @param pathSegments The path segments + * @return The response from your control plane + * @throws IOException If the connection to your control plane fails */ - public String deleteAsset(String assetId) throws IOException { - var urlBuilder = new HttpUrl.Builder() - .scheme("http") - .host(edcHost) - .port(dataPort); - urlBuilder.addPathSegment("data"); - urlBuilder.addPathSegment("assets"); - urlBuilder.addPathSegment(assetId); - var url = urlBuilder.build(); + private Response sendDspPostRequest(JsonNode requestBody, List pathSegments) throws IOException { + HttpUrl.Builder urlBuilder = HttpUrl.parse(variablesService.getEdcManagementUrl()).newBuilder(); + for (var pathSegment : pathSegments) { + urlBuilder.addPathSegment(pathSegment); + } + RequestBody body = RequestBody.create(MediaType.parse("application/json"), requestBody.toString()); + var request = new Request.Builder() - .url(url) - .header("X-Api-Key", edcApiKey) - .header("Content-Type", "application/json") - .delete() - .build(); - var response = CLIENT.newCall(request).execute(); - String stringData = response.body().string(); - response.body().close(); - return stringData; + .post(body) + .url(urlBuilder.build()) + .header("X-Api-Key", variablesService.getEdcApiKey()) + .header("Content-Type", "application/json") + .build(); + return CLIENT.newCall(request).execute(); } /** - * Send a GET request to the own EDC. + * Sends a request to the own control plane in order to receive + * the current status of the previously initiated contractNegotiations as + * specified by the parameter. * - * @param resourceId (optional) id of the resource to request, will be left empty if null. - * @param pathSegments varargs for the path segments of the request - * (e.g "data", "assets" will be turned to /data/assets). - * @return response body received from the EDC. - * @throws IOException if the connection to the EDC failed. + * @param negotiationId The id of the ongoing negotiation + * @return The response body as String + * @throws IOException If the connection to your control plane fails */ - public String getFromEdc(String resourceId, String... pathSegments) throws IOException { - var urlBuilder = new HttpUrl.Builder() - .scheme("http") - .host(edcHost) - .port(dataPort); - for (var seg : pathSegments) { - urlBuilder.addPathSegment(seg); - } - if (resourceId != null) { - urlBuilder.addPathSegment(resourceId); - } - var url = urlBuilder.build(); - var request = new Request.Builder() - .get() - .url(url) - .header("X-Api-Key", edcApiKey) - .header("Content-Type", "application/json") - .build(); - var response = CLIENT.newCall(request).execute(); + public JsonNode getDspNegotiationState(String negotiationId) throws IOException { + var response = sendDspGetRequest(List.of("v2", "contractnegotiations", negotiationId)); String stringData = response.body().string(); response.body().close(); - return stringData; + return objectMapper.readTree(stringData); } /** - * Util method for building a http POST request to the own EDC. - * Any caller of this method has the responsibility to close - * the returned Response object after using it. + * Sends a request to the own control plane in order to initiate a transfer of + * a previously negotiated asset. * - * @param requestBody requestBody to be sent to the EDC. - * @param urlSuffix path to POST data to - * @return response received from the EDC. - * @throws IOException if the connection to the EDC failed. + * @param partner The partner + * @param contractId The contract id + * @param assetId The asset id + * @return The response object + * @throws IOException If the connection to your control plane fails */ - public Response sendEdcRequest(JsonNode requestBody, String urlSuffix) throws IOException { - Request request = new Request.Builder() - .header("X-Api-Key", edcApiKey) - .header("Content-Type", "application/json") - .post(RequestBody.create(MediaType.parse("application/json"), requestBody.toString())) - .url("http://" + edcHost + ":" + dataPort + dataPath + urlSuffix) - .build(); - log.debug(String.format("Request send to url: %s", request.urlString())); - log.debug(String.format("Request body of EDC Request: %s", requestBody)); - return CLIENT.newCall(request).execute(); + public JsonNode startDspPullTransfer(Partner partner, String contractId, String assetId) throws IOException { + var body = edcRequestBodyBuilder.buildDSPDataPullRequestBody(partner, contractId, assetId); + var response = sendDspPostRequest(body, List.of("v2", "transferprocesses")); + String data = response.body().string(); + response.body().close(); + return objectMapper.readTree(data); } /** - * Util method for building a http GET request to the own EDC. - * Any caller of this method has the responsibility to close - * the returned Response object after using it. - * - * @param urlSuffix path to send GET request to - * @return response received from the EDC. - * @throws IOException if the connection to the EDC failed. + * Sends a request to the own control plane in order to receive + * the current status of the previously initiated transfer as specified by + * the parameter. + * + * @param transferId The id of the transfer in question + * @return The response from your Controlplane + * @throws IOException If the connection to your control plane fails */ - public Response sendEdcRequest(String urlSuffix) throws IOException { - Request request = new Request.Builder() - .header("X-Api-Key", edcApiKey) - .header("Content-Type", "application/json") - .url("http://" + edcHost + ":" + dataPort + dataPath + urlSuffix) - .build(); - log.debug(String.format("Send Request to url: %s", request.urlString())); - - return CLIENT.newCall(request).execute(); + public JsonNode getDspTransferState(String transferId) throws IOException { + var response = sendDspGetRequest(List.of("v2", "transferprocesses", transferId)); + String data = response.body().string(); + response.body().close(); + return objectMapper.readTree(data); } + /** - * Util method for sending a post request to your own dataplane + * Util method for sending a post request the given endpoint * in order to initiate a consumer pull request. * Any caller of this method has the responsibility to close * the returned Response object after using it. - * - * @param url the URL of an endpoint you received to perform a pull request - * @param authKey authKey to be used in the HTTP request header - * @param authCode authCode to be used in the HTTP request header - * @param requestBodyString the request body in JSON format as String - * @return the response from your dataplane + * + * @param url The URL of an endpoint you received to perform a pull request + * @param authKey The authKey to be used in the HTTP request header + * @param authCode The authCode to be used in the HTTP request header + * @param requestBodyString The request body in JSON format as String + * @return The response from the endpoint defined in the url (which is usually the other party's data plane), carrying the asset payload */ - public Response sendDataPullRequest(String url, String authKey, String authCode, String requestBodyString){ - log.debug(String.format("Sending proxy call to endpoint '%s' with auth key '%s' and auth code '%s' with request body '%s'", url, authKey, authCode, requestBodyString)); + public Response sendDataPullRequest(String url, String authKey, String authCode, String requestBodyString) { try { RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), requestBodyString); Request request = new Request.Builder() - .url(url) - .header(authKey, authCode) - .post(requestBody) - .build(); + .url(url) + .header(authKey, authCode) + .post(requestBody) + .build(); return CLIENT.newCall(request).execute(); } catch (Exception e) { log.error("Failed to send Data Pull request to " + url, e); throw new RuntimeException(e); } - } /** * Tries to negotiate for the request api of the given partner, including the retrieval of the - * authCode for a request. - * It will return a String array of length 5. The authKey is stored under index 0, the - * authCode under index 1, the endpoint under index 2 and the contractId under index 3. - * - * @param partnerIdsUrl - * @return a String array or null, if negotiation or transfer have failed or the authCode did not arrive + * authCode for a request. + * It will return a String array of length 4. The authKey is stored under index 0, the + * authCode under index 1, the endpoint under index 2 and the contractId under index 3. + * + * @param partner The partner to negotiate with + * @return A String array or null, if negotiation or transfer have failed or the authCode did not arrive */ - public String[] getContractForRequestApi(String partnerIdsUrl) { + public String[] getContractForRequestApi(Partner partner) { HashMap filter = new HashMap<>(); filter.put("asset:prop:type", "api"); filter.put("asset:prop:apibusinessobject", "product-stock"); filter.put("asset:prop:apipurpose", "request"); filter.put("asset:prop:version", variablesService.getPurisApiVersion()); - return getContractForRequestOrResponseApiApi(partnerIdsUrl, filter); + return getContractForRequestOrResponseApiApi(partner, filter); } /** * Tries to negotiate for the response api of the given partner, including the retrieval of the - * authCode for a request. - * It will return a String array of length 5. The authKey is stored under index 0, the - * authCode under index 1, the endpoint under index 2 and the contractId under index 3. - * @param partnerIdsUrl - * @return a String array or null, if negotiation or transfer have failed or the authCode did not arrive + * authCode for a request. + * It will return a String array of length 4. The authKey is stored under index 0, the + * authCode under index 1, the endpoint under index 2 and the contractId under index 3. + * + * @param partner The partner to negotiate with + * @return A String array or null, if negotiation or transfer have failed or the authCode did not arrive */ - public String[] getContractForResponseApi(String partnerIdsUrl) { + public String[] getContractForResponseApi(Partner partner) { HashMap filter = new HashMap<>(); filter.put("asset:prop:type", "api"); filter.put("asset:prop:apibusinessobject", "product-stock"); filter.put("asset:prop:apipurpose", "response"); filter.put("asset:prop:version", variablesService.getPurisApiVersion()); - return getContractForRequestOrResponseApiApi(partnerIdsUrl, filter); + return getContractForRequestOrResponseApiApi(partner, filter); } /** * Tries to negotiate for the given api of the partner specified by the parameter - * and also tries to initiate the transfer of the edr token to the given endpoint. - * - * It will return a String array of length 5. The authKey is stored under index 0, the - * authCode under index 1, the endpoint under index 2 and the contractId under index 3. - * @param partnerIdsUrl counterparty's idsUrl - * @param filter the filter to be applied on the level of the asset's properties object. - * @return a String array or null, if negotiation or transfer have failed or the authCode did not arrive + * and also tries to initiate the transfer of the edr token to the given endpoint. + *

+ * It will return a String array of length 4. The authKey is stored under index 0, the + * authCode under index 1, the endpoint under index 2 and the contractId under index 3. + * + * @param partner The partner to negotiate with + * @param filter The filter to be applied on the level of the asset's properties object. + * @return A String array or null, if negotiation or transfer have failed or the authCode did not arrive */ - public String[] getContractForRequestOrResponseApiApi(String partnerIdsUrl, Map filter) { + public String[] getContractForRequestOrResponseApiApi(Partner partner, Map filter) { try { - JsonNode objectNode = getCatalogFilteredByAssetPropertyObjectFilter(partnerIdsUrl, filter); - JsonNode contractOffer = objectNode.get("contractOffers").get(0); - String assetApi = contractOffer.get("asset").get("id").asText(); - String contractDefinitionId = contractOffer.get("id").asText(); - String negotiationResponseString = startNegotiation(partnerIdsUrl + "/data", contractDefinitionId, assetApi); - String negotiationId = objectMapper.readTree(negotiationResponseString).get("id").asText(); - + JsonNode catalogItem = getDSPCatalogItems(partner.getEdcUrl(), filter).get(0); + JsonNode negotiationResponse = startDspNegotiation(partner, catalogItem); + String assetApi = catalogItem.get("@id").asText(); + String negotiationId = negotiationResponse.get("@id").asText(); // Await confirmation of contract and contractId String contractId = null; for (int i = 0; i < 100; i++) { Thread.sleep(100); - var negotiationState = getNegotiationState(negotiationId); - var responseObject = objectMapper.readTree(negotiationState); - if ("CONFIRMED".equals(responseObject.get("state").asText())) { - contractId = responseObject.get("contractAgreementId").asText(); + var responseObject = getDspNegotiationState(negotiationId); + if ("FINALIZED".equals(responseObject.get("edc:state").asText())) { + contractId = responseObject.get("edc:contractAgreementId").asText(); break; } } if (contractId == null) { - var negotiationState = getNegotiationState(negotiationId); - log.warn("no contract id, last negotiation state: " + negotiationState); - log.warn("Failed to obtain " + assetApi + " from " + partnerIdsUrl); + var negotiationState = getDspNegotiationState(negotiationId); + log.warn("no contract id, last negotiation state: \n" + negotiationState.toPrettyString()); + log.error("Failed to obtain " + assetApi + " from " + partner.getEdcUrl()); return null; } // Initiate transfer of edr - String randomTransferID = UUID.randomUUID().toString(); - String transferResponse = startTransfer(randomTransferID, partnerIdsUrl + "/data", contractId, assetApi); - String transferId = objectMapper.readTree(transferResponse).get("id").asText(); + var transferResp = startDspPullTransfer(partner, contractId, assetApi); + String transferId = transferResp.get("@id").asText(); for (int i = 0; i < 100; i++) { Thread.sleep(100); - transferResponse = getTransferState(transferId); - var transferResponseObject = objectMapper.readTree(transferResponse); - if ("COMPLETED".equals(transferResponseObject.get("state").asText())) { + transferResp = getDspTransferState(transferId); + if ("STARTED".equals(transferResp.get("edc:state").asText())) { break; } } @@ -535,21 +429,18 @@ public String[] getContractForRequestOrResponseApiApi(String partnerIdsUrl, Map< // Await arrival of edr for (int i = 0; i < 100; i++) { Thread.sleep(100); - EDR_Dto edr_Dto = edrService.findByTransferId(randomTransferID); + EDR_Dto edr_Dto = edrService.findByTransferId(transferId); if (edr_Dto != null) { - log.info("Successfully negotiated for " + assetApi + " with " + partnerIdsUrl); - return new String [] {edr_Dto.getAuthKey(),edr_Dto.getAuthCode(), edr_Dto.getEndpoint(), contractId}; + log.info("Successfully negotiated for " + assetApi + " with " + partner.getEdcUrl()); + return new String[]{edr_Dto.getAuthKey(), edr_Dto.getAuthCode(), edr_Dto.getEndpoint(), contractId}; } } log.warn("did not receive authCode"); - log.warn("Failed to obtain " + assetApi + " from " + partnerIdsUrl); + log.error("Failed to obtain " + assetApi + " from " + partner.getEdcUrl()); return null; - } catch (Exception e){ - log.warn("ERROR"); - log.error("Failed to obtain api from " + partnerIdsUrl, e); + } catch (Exception e) { + log.error("Failed to obtain api from " + partner.getEdcUrl(), e); return null; } - } - } diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/util/EDCRequestBodyBuilder.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/util/EDCRequestBodyBuilder.java index f0244b92..04eeb365 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/util/EDCRequestBodyBuilder.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/util/EDCRequestBodyBuilder.java @@ -2,25 +2,23 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import org.eclipse.tractusx.puris.backend.common.api.domain.model.datatype.DT_UseCaseEnum; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.puris.backend.common.api.logic.service.VariablesService; -import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.*; -import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.datatype.DT_ApiBusinessObjectEnum; import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.datatype.DT_ApiMethodEnum; -import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.datatype.DT_AssetTypeEnum; -import org.eclipse.tractusx.puris.backend.common.edc.logic.dto.datatype.DT_DataAddressTypeEnum; +import org.eclipse.tractusx.puris.backend.masterdata.domain.model.Partner; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.util.Map; + /** * Utility Component for building EDC request body json objects. */ @Component +@Slf4j public class EDCRequestBodyBuilder { - @Value("${edr.endpoint}") - private String endpointDataReferenceEndpoint; @Autowired private VariablesService variablesService; @@ -28,188 +26,201 @@ public class EDCRequestBodyBuilder { @Autowired private ObjectMapper MAPPER; + private final String publicPolicyId = "policy1"; + private final String publicContractDefinitionId = "contractdef1"; + private final String EDC_NAMESPACE = "https://w3id.org/edc/v0.0.1/ns/"; + private final String VOCAB_KEY = "@vocab"; + private final String ODRL_NAMESPACE = "http://www.w3.org/ns/odrl/2/"; + private final String CX_TAXO_NAMESPACE = "https://w3id.org/catenax/taxonomy#"; + private final String CX_COMMON_NAMESPACE = "https://w3id.org/catenax/ontology/common#"; + private final String CX_VERSION_KEY = "https://w3id.org/catenax/ontology/common#version"; + private final String CX_VERSION_NUMBER = "2.0.0"; + private final String DCT_NAMESPACE = "https://purl.org/dc/terms/"; + private final String PURL_TYPE_KEY = "https://purl.org/dc/terms/type"; + + /** - * Build an EDC request body for the creation of an asset (using an order). + * Creates a request body for requesting a catalog in DSP protocol. + * You can add filter criteria. However, at the moment there are issues + * with nested catalog item properties, so it seems advisable to check + * for the filter criteria programmatically. * - * @param orderUrl url where the published order can be received by the controlplane. - * @param orderId id of the created asset (currently has to match policy and contract id). - * @return JsonNode used as requestBody for asset creation. + * @param counterPartyDspUrl The protocol url of the other party + * @param filter Key-value-pairs, may be empty or null + * @return The request body */ - public JsonNode buildAssetRequestBody(String orderUrl, String orderId) { - var assetRequest = MAPPER.createObjectNode(); - var assetNode = MAPPER.createObjectNode(); - var assetPropNode = MAPPER.createObjectNode(); - assetNode.set("properties", assetPropNode); - assetPropNode.put("asset:prop:id", orderId); - assetPropNode.put("asset:prop:description", "EDC Demo Asset"); - assetRequest.set("asset", assetNode); - var dataAddressNode = MAPPER.createObjectNode(); - var propertiesNode = MAPPER.createObjectNode(); - dataAddressNode.set("properties", propertiesNode); - propertiesNode.put("type", "HttpData"); - propertiesNode.put("baseUrl", orderUrl); - assetRequest.set("dataAddress", dataAddressNode); - return assetRequest; + public ObjectNode buildBasicDSPCatalogRequestBody(String counterPartyDspUrl, Map filter) { + var objectNode = getEDCContextObject(); + objectNode.put("protocol", "dataspace-protocol-http"); + objectNode.put("@type", "CatalogRequest"); + objectNode.put("counterPartyAddress", counterPartyDspUrl); + if (filter != null && !filter.isEmpty()) { + var querySpecNode = MAPPER.createObjectNode(); + objectNode.set("querySpec", querySpecNode); + for (var entry : filter.entrySet()) { + querySpecNode.put(entry.getKey(), entry.getValue()); + } + } + return objectNode; } /** - * Build an EDC request body for the creation of a simple USE policy. + * Build a request body for a request to register an api method as an asset in DSP protocol. * - * @param orderId id of the policy to create (currently has to match contract and asset id). - * @return JsonNode used as requestBody for policy creation. + * @param apiMethod The API method you want to register + * @return The request body */ - public JsonNode buildPolicyRequestBody(String orderId) { - var policyNode = MAPPER.createObjectNode(); - var policySubNode = MAPPER.createObjectNode(); - policySubNode.set("prohibitions", MAPPER.createArrayNode()); - policySubNode.set("obligations", MAPPER.createArrayNode()); - var permissionArray = MAPPER.createArrayNode(); - var permissionNode = MAPPER.createObjectNode(); - permissionNode.put("edctype", "dataspaceconnector:permission"); - permissionNode.set("constraints", MAPPER.createArrayNode()); - var actionNode = MAPPER.createObjectNode(); - actionNode.put("type", "USE"); - permissionNode.set("action", actionNode); - permissionArray.add(permissionNode); - policySubNode.set("permissions", permissionArray); - policyNode.put("id", orderId); - policyNode.set("policy", policySubNode); - return policyNode; + public JsonNode buildDSPCreateAssetBody(DT_ApiMethodEnum apiMethod) { + var body = MAPPER.createObjectNode(); + var context = MAPPER.createObjectNode(); + context.put(VOCAB_KEY, EDC_NAMESPACE); + context.put("cx-taxo", CX_TAXO_NAMESPACE); + context.put("cx-common", CX_COMMON_NAMESPACE); + context.put("dct", DCT_NAMESPACE); + body.set("@context", context); + + String apiId = variablesService.getApiAssetId(apiMethod); + body.put("@id", apiId); + var properties = MAPPER.createObjectNode(); + properties.put("asset:prop:type", "api"); + properties.put("asset:prop:apibusinessobject", "product-stock"); + properties.put("asset:prop:version", variablesService.getPurisApiVersion()); + properties.put("asset:prop:apipurpose", apiMethod.PURPOSE); + body.set("properties", properties); + var edcProperties = MAPPER.createObjectNode(); + edcProperties.put(CX_VERSION_KEY, CX_VERSION_NUMBER); + var typeNode = MAPPER.createObjectNode(); + String taxonomy = DT_ApiMethodEnum.REQUEST == apiMethod ? "ProductStockRequestApi" : "ProductStockResponseApi"; + typeNode.put("@id", CX_TAXO_NAMESPACE + taxonomy); + edcProperties.set(PURL_TYPE_KEY, typeNode); + + var dataAddress = MAPPER.createObjectNode(); + String url = apiMethod == DT_ApiMethodEnum.REQUEST ? variablesService.getRequestServerEndpoint() : variablesService.getResponseServerEndpoint(); + dataAddress.put("baseUrl", url); + dataAddress.put("type", "HttpData"); + dataAddress.put("proxyPath", "true"); + dataAddress.put("proxyBody", "true"); + dataAddress.put("proxyMethod", "true"); + body.set("dataAddress", dataAddress); + return body; } + /** - * Build an EDC request body for the creation of a contract. + * Creates a request body for registering a public policy in DSP protocol that contains no + * restrictions whatsoever. * - * @param orderId id of the contract to create (currently has to match policy and asset id). - * @return JsonNode used as requestBody for contract creation. + * @return The request body */ - public JsonNode buildContractRequestBody(String orderId) { - var contractNode = MAPPER.createObjectNode(); - contractNode.put("id", orderId); - contractNode.put("accessPolicyId", orderId); - contractNode.put("contractPolicyId", orderId); - var criteriaArray = MAPPER.createArrayNode(); - var criteriaNode = MAPPER.createObjectNode(); - criteriaNode.put("operandLeft", "asset:prop:id"); - criteriaNode.put("operator", "="); - criteriaNode.put("operandRight", orderId); - criteriaArray.add(criteriaNode); - contractNode.set("criteria", criteriaArray); - return contractNode; + public JsonNode buildPublicDSPPolicy() { + var body = MAPPER.createObjectNode(); + var context = MAPPER.createObjectNode(); + context.put("odrl", ODRL_NAMESPACE); + body.set("@context", context); + body.put("@type", "PolicyDefinitionRequestDto"); + body.put("@id", publicPolicyId); + var policy = MAPPER.createObjectNode(); + policy.put("@type", "set"); + var emptyArray = MAPPER.createArrayNode(); + policy.set("odrl:permission", emptyArray); + policy.set("odrl:prohibition", emptyArray); + policy.set("odrl:obligation", emptyArray); + body.set("policy", policy); + return body; } /** - * Build an EDC request body used for starting a negotiation. - * @param connectorAddress ids url of the negotiation counterparty. - * @param contractDefinitionId id of a contract offer given by the counterparty. - * @param assetId id of the negotiations target asset. - * @return JsonNode used as requestBody for an EDC negotiation request. + * Creates the request body for registering a simple contract definition. + * Relies on the policy that is created via the buildPublicDSPPolicy() method. + * + * @return The request body */ - public JsonNode buildNegotiationRequestBody(String connectorAddress, - String contractDefinitionId, - String assetId) { - var negotiationNode = MAPPER.createObjectNode(); - negotiationNode.put("connectorId", "foo"); - negotiationNode.put("connectorAddress", connectorAddress); - negotiationNode.put("protocol", "ids-multipart"); + public JsonNode buildDSPContractDefinitionWithPublicPolicy() { + var body = getEDCContextObject(); + body.put("@id", publicContractDefinitionId); + body.put("accessPolicyId", publicPolicyId); + body.put("contractPolicyId", publicPolicyId); + body.set("assetsSelector", MAPPER.createArrayNode()); + return body; + } + + /** + * Creates the request body for initiating a negotiation in DSP protocol. + * Will use the policy terms as specified in the catalog item. + * + * @param partner The Partner to negotiate with + * @param dcatCatalogItem The catalog entry that describes the target asset. + * @return The request body + */ + public ObjectNode buildDSPAssetNegotiation(Partner partner, JsonNode dcatCatalogItem) { + var objectNode = MAPPER.createObjectNode(); + var contextNode = MAPPER.createObjectNode(); + contextNode.put(VOCAB_KEY, EDC_NAMESPACE); + contextNode.put("odrl", ODRL_NAMESPACE); + objectNode.set("@context", contextNode); + objectNode.put("@type", "NegotiationInitiateRequestDto"); + objectNode.put("connectorId", partner.getBpnl()); + objectNode.put("connectorAddress", partner.getEdcUrl()); + objectNode.put("consumerId", variablesService.getOwnBpnl()); + objectNode.put("providerId", partner.getBpnl()); + objectNode.put("protocol", "dataspace-protocol-http"); + String assetId = dcatCatalogItem.get("@id").asText(); + var policyNode = dcatCatalogItem.get("odrl:hasPolicy"); var offerNode = MAPPER.createObjectNode(); - offerNode.put("offerId", contractDefinitionId); + String offerId = policyNode.get("@id").asText(); + offerNode.put("offerId", offerId); offerNode.put("assetId", assetId); - var policyNode = MAPPER.createObjectNode(); - policyNode.put("uid", assetId); - policyNode.set("prohibitions", MAPPER.createArrayNode()); - policyNode.set("obligations", MAPPER.createArrayNode()); - var permissionArray = MAPPER.createArrayNode(); - var permissionNode = MAPPER.createObjectNode(); - permissionNode.put("edctype", "dataspaceconnector:permission"); - permissionNode.put("target", assetId); - permissionNode.set("constraints", MAPPER.createArrayNode()); - var actionNode = MAPPER.createObjectNode(); - actionNode.put("type", "USE"); - permissionNode.set("action", actionNode); - permissionArray.add(permissionNode); - policyNode.set("permissions", permissionArray); offerNode.set("policy", policyNode); - negotiationNode.set("offer", offerNode); - return negotiationNode; + objectNode.set("offer", offerNode); + return objectNode; } /** - * Build an EDC request body used for starting a transfer. + * Creates the request body for requesting a data pull transfer using the + * DSP protocol and the Tractus-X-EDC. * - * @param transferId id created for the transferprocess. - * @param connectorAddress ids url of the negotiation counterparty. - * @param contractId id of the negotiated contract. - * @param orderId id of the transfers target asset. - * @return JsonNode used as requestBody for an EDC transfer request. + * @param partner The Partner who controls the target asset + * @param contractID The contractId + * @param assetId The assetId + * @return The request body */ - public JsonNode buildTransferRequestBody(String transferId, - String connectorAddress, - String contractId, - String orderId) { - var transferNode = MAPPER.createObjectNode(); - transferNode.put("edctype", "dataspaceconnector:datarequest"); - transferNode.put("protocol", "ids-multipart"); - transferNode.put("id", transferId); - transferNode.put("connectorId", "foo"); - transferNode.put("connectorAddress", connectorAddress); - transferNode.put("contractId", contractId); - transferNode.put("assetId", orderId); - transferNode.put("managedResources", "false"); - var destinationNode = MAPPER.createObjectNode(); - var propertiesNode = MAPPER.createObjectNode(); - propertiesNode.put("type", "HttpProxy"); - destinationNode.set("properties", propertiesNode); - transferNode.set("dataDestination", destinationNode); - var transferTypeNode = MAPPER.createObjectNode(); - transferTypeNode.put("contentType", "application/octet-stream"); - transferTypeNode.put("isFinite", true); - transferNode.set("transferType", transferTypeNode); - transferNode.put("managedResources", false); - propertiesNode = MAPPER.createObjectNode(); - propertiesNode.put("receiver.http.endpoint", endpointDataReferenceEndpoint); - transferNode.set("properties", propertiesNode); - - return transferNode; + public JsonNode buildDSPDataPullRequestBody(Partner partner, String contractID, String assetId) { + var body = getEDCContextObject(); + body.put("@type", "TransferRequestDto"); + body.put("connectorId", partner.getBpnl()); + body.put("connectorAddress", partner.getEdcUrl()); + body.put("contractId", contractID); + body.put("assetId", assetId); + body.put("protocol", "dataspace-protocol-http"); + var dataDestination = MAPPER.createObjectNode(); + dataDestination.put("type", "HttpProxy"); + body.set("dataDestination", dataDestination); + var callbackAddress = MAPPER.createObjectNode(); + callbackAddress.put("uri", variablesService.getEdrEndpoint()); + callbackAddress.put("transactional", false); + var events = MAPPER.createArrayNode(); + events.add("contract.negotiation"); + events.add("transfer.process"); + callbackAddress.set("events", events); + var callbackAddresses = MAPPER.createArrayNode(); + callbackAddresses.add(callbackAddress); + body.set("callbackAddresses", callbackAddresses); + return body; } /** - * Builds a CreateAssetDto for an API + * A helper method returning a basic request object that can be used to build other + * specific request bodies. * - * @param method api method to create - * @param apiBaseUrl api baseUrl to get the data at - * @return assetDto for creation. + * @return A request body stub */ - public CreateAssetDto buildCreateAssetDtoForApi(DT_ApiMethodEnum method, - String apiBaseUrl) { - AssetPropertiesDto apiAssetPropertiesDto = new AssetPropertiesDto(); - apiAssetPropertiesDto.setApiBusinessObject(DT_ApiBusinessObjectEnum.PRODUCT_STOCK.PROPERTIES_DESCRIPTION); - apiAssetPropertiesDto.setApiPurpose(method.PURPOSE); - apiAssetPropertiesDto.setContentType("application/json"); - apiAssetPropertiesDto.setId(variablesService.getApiAssetId(method)); - apiAssetPropertiesDto.setName(method.NAME); - apiAssetPropertiesDto.setType(DT_AssetTypeEnum.api); - apiAssetPropertiesDto.setUseCase(DT_UseCaseEnum.PURIS); - apiAssetPropertiesDto.setVersion(variablesService.getPurisApiVersion()); - - AssetDto apiAssetDto = new AssetDto(); - apiAssetDto.setPropertiesDto(apiAssetPropertiesDto); - - DataAddressPropertiesDto apiDataAddressPropertiesDto = - new DataAddressPropertiesDto(); - apiDataAddressPropertiesDto.setBaseUrl(apiBaseUrl); - apiDataAddressPropertiesDto.setType(DT_DataAddressTypeEnum.HttpData); - apiDataAddressPropertiesDto.setProxyBody(true); - apiDataAddressPropertiesDto.setProxyMethod(true); - - DataAddressDto apiDataAddressDto = new DataAddressDto(); - apiDataAddressDto.setDataAddressPropertiesDto(apiDataAddressPropertiesDto); - - CreateAssetDto createApiAssetDto = new CreateAssetDto(); - createApiAssetDto.setAssetDto(apiAssetDto); - createApiAssetDto.setDataAddressDto(apiDataAddressDto); - - return createApiAssetDto; + private ObjectNode getEDCContextObject() { + ObjectNode node = MAPPER.createObjectNode(); + var context = MAPPER.createObjectNode(); + context.put(VOCAB_KEY, EDC_NAMESPACE); + node.set("@context", context); + return node; } + } diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockRequestApiController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockRequestApiController.java index 759bb380..ad20fe30 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockRequestApiController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockRequestApiController.java @@ -34,6 +34,7 @@ import org.eclipse.tractusx.puris.backend.common.api.domain.model.datatype.DT_RequestStateEnum; import org.eclipse.tractusx.puris.backend.common.api.logic.dto.MessageHeaderDto; import org.eclipse.tractusx.puris.backend.common.api.logic.dto.SuccessfulRequestDto; +import org.eclipse.tractusx.puris.backend.common.api.logic.service.VariablesService; import org.eclipse.tractusx.puris.backend.stock.domain.model.ProductStockRequest; import org.eclipse.tractusx.puris.backend.stock.logic.service.ProductStockRequestApiServiceImpl; import org.eclipse.tractusx.puris.backend.stock.logic.service.ProductStockRequestService; @@ -54,16 +55,13 @@ public class ProductStockRequestApiController { @Autowired - ModelMapper modelMapper; + private ObjectMapper objectMapper; @Autowired - ObjectMapper objectMapper; + private ProductStockRequestService productStockRequestService; @Autowired - ProductStockRequestService productStockRequestService; - - @Autowired - ProductStockRequestApiServiceImpl requestApiService; + private ProductStockRequestApiServiceImpl requestApiService; @PostMapping("request") @Operation(summary = "This endpoint receives the product stock requests from a consumer.", diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockResponseApiController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockResponseApiController.java index 438c4f4e..55b19b83 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockResponseApiController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/ProductStockResponseApiController.java @@ -31,18 +31,15 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.puris.backend.common.api.domain.model.datatype.DT_RequestStateEnum; import org.eclipse.tractusx.puris.backend.common.api.logic.dto.SuccessfulRequestDto; +import org.eclipse.tractusx.puris.backend.common.api.logic.service.VariablesService; import org.eclipse.tractusx.puris.backend.stock.domain.model.ProductStockRequest; import org.eclipse.tractusx.puris.backend.stock.domain.model.ProductStockResponse; import org.eclipse.tractusx.puris.backend.stock.logic.service.ProductStockRequestService; import org.eclipse.tractusx.puris.backend.stock.logic.service.ProductStockResponseApiServiceImpl; -import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.UUID; @@ -55,17 +52,13 @@ public class ProductStockResponseApiController { @Autowired - ProductStockRequestService productStockRequestService; + private ProductStockRequestService productStockRequestService; @Autowired - ModelMapper modelMapper; + private ObjectMapper objectMapper; @Autowired - ObjectMapper objectMapper; - - @Autowired - ProductStockResponseApiServiceImpl productStockResponseApiService; - + private ProductStockResponseApiServiceImpl productStockResponseApiService; @PostMapping("response") @Operation(summary = "This endpoint receives the responses to the consumer's requests.", diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java index e1222085..69d2346c 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java @@ -287,15 +287,12 @@ public List getCustomerPartnersOrderingMaterial(@RequestParam String "when the corresponding responses will be available. As soon as a response arrives, it will be available via a " + "call to the GET partner-product-stocks endpoint.") public List triggerPartnerProductStockUpdateForMaterial(@RequestParam String ownMaterialNumber) { - Material materialEntity = materialService.findByOwnMaterialNumber(ownMaterialNumber); log.info("Found material: " + (materialEntity != null) + " " + ownMaterialNumber); - List allSupplierPartnerEntities = mprService.findAllSuppliersForOwnMaterialNumber(ownMaterialNumber); for (Partner supplierPartner : allSupplierPartnerEntities) { - - productStockRequestApiService.request(materialEntity, supplierPartner); + productStockRequestApiService.doRequest(materialEntity, supplierPartner); } return allSupplierPartnerEntities.stream()