Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/dtrcontract reusage #382

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
</parent>
<groupId>org.eclipse.tractusx.puris</groupId>
<artifactId>puris-backend</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
<name>puris-backend</name>
<description>PURIS Backend</description>
<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,18 @@ public Integer updateProduct(Material material, List<MaterialPartnerRelation> mp
}

/**
* Call this method when a new Material with a product flag was created in your MaterialService - or if a product
* flag was later added to an existing Material.
* Call this method when you need to register a product at the DTR for which there was no product AAS registered
* previously.
* <p>
* A new AAS will be registered for this Material at your dDTR.
*
* @param material The Material
* @param mprs The list of all MaterialProductRelations that exist with customers of the given Material
* @return The HTTP response code from the DTR, or null if none was received
*/
public Integer registerProductAtDtr(Material material) {
public Integer registerProductAtDtr(Material material, List<MaterialPartnerRelation> mprs) {
String twinId = digitalTwinMappingService.get(material).getProductTwinId();
var body = dtrRequestBodyBuilder.createProductRegistrationRequestBody(material, twinId, List.of());
var body = dtrRequestBodyBuilder.createProductRegistrationRequestBody(material, twinId, mprs);
try (var response = sendDtrPostRequest(body, List.of("api", "v3", "shell-descriptors"))) {
return response.code();
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.SubmodelType;
Expand Down Expand Up @@ -178,7 +177,7 @@ public boolean registerAssetsInitially() {
* Utility method to register policy- and contract-definitions for both the
* REQUEST and the RESPONSE-Api specifically for the given partner.
*
* @param partner the partner
* @param partner The partner
* @return true, if all registrations ran successfully
*/
public boolean createPolicyAndContractDefForPartner(Partner partner) {
Expand Down Expand Up @@ -227,7 +226,7 @@ private boolean createDtrContractDefinitionForPartner(Partner partner) {
* 1. The BPNL of the requesting connector is equal to the BPNL of the partner
* 2. There's a CX membership credential present
*
* @param partner the partner to create the policy for
* @param partner The partner to create the policy for
* @return true, if registration ran successfully
*/
private boolean createBpnlAndMembershipPolicyDefinitionForPartner(Partner partner) {
Expand Down Expand Up @@ -475,8 +474,8 @@ public Response getAllTransfers() throws IOException {
* Sends a request to the own control plane in order to receive
* the contract agreement with the given contractAgreementId
*
* @param contractAgreementId the contractAgreement's Id
* @return the contractAgreement
* @param contractAgreementId The contractAgreement's Id
* @return The contractAgreement
* @throws IOException If the connection to your control plane fails
*/
public String getContractAgreement(String contractAgreementId) throws IOException {
Expand Down Expand Up @@ -558,7 +557,7 @@ private JsonNode getSubmodelFromPartner(MaterialPartnerRelation mpr, SubmodelTyp
}
}
if (!partner.getEdcUrl().equals(partnerDspUrl)) {
log.warn("Divering Edc Urls for Partner: " + partner.getBpnl() + " and type " + type);
log.warn("Diverging Edc Urls for Partner: " + partner.getBpnl() + " and type " + type);
log.warn("General Partner EdcUrl: " + partner.getEdcUrl());
log.warn("URL from AAS: " + partnerDspUrl);
}
Expand All @@ -568,13 +567,6 @@ private JsonNode getSubmodelFromPartner(MaterialPartnerRelation mpr, SubmodelTyp
String transferId = transferResp.get("@id").asText();
// try proxy pull and terminate request
try {
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
transferResp = getTransferState(transferId);
if ("STARTED".equals(transferResp.get("state").asText())) {
break;
}
}
EdrDto edrDto = getAndAwaitEdrDto(transferId);
log.info("Received EDR data for " + assetId + " with " + partner.getEdcUrl());
if (edrDto == null) {
Expand Down Expand Up @@ -610,17 +602,24 @@ private JsonNode getSubmodelFromPartner(MaterialPartnerRelation mpr, SubmodelTyp
}

/**
* get the EDR via edr api and retry multiple times in case the EDR has not yet been available
* Get the EDR via edr api and retry multiple times in case the EDR has not yet been available
*
* @param transferProcessId to get the EDR for, not null
* @return edr received, or null if not yet available
* @throws InterruptedException if thread was not able to sleep
*/
private @Nullable EdrDto getAndAwaitEdrDto(String transferProcessId) throws InterruptedException {
private @Nullable EdrDto getAndAwaitEdrDto(String transferProcessId) throws InterruptedException, IOException {
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
JsonNode transferResp = getTransferState(transferProcessId);
if ("STARTED".equals(transferResp.get("state").asText())) {
break;
}
}
EdrDto edrDto = null;
// retry, if Data Space Protocol / Data Plane Provisioning communication needs time to prepare
for (int i = 0; i < 100; i++) {
edrDto = getEdrForTransferProcessId(transferProcessId);
edrDto = getEdrForTransferProcessId(transferProcessId, 2);
if (edrDto != null) {
break;
}
Expand Down Expand Up @@ -747,7 +746,7 @@ private SubmodelData fetchSubmodelData(MaterialPartnerRelation mpr, String seman
}

/**
* quries the dtr of a pratner for the given mpr / material and returns submodel descriptors
* Queries the dtr of a partner for the given mpr / material and returns submodel descriptors
* <p>
* Method assumes that the query at dtr only finds one shell (else take first entry)
*
Expand All @@ -762,7 +761,11 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
log.error("AasSubmodelDescriptors Request failed for " + manufacturerPartId + " and " + manufacturerId);
return null;
}
boolean failed = true;

// A criticalFailure indicates that the connection to the partner's DTR could not be established at all
// or delivers a completely unexpected response. This is assumed to be true at first, and will be set to false
// if a response was received that contains the expected answer or at least an empty result.
boolean criticalFailure = true;
Partner partner = mpr.getPartner();
try {
var dtrContractData = edcContractMappingService.getDtrAssetAndContractId(partner);
Expand All @@ -779,13 +782,6 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
var transferResp = initiateProxyPullTransfer(partner, contractId, assetId);
String transferId = transferResp.get("@id").asText();
try {
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
transferResp = getTransferState(transferId);
if ("STARTED".equals(transferResp.get("state").asText())) {
break;
}
}
EdrDto edrDto = getAndAwaitEdrDto(transferId);
if (edrDto == null) {
log.error("Failed to obtain EDR data for " + assetId + " with " + partner.getEdcUrl());
Expand Down Expand Up @@ -834,7 +830,7 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
var aasJson = objectMapper.readTree(body2String);
var submodelDescriptors = aasJson.get("submodelDescriptors");
if (submodelDescriptors != null) {
failed = false;
criticalFailure = false;
tom-rm-meyer-ISST marked this conversation as resolved.
Show resolved Hide resolved
return submodelDescriptors;
} else {
log.warn("No SubmodelDescriptors found in DTR shell-descriptors response:\n" + aasJson.toPrettyString());
Expand All @@ -844,6 +840,7 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
if (resultArray != null) {
if (resultArray.isArray() && resultArray.isEmpty()) {
log.warn("Empty Result array received");
criticalFailure = false;
} else {
log.warn("Unexpected Response for DTR lookup with query " + query + "\n" + resultArray.toPrettyString());
}
Expand All @@ -862,7 +859,7 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
log.error("Error in AasSubmodelDescriptor Request for " + mpr + " and manufacturerPartId " + manufacturerPartId, e);
return getAasSubmodelDescriptors(manufacturerPartId, manufacturerId, mpr, --retries);
} finally {
if (failed) {
if (criticalFailure) {
log.warn("Invalidating DTR contract data");
edcContractMappingService.putDtrContractData(partner, null, null);
}
Expand All @@ -879,27 +876,38 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
* @param transferProcessId to get the EDR for
* @return unpersisted EdrDto.
*/
private EdrDto getEdrForTransferProcessId(String transferProcessId) {

private EdrDto getEdrForTransferProcessId(String transferProcessId, int retries) {
if (retries < 0) return null;
boolean failed = true;
try (Response response = sendGetRequest(
List.of("v2", "edrs", transferProcessId, "dataaddress"),
Map.of("auto_refresh", "true"))
) {
ObjectNode responseObject = (ObjectNode) objectMapper.readTree(response.body().string());

String dataPlaneEndpoint = responseObject.get("endpoint").asText();
String authToken = responseObject.get("authorization").asText();

EdrDto edr = new EdrDto("Authorization", authToken, dataPlaneEndpoint);
log.debug("Requested EDR successfully: {}", edr);

return edr;

} catch (IOException e) {
if (response.isSuccessful() && response.body() != null) {
JsonNode responseObject = objectMapper.readTree(response.body().string());

String dataPlaneEndpoint = responseObject.get("endpoint").asText();
String authToken = responseObject.get("authorization").asText();
if (dataPlaneEndpoint != null && authToken != null) {
EdrDto edr = new EdrDto("Authorization", authToken, dataPlaneEndpoint);
log.debug("Requested EDR successfully: {}", edr);
failed = false;
return edr;
}
}
} catch (Exception e) {
log.error("EDR token for transfer process with ID {} could not be obtained", transferProcessId);
} finally {
if (failed && --retries >= 0) {
try {
Thread.sleep(100);
} catch (Exception e1) {
log.error("Sleep interrupted", e1);
}
}
}
return getEdrForTransferProcessId(transferProcessId, retries);

return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,12 @@ public class DeliveryInformationSammMapper {
@Autowired
private MaterialService materialService;

public DeliveryInformation ownDeliveryToSamm(List<OwnDelivery> deliveryList) {
if (deliveryList == null || deliveryList.isEmpty()) {
log.warn("Can't map empty list");
return null;
}
Partner partner = deliveryList.get(0).getPartner();
public DeliveryInformation ownDeliveryToSamm(List<OwnDelivery> deliveryList, Partner partner, Material material) {
if (deliveryList.stream().anyMatch(deli -> !deli.getPartner().equals(partner))) {
log.warn("Can't map delivery list with different partners");
return null;
}
Material material = deliveryList.get(0).getMaterial();

if (deliveryList.stream().anyMatch(deli -> !deli.getMaterial().equals(material))) {
log.warn("Can't map delivery list with different materials");
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,11 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;

import org.eclipse.tractusx.puris.backend.common.edc.domain.model.SubmodelType;
import org.eclipse.tractusx.puris.backend.common.edc.logic.service.EdcAdapterService;
import org.eclipse.tractusx.puris.backend.delivery.logic.adapter.DeliveryInformationSammMapper;
import org.eclipse.tractusx.puris.backend.delivery.logic.dto.deliverysamm.DeliveryInformation;
import org.eclipse.tractusx.puris.backend.masterdata.domain.model.Material;
import org.eclipse.tractusx.puris.backend.masterdata.domain.model.MaterialPartnerRelation;
import org.eclipse.tractusx.puris.backend.masterdata.domain.model.Partner;
import org.eclipse.tractusx.puris.backend.masterdata.logic.service.MaterialPartnerRelationService;
import org.eclipse.tractusx.puris.backend.masterdata.logic.service.MaterialService;
Expand All @@ -39,6 +35,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@Slf4j
/**
Expand Down Expand Up @@ -68,22 +66,41 @@ public DeliveryInformation handleDeliverySubmodelRequest(String bpnl, String mat
log.error("Unknown Partner BPNL " + bpnl);
return null;
}
MaterialPartnerRelation mpr = mprService.findByPartnerAndPartnerCXNumber(partner, materialNumberCx);

Material material = materialService.findByMaterialNumberCx(materialNumberCx);
if (material == null && mpr == null) {
if (material == null) {
// Could not identify partner cx number. I.e. we do not have that partner's
// CX id in one of our MaterialPartnerRelation entities. Try to fix this by
// looking for MPR's, where that partner is a supplier and where we don't have
// a partnerCXId yet. Of course this can only work if there was previously an MPR
// created, but for some unforeseen reason, the initial PartTypeRetrieval didn't succeed.
log.warn("Could not find " + materialNumberCx + " from partner " + partner.getBpnl());
github-advanced-security[bot] marked this conversation as resolved.
Dismissed
Show resolved Hide resolved
mprService.triggerPartTypeRetrievalTask(partner);
material = materialService.findByMaterialNumberCx(materialNumberCx);
}

if (material == null) {
log.error("Unknown Material " + materialNumberCx);
return null;
}
if (material == null) {
material = mpr.getMaterial();

var mpr = mprService.find(material,partner);
if (mpr == null || !mpr.isPartnerSuppliesMaterial()) {
// only send an answer if partner is registered as supplier
return null;
}

var currentDeliveries = ownDeliveryService.findAllByFilters(Optional.of(material.getOwnMaterialNumber()), Optional.empty(), Optional.of(partner.getBpnl()));
return sammMapper.ownDeliveryToSamm(currentDeliveries);
return sammMapper.ownDeliveryToSamm(currentDeliveries, partner, material);
}

public void doReportedDeliveryRequest(Partner partner, Material material) {
try {
var mpr = mprService.find(material, partner);
if (mpr.getPartnerCXNumber() == null) {
mprService.triggerPartTypeRetrievalTask(partner);
mpr = mprService.find(material, partner);
}
var direction = material.isMaterialFlag() ? DirectionCharacteristic.OUTBOUND : DirectionCharacteristic.INBOUND;
var data = edcAdapterService.doSubmodelRequest(SubmodelType.DELIVERY, mpr, direction, 1);
var samm = objectMapper.treeToValue(data, DeliveryInformation.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,7 @@ public class ShortTermMaterialDemandSammMapper {
@Autowired
private MaterialService materialService;

public ShortTermMaterialDemand ownDemandToSamm(List<OwnDemand> demandList) {
if (demandList == null || demandList.isEmpty()) {
log.warn("Can't map empty list");
return null;
}
Partner partner = demandList.get(0).getPartner();
Material material = demandList.get(0).getMaterial();
public ShortTermMaterialDemand ownDemandToSamm(List<OwnDemand> demandList,Partner partner, Material material) {
if (demandList.stream().anyMatch(dem -> !dem.getPartner().equals(partner))) {
log.warn("Can't map demand list with different partners");
return null;
Expand Down
Loading
Loading