diff --git a/src/main/java/org/folio/inventory/client/util/ClientWrapperUtil.java b/src/main/java/org/folio/inventory/client/util/ClientWrapperUtil.java new file mode 100644 index 000000000..dabe57a6d --- /dev/null +++ b/src/main/java/org/folio/inventory/client/util/ClientWrapperUtil.java @@ -0,0 +1,85 @@ +package org.folio.inventory.client.util; + +import io.vertx.core.buffer.Buffer; +import io.vertx.ext.web.client.HttpRequest; +import io.vertx.ext.web.client.WebClient; +import org.folio.rest.tools.ClientHelpers; +import io.vertx.core.http.HttpMethod; + +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TENANT; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TOKEN; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_URL; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_USER_ID; + +/** + * Utility class for handling client wrapper operations. + */ +public final class ClientWrapperUtil { + public static final String CONTENT_TYPE = "Content-type"; + public static final String APPLICATION_JSON = "application/json"; + public static final String ACCEPT = "Accept"; + public static final String APPLICATION_JSON_TEXT_PLAIN = "application/json,text/plain"; + + private ClientWrapperUtil() { + } + + /** + * Creates an HTTP request with the specified method and URL, and populates it with Okapi headers. + * + * @param method the HTTP method to use (e.g., GET, POST, PUT) + * @param url the URL for the request + * @param okapiUrl the Okapi URL + * @param tenantId the tenant ID + * @param token the authentication token + * @param userId the user ID + * @param webClient the WebClient instance to use for creating the request + * @return the created HTTP request with populated headers + */ + public static HttpRequest createRequest(HttpMethod method, String url, String okapiUrl, String tenantId, + String token, String userId, WebClient webClient) { + HttpRequest request = webClient.requestAbs(method, url); + populateOkapiHeaders(request, okapiUrl, tenantId, token, userId); + return request; + } + + /** + * Converts an object to a JSON buffer. + * + * @param object the object to convert + * @return the JSON buffer + */ + public static Buffer getBuffer(Object object) { + Buffer buffer = Buffer.buffer(); + if (object != null) { + buffer.appendString(ClientHelpers.pojo2json(object)); + } + return buffer; + } + + /** + * Populates the Okapi headers for the given HTTP request. + * + * @param request the HTTP request to populate headers for + * @param okapiUrl the Okapi URL + * @param tenantId the tenant ID + * @param token the authentication token + * @param userId the user ID + */ + private static void populateOkapiHeaders(HttpRequest request, String okapiUrl, String tenantId, String token, String userId) { + request.putHeader(CONTENT_TYPE, APPLICATION_JSON); + request.putHeader(ACCEPT, APPLICATION_JSON_TEXT_PLAIN); + + if (tenantId != null) { + request.putHeader(OKAPI_TOKEN, token); + request.putHeader(OKAPI_TENANT, tenantId); + } + + if (userId != null) { + request.putHeader(OKAPI_USER_ID, userId); + } + + if (okapiUrl != null) { + request.putHeader(OKAPI_URL, okapiUrl); + } + } +} diff --git a/src/main/java/org/folio/inventory/client/wrappers/ChangeManagerClientWrapper.java b/src/main/java/org/folio/inventory/client/wrappers/ChangeManagerClientWrapper.java new file mode 100644 index 000000000..ad20f9255 --- /dev/null +++ b/src/main/java/org/folio/inventory/client/wrappers/ChangeManagerClientWrapper.java @@ -0,0 +1,84 @@ +package org.folio.inventory.client.wrappers; + +import io.vertx.core.Future; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import org.folio.rest.client.ChangeManagerClient; +import org.folio.rest.jaxrs.model.InitJobExecutionsRqDto; +import org.folio.rest.jaxrs.model.JobExecution; +import org.folio.rest.jaxrs.model.JobProfileInfo; +import org.folio.rest.jaxrs.model.ParsedRecordDto; +import org.folio.rest.jaxrs.model.RawRecordsDto; +import org.folio.rest.jaxrs.model.StatusDto; + +import static org.folio.inventory.client.util.ClientWrapperUtil.createRequest; +import static org.folio.inventory.client.util.ClientWrapperUtil.getBuffer; + +/** + * Wrapper class for ChangeManagerClient to handle POST and PUT HTTP requests with x-okapi-user-id header. + */ +public class ChangeManagerClientWrapper extends ChangeManagerClient { + private final String tenantId; + private final String token; + private final String okapiUrl; + private final String userId; + private final WebClient webClient; + public static final String CHANGE_MANAGER_JOB_EXECUTIONS = "/change-manager/jobExecutions/"; + public static final String CHANGE_MANAGER_PARSED_RECORDS = "/change-manager/parsedRecords/"; + + public ChangeManagerClientWrapper(String okapiUrl, String tenantId, String token, String userId, HttpClient httpClient) { + super(okapiUrl, tenantId, token, httpClient); + this.okapiUrl = okapiUrl; + this.tenantId = tenantId; + this.token = token; + this.userId = userId; + this.webClient = WebClient.wrap(httpClient); + } + + @Override + public Future> postChangeManagerJobExecutions(InitJobExecutionsRqDto initJobExecutionsRqDto) { + return createRequest(HttpMethod.POST, okapiUrl + "/change-manager/jobExecutions", okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(initJobExecutionsRqDto)); + } + + @Override + public Future> postChangeManagerJobExecutionsRecordsById(String id, boolean acceptInstanceId, RawRecordsDto rawRecordsDto) { + StringBuilder queryParams = new StringBuilder("?"); + queryParams.append("acceptInstanceId="); + queryParams.append(acceptInstanceId); + + return createRequest(HttpMethod.POST, okapiUrl + CHANGE_MANAGER_JOB_EXECUTIONS + id + "/records" + queryParams, + okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(rawRecordsDto)); + } + + @Override + public Future> putChangeManagerJobExecutionsById(String id, JobExecution jobExecution) { + return createRequest(HttpMethod.PUT, okapiUrl + CHANGE_MANAGER_JOB_EXECUTIONS + id, okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(jobExecution)); + } + + @Override + public Future> putChangeManagerJobExecutionsJobProfileById(String id, JobProfileInfo jobProfileInfo) { + return createRequest(HttpMethod.PUT, okapiUrl + CHANGE_MANAGER_JOB_EXECUTIONS + id + "/jobProfile", + okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(jobProfileInfo)); + } + + @Override + public Future> putChangeManagerJobExecutionsStatusById(String id, StatusDto statusDto) { + return createRequest(HttpMethod.PUT, okapiUrl + CHANGE_MANAGER_JOB_EXECUTIONS + id + "/status", + okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(statusDto)); + } + + @Override + public Future> putChangeManagerParsedRecordsById(String id, ParsedRecordDto parsedRecordDto) { + return createRequest(HttpMethod.PUT, okapiUrl + CHANGE_MANAGER_PARSED_RECORDS + id, + okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(parsedRecordDto)); + } +} diff --git a/src/main/java/org/folio/inventory/client/wrappers/SourceStorageRecordsClientWrapper.java b/src/main/java/org/folio/inventory/client/wrappers/SourceStorageRecordsClientWrapper.java new file mode 100644 index 000000000..2754faff1 --- /dev/null +++ b/src/main/java/org/folio/inventory/client/wrappers/SourceStorageRecordsClientWrapper.java @@ -0,0 +1,71 @@ +package org.folio.inventory.client.wrappers; + +import io.vertx.core.Future; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import org.folio.rest.client.SourceStorageRecordsClient; +import org.folio.rest.jaxrs.model.Record; +import org.folio.util.PercentCodec; + +import static org.folio.inventory.client.util.ClientWrapperUtil.createRequest; +import static org.folio.inventory.client.util.ClientWrapperUtil.getBuffer; + +/** + * Wrapper class for SourceStorageRecordsClient to handle POST and PUT HTTP requests with x-okapi-user-id header. + */ +public class SourceStorageRecordsClientWrapper extends SourceStorageRecordsClient { + private final String tenantId; + private final String token; + private final String okapiUrl; + private final String userId; + private final WebClient webClient; + public static final String SOURCE_STORAGE_RECORDS = "/source-storage/records/"; + + public SourceStorageRecordsClientWrapper(String okapiUrl, String tenantId, String token, String userId, HttpClient httpClient) { + super(okapiUrl, tenantId, token, httpClient); + this.okapiUrl = okapiUrl; + this.tenantId = tenantId; + this.token = token; + this.userId = userId; + this.webClient = WebClient.wrap(httpClient); + } + + @Override + public Future> postSourceStorageRecords(Record aRecord) { + return createRequest(HttpMethod.POST, okapiUrl + "/source-storage/records", okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(aRecord)); + } + + @Override + public Future> putSourceStorageRecordsById(String id, Record aRecord) { + return createRequest(HttpMethod.PUT, okapiUrl + SOURCE_STORAGE_RECORDS + id, okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(aRecord)); + } + + @Override + public Future> putSourceStorageRecordsGenerationById(String id, Record aRecord) { + return createRequest(HttpMethod.PUT, okapiUrl + SOURCE_STORAGE_RECORDS + id + "/generation", + okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(aRecord)); + } + + @Override + public Future> putSourceStorageRecordsSuppressFromDiscoveryById(String id, String idType, boolean suppress) { + StringBuilder queryParams = new StringBuilder("?"); + if (idType != null) { + queryParams.append("idType="); + queryParams.append(PercentCodec.encode(idType)); + queryParams.append("&"); + } + + queryParams.append("suppress="); + queryParams.append(suppress); + + return createRequest(HttpMethod.PUT, okapiUrl + SOURCE_STORAGE_RECORDS + id + "/suppress-from-discovery" + queryParams, + okapiUrl, tenantId, token, userId, webClient) + .send(); + } +} diff --git a/src/main/java/org/folio/inventory/client/wrappers/SourceStorageSnapshotsClientWrapper.java b/src/main/java/org/folio/inventory/client/wrappers/SourceStorageSnapshotsClientWrapper.java new file mode 100644 index 000000000..3946db106 --- /dev/null +++ b/src/main/java/org/folio/inventory/client/wrappers/SourceStorageSnapshotsClientWrapper.java @@ -0,0 +1,46 @@ +package org.folio.inventory.client.wrappers; + +import io.vertx.core.Future; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import org.folio.rest.client.SourceStorageSnapshotsClient; +import org.folio.rest.jaxrs.model.Snapshot; + +import static org.folio.inventory.client.util.ClientWrapperUtil.createRequest; +import static org.folio.inventory.client.util.ClientWrapperUtil.getBuffer; + +/** + * Wrapper class for SourceStorageSnapshotsClient to handle POST and PUT HTTP requests with x-okapi-user-id header. + */ +public class SourceStorageSnapshotsClientWrapper extends SourceStorageSnapshotsClient { + private final String tenantId; + private final String token; + private final String okapiUrl; + private final String userId; + private final WebClient webClient; + + public SourceStorageSnapshotsClientWrapper(String okapiUrl, String tenantId, String token, String userId, HttpClient httpClient) { + super(okapiUrl, tenantId, token, httpClient); + this.okapiUrl = okapiUrl; + this.tenantId = tenantId; + this.token = token; + this.userId = userId; + this.webClient = WebClient.wrap(httpClient); + } + + @Override + public Future> postSourceStorageSnapshots(Snapshot snapshot) { + return createRequest(HttpMethod.POST, okapiUrl + "/source-storage/snapshots", okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(snapshot)); + } + + @Override + public Future> putSourceStorageSnapshotsByJobExecutionId(String jobExecutionId, Snapshot snapshot) { + return createRequest(HttpMethod.PUT, okapiUrl + "/source-storage/snapshots/" + jobExecutionId, + okapiUrl, tenantId, token, userId, webClient) + .sendBuffer(getBuffer(snapshot)); + } +} diff --git a/src/main/java/org/folio/inventory/consortium/handlers/MarcInstanceSharingHandlerImpl.java b/src/main/java/org/folio/inventory/consortium/handlers/MarcInstanceSharingHandlerImpl.java index 491f713dc..0c4a232fc 100644 --- a/src/main/java/org/folio/inventory/consortium/handlers/MarcInstanceSharingHandlerImpl.java +++ b/src/main/java/org/folio/inventory/consortium/handlers/MarcInstanceSharingHandlerImpl.java @@ -12,6 +12,7 @@ import org.folio.Link; import org.folio.LinkingRuleDto; import org.folio.Record; +import org.folio.inventory.client.wrappers.SourceStorageRecordsClientWrapper; import org.folio.inventory.common.Context; import org.folio.inventory.common.api.request.PagingParameters; import org.folio.inventory.consortium.entities.SharingInstance; @@ -282,10 +283,11 @@ Future updateSourceRecordSuppressFromDiscoveryByInstanceId(String instan public SourceStorageRecordsClient getSourceStorageRecordsClient(String tenant, Map kafkaHeaders) { LOGGER.info("getSourceStorageRecordsClient :: Creating SourceStorageRecordsClient for tenant={}", tenant); - return new SourceStorageRecordsClient( + return new SourceStorageRecordsClientWrapper( kafkaHeaders.get(OKAPI_URL_HEADER), tenant, kafkaHeaders.get(OKAPI_TOKEN_HEADER), + kafkaHeaders.get(OKAPI_USER_ID), vertx.createHttpClient()); } diff --git a/src/main/java/org/folio/inventory/consortium/util/RestDataImportHelper.java b/src/main/java/org/folio/inventory/consortium/util/RestDataImportHelper.java index 696cfa3e9..09eeebe03 100644 --- a/src/main/java/org/folio/inventory/consortium/util/RestDataImportHelper.java +++ b/src/main/java/org/folio/inventory/consortium/util/RestDataImportHelper.java @@ -10,6 +10,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.folio.Record; +import org.folio.inventory.client.wrappers.ChangeManagerClientWrapper; import org.folio.inventory.consortium.entities.SharingInstance; import org.folio.kafka.SimpleConfigurationReader; import org.folio.rest.client.ChangeManagerClient; @@ -290,10 +291,11 @@ private RawRecordsDto buildDataChunk(boolean isLast, List data) { } public ChangeManagerClient getChangeManagerClient(Map kafkaHeaders) { - return new ChangeManagerClient( + return new ChangeManagerClientWrapper( kafkaHeaders.get(URL.toLowerCase()), kafkaHeaders.get(TENANT.toLowerCase()), kafkaHeaders.get(TOKEN.toLowerCase()), + kafkaHeaders.get(USER_ID.toLowerCase()), vertx.createHttpClient()); } diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractInstanceEventHandler.java b/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractInstanceEventHandler.java index fd254f1fd..89720fec9 100644 --- a/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractInstanceEventHandler.java +++ b/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractInstanceEventHandler.java @@ -24,6 +24,8 @@ import org.apache.logging.log4j.Logger; import org.folio.DataImportEventPayload; import org.folio.HttpStatus; +import org.folio.inventory.client.wrappers.SourceStorageRecordsClientWrapper; +import org.folio.inventory.client.wrappers.SourceStorageSnapshotsClientWrapper; import org.folio.inventory.common.Context; import org.folio.inventory.dataimport.cache.MappingMetadataCache; import org.folio.inventory.dataimport.util.AdditionalFieldsUtil; @@ -94,9 +96,10 @@ protected org.folio.Instance defaultMapRecordToInstance(DataImportEventPayload d } protected Future saveRecordInSrsAndHandleResponse(DataImportEventPayload payload, Record srcRecord, - Instance instance, InstanceCollection instanceCollection, String tenantId) { + Instance instance, InstanceCollection instanceCollection, + String tenantId, String userId) { Promise promise = Promise.promise(); - getSourceStorageRecordsClient(payload.getOkapiUrl(), payload.getToken(), tenantId).postSourceStorageRecords(srcRecord) + getSourceStorageRecordsClient(payload.getOkapiUrl(), payload.getToken(), tenantId, userId).postSourceStorageRecords(srcRecord) .onComplete(ar -> { var result = ar.result(); if (ar.succeeded() && result.statusCode() == HttpStatus.HTTP_CREATED.toInt()) { @@ -117,9 +120,10 @@ protected Future saveRecordInSrsAndHandleResponse(DataImportEventPaylo } protected Future putRecordInSrsAndHandleResponse(DataImportEventPayload payload, Record srcRecord, - Instance instance, String matchedId, String tenantId) { + Instance instance, String matchedId, String tenantId, String userId) { Promise promise = Promise.promise(); - getSourceStorageRecordsClient(payload.getOkapiUrl(), payload.getToken(), tenantId).putSourceStorageRecordsGenerationById(matchedId ,srcRecord) + getSourceStorageRecordsClient(payload.getOkapiUrl(), payload.getToken(), tenantId, userId) + .putSourceStorageRecordsGenerationById(matchedId ,srcRecord) .onComplete(ar -> { var result = ar.result(); if (ar.succeeded() && result.statusCode() == HttpStatus.HTTP_OK.toInt()) { @@ -140,7 +144,7 @@ protected Future putRecordInSrsAndHandleResponse(DataImportEventPayloa protected Future postSnapshotInSrsAndHandleResponse(Context context, Snapshot snapshot) { Promise promise = Promise.promise(); - getSourceStorageSnapshotsClient(context.getOkapiLocation(), context.getToken(), context.getTenantId()).postSourceStorageSnapshots(snapshot) + getSourceStorageSnapshotsClient(context.getOkapiLocation(), context.getToken(), context.getTenantId(), context.getUserId()).postSourceStorageSnapshots(snapshot) .onComplete(ar -> { var result = ar.result(); if (ar.succeeded() && result.statusCode() == HttpStatus.HTTP_CREATED.toInt()) { @@ -202,12 +206,12 @@ protected void deleteInstance(String id, String jobExecutionId, InstanceCollecti promise.future(); } - public SourceStorageRecordsClient getSourceStorageRecordsClient(String okapiUrl, String token, String tenantId) { - return new SourceStorageRecordsClient(okapiUrl, tenantId, token, getHttpClient()); + public SourceStorageRecordsClient getSourceStorageRecordsClient(String okapiUrl, String token, String tenantId, String userId) { + return new SourceStorageRecordsClientWrapper(okapiUrl, tenantId, token, userId, getHttpClient()); } - public SourceStorageSnapshotsClient getSourceStorageSnapshotsClient(String okapiUrl, String token, String tenantId) { - return new SourceStorageSnapshotsClient(okapiUrl, tenantId, token, getHttpClient()); + public SourceStorageSnapshotsClient getSourceStorageSnapshotsClient(String okapiUrl, String token, String tenantId, String userId) { + return new SourceStorageSnapshotsClientWrapper(okapiUrl, tenantId, token, userId, getHttpClient()); } private Record encodeParsedRecordContent(Record srcRecord) { diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandler.java b/src/main/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandler.java index 516be25b4..ab3a86cb1 100644 --- a/src/main/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandler.java +++ b/src/main/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandler.java @@ -151,7 +151,8 @@ public CompletableFuture handle(DataImportEventPayload d var content = reorderMarcRecordFields(sourceContent, targetContent); targetRecord.setParsedRecord(targetRecord.getParsedRecord().withContent(content)); setSuppressFormDiscovery(targetRecord, instanceAsJson.getBoolean(DISCOVERY_SUPPRESS_PROPERTY, false)); - return saveRecordInSrsAndHandleResponse(dataImportEventPayload, targetRecord, createdInstance, instanceCollection, dataImportEventPayload.getTenant()); + return saveRecordInSrsAndHandleResponse(dataImportEventPayload, targetRecord, createdInstance, instanceCollection, + dataImportEventPayload.getTenant(), context.getUserId()); }); }) .onSuccess(ar -> { diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandler.java b/src/main/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandler.java index bc9421adb..69f0440a2 100644 --- a/src/main/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandler.java +++ b/src/main/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandler.java @@ -229,7 +229,8 @@ private void processInstanceUpdate(DataImportEventPayload dataImportEventPayload .compose(instance -> { if (instanceToUpdate.getSource().equals(FOLIO.getValue())) { executeFieldsManipulation(instance, targetRecord); - return saveRecordInSrsAndHandleResponse(dataImportEventPayload, targetRecord, instance, instanceCollection, tenantId); + return saveRecordInSrsAndHandleResponse(dataImportEventPayload, targetRecord, instance, instanceCollection, + tenantId, context.getUserId()); } if (instanceToUpdate.getSource().equals(MARC.getValue())) { setExternalIds(targetRecord, instance); @@ -238,7 +239,8 @@ private void processInstanceUpdate(DataImportEventPayload dataImportEventPayload JsonObject jsonInstance = new JsonObject(instance.getJsonForStorage().encode()); setSuppressFormDiscovery(targetRecord, jsonInstance.getBoolean(DISCOVERY_SUPPRESS_KEY, false)); - return putRecordInSrsAndHandleResponse(dataImportEventPayload, targetRecord, instance, targetRecord.getMatchedId(), tenantId); + return putRecordInSrsAndHandleResponse(dataImportEventPayload, targetRecord, instance, + targetRecord.getMatchedId(), tenantId, context.getUserId()); } return Future.succeededFuture(instance); }).compose(ar -> getPrecedingSucceedingTitlesHelper().createPrecedingSucceedingTitles(mappedInstance, context).map(ar)) @@ -332,7 +334,7 @@ private Future prepareRecordForMapping(DataImportEventPayload dataImportEv List marcFieldProtectionSettings, Instance instance, MappingParameters mappingParameters, String tenantId) { if (MARC_INSTANCE_SOURCE.equals(instance.getSource()) || CONSORTIUM_MARC.getValue().equals(instance.getSource())) { - SourceStorageRecordsClient client = getSourceStorageRecordsClient(dataImportEventPayload.getOkapiUrl(), dataImportEventPayload.getToken(), tenantId); + SourceStorageRecordsClient client = getSourceStorageRecordsClient(dataImportEventPayload.getOkapiUrl(), dataImportEventPayload.getToken(), tenantId, null); return getRecordByInstanceId(client, instance.getId()) .compose(existingRecord -> { Record incomingRecord = Json.decodeValue(dataImportEventPayload.getContext().get(MARC_BIBLIOGRAPHIC.value()), Record.class); diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/actions/modify/AbstractModifyEventHandler.java b/src/main/java/org/folio/inventory/dataimport/handlers/actions/modify/AbstractModifyEventHandler.java index efb51b248..e20f2a67c 100644 --- a/src/main/java/org/folio/inventory/dataimport/handlers/actions/modify/AbstractModifyEventHandler.java +++ b/src/main/java/org/folio/inventory/dataimport/handlers/actions/modify/AbstractModifyEventHandler.java @@ -12,6 +12,7 @@ import org.folio.DataImportEventPayload; import org.folio.MappingMetadataDto; import org.folio.MappingProfile; +import org.folio.inventory.client.wrappers.SourceStorageRecordsClientWrapper; import org.folio.inventory.common.Context; import org.folio.inventory.dataimport.cache.MappingMetadataCache; import org.folio.inventory.dataimport.exceptions.OptimisticLockingException; @@ -266,7 +267,8 @@ protected Future updateRecord(Record record, Context context) { } public SourceStorageRecordsClient getSourceStorageRecordsClient(Context context) { - return new SourceStorageRecordsClient(context.getOkapiLocation(), context.getTenantId(), context.getToken(), client); + return new SourceStorageRecordsClientWrapper(context.getOkapiLocation(), context.getTenantId(), + context.getToken(), context.getUserId(), client); } private void preparePayload(DataImportEventPayload dataImportEventPayload) { diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/matching/AbstractMarcMatchEventHandler.java b/src/main/java/org/folio/inventory/dataimport/handlers/matching/AbstractMarcMatchEventHandler.java index d8cb9ac31..f9ee4401f 100644 --- a/src/main/java/org/folio/inventory/dataimport/handlers/matching/AbstractMarcMatchEventHandler.java +++ b/src/main/java/org/folio/inventory/dataimport/handlers/matching/AbstractMarcMatchEventHandler.java @@ -12,6 +12,7 @@ import org.folio.DataImportEventTypes; import org.folio.MatchDetail; import org.folio.MatchProfile; +import org.folio.inventory.client.wrappers.SourceStorageRecordsClientWrapper; import org.folio.inventory.common.Context; import org.folio.inventory.consortium.services.ConsortiumService; import org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil; @@ -47,7 +48,6 @@ import static org.apache.http.HttpStatus.SC_OK; import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.PAYLOAD_USER_ID; import static org.folio.processing.value.Value.ValueType.MISSING; -import static org.folio.rest.jaxrs.model.Filter.*; import static org.folio.rest.jaxrs.model.MatchExpression.DataValueType.VALUE_FROM_RECORD; import static org.folio.rest.jaxrs.model.ProfileType.MATCH_PROFILE; @@ -95,8 +95,9 @@ public CompletableFuture handle(DataImportEventPayload p LOG.warn("handle:: {}", PAYLOAD_HAS_NO_DATA_MESSAGE); return CompletableFuture.failedFuture(new EventProcessingException(PAYLOAD_HAS_NO_DATA_MESSAGE)); } + String userId = context.get(USER_ID_HEADER); payload.getEventsChain().add(payload.getEventType()); - payload.setAdditionalProperty(USER_ID_HEADER, context.get(USER_ID_HEADER)); + payload.setAdditionalProperty(USER_ID_HEADER, userId); String recordAsString = context.get(getMarcType()); MatchDetail matchDetail = retrieveMatchDetail(payload); @@ -114,7 +115,7 @@ public CompletableFuture handle(DataImportEventPayload p } RecordMatchingDto recordMatchingDto = buildRecordsMatchingRequest(matchDetail, value); - return retrieveMarcRecords(recordMatchingDto, payload.getTenant(), payload) + return retrieveMarcRecords(recordMatchingDto, payload.getTenant(), userId, payload) .compose(localMatchedRecords -> { if (isMatchingOnCentralTenantRequired()) { return matchCentralTenantIfNeededAndCombineWithLocalMatchedRecords(recordMatchingDto, payload, localMatchedRecords); @@ -198,7 +199,7 @@ private RecordMatchingDto buildRecordsMatchingRequest(MatchDetail matchDetail, V Qualifier qualifier = matchDetail.getExistingMatchExpression().getQualifier(); Filter.Qualifier qualifierFilterType = null; - ComparisonPartType comparisonPartType = null; + Filter.ComparisonPartType comparisonPartType = null; String qualifierValue = null; if (qualifier != null) { @@ -208,7 +209,7 @@ private RecordMatchingDto buildRecordsMatchingRequest(MatchDetail matchDetail, V Filter.Qualifier.valueOf(qualifier.getQualifierType().toString()) : null; comparisonPartType = qualifier.getComparisonPart() != null ? - ComparisonPartType.valueOf(qualifier.getComparisonPart().toString()) : null; + Filter.ComparisonPartType.valueOf(qualifier.getComparisonPart().toString()) : null; } return new RecordMatchingDto() @@ -225,10 +226,10 @@ private RecordMatchingDto buildRecordsMatchingRequest(MatchDetail matchDetail, V .withReturnTotalRecordsCount(true); } - private Future> retrieveMarcRecords(RecordMatchingDto recordMatchingDto, String tenantId, + private Future> retrieveMarcRecords(RecordMatchingDto recordMatchingDto, String tenantId, String userId, DataImportEventPayload payload) { SourceStorageRecordsClient sourceStorageRecordsClient = - new SourceStorageRecordsClient(payload.getOkapiUrl(), tenantId, payload.getToken(), httpClient); + new SourceStorageRecordsClientWrapper(payload.getOkapiUrl(), tenantId, payload.getToken(), userId, httpClient); return getAllMatchedRecordsIdentifiers(recordMatchingDto, payload, sourceStorageRecordsClient) .compose(recordsIdentifiersCollection -> { @@ -332,7 +333,7 @@ private Future> matchCentralTenantIfNeededAndCombineWithLocalMatche LOG.debug("matchCentralTenantIfNeededAndCombineWithLocalMatchedRecords:: Matching on centralTenant with id: {}", consortiumConfigurationOptional.get().getCentralTenantId()); - return retrieveMarcRecords(recordMatchingDto, consortiumConfigurationOptional.get().getCentralTenantId(), payload) + return retrieveMarcRecords(recordMatchingDto, consortiumConfigurationOptional.get().getCentralTenantId(), context.getUserId(), payload) .map(centralRecordOptional -> { centralRecordOptional.ifPresent(r -> payload.getContext().put(CENTRAL_TENANT_ID_KEY, consortiumConfigurationOptional.get().getCentralTenantId())); return Stream.concat(localMatchedRecord.stream(), centralRecordOptional.stream()).toList(); diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/matching/util/EventHandlingUtil.java b/src/main/java/org/folio/inventory/dataimport/handlers/matching/util/EventHandlingUtil.java index 1d82ffd7d..b01067755 100644 --- a/src/main/java/org/folio/inventory/dataimport/handlers/matching/util/EventHandlingUtil.java +++ b/src/main/java/org/folio/inventory/dataimport/handlers/matching/util/EventHandlingUtil.java @@ -15,6 +15,9 @@ public final class EventHandlingUtil { public static final String PAYLOAD_USER_ID = "userId"; + public static final String OKAPI_TENANT = "x-okapi-tenant"; + public static final String OKAPI_TOKEN = "x-okapi-token"; + public static final String OKAPI_URL = "x-okapi-url"; public static final String OKAPI_USER_ID = "x-okapi-user-id"; public static final String OKAPI_REQUEST_ID = "x-okapi-request-id"; private static final String CENTRAL_TENANT_ID = "CENTRAL_TENANT_ID"; diff --git a/src/main/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandler.java b/src/main/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandler.java index c258d0ca5..e1ea8c4b9 100644 --- a/src/main/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandler.java +++ b/src/main/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandler.java @@ -99,7 +99,7 @@ private Future saveRecordInSrsAndHandleResponse(InstanceIngressEvent e postSnapshotInSrsAndHandleResponse(srcRecord.getSnapshotId(), context, super::postSnapshotInSrsAndHandleResponse) .onFailure(promise::fail) .compose(snapshot -> { - getSourceStorageRecordsClient(context.getOkapiLocation(), context.getToken(), context.getTenantId()) + getSourceStorageRecordsClient(context.getOkapiLocation(), context.getToken(), context.getTenantId(), context.getUserId()) .postSourceStorageRecords(srcRecord) .onComplete(ar -> { var result = ar.result(); diff --git a/src/main/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandler.java b/src/main/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandler.java index 0058afb61..1f9fd26cc 100644 --- a/src/main/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandler.java +++ b/src/main/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandler.java @@ -123,7 +123,7 @@ private Future processInstanceUpdate(Instance instance, InstanceIngres private Future putRecordInSrsAndHandleResponse(Record targetRecord, Instance instance) { Promise promise = Promise.promise(); - var sourceStorageRecordsClient = getSourceStorageRecordsClient(context.getOkapiLocation(), context.getToken(), context.getTenantId()); + var sourceStorageRecordsClient = getSourceStorageRecordsClient(context.getOkapiLocation(), context.getToken(), context.getTenantId(), context.getUserId()); postSnapshotInSrsAndHandleResponse(targetRecord.getSnapshotId(), context, super::postSnapshotInSrsAndHandleResponse) .onFailure(promise::fail) .compose(snapshot -> super.getRecordByInstanceId(sourceStorageRecordsClient, instance.getId())) diff --git a/src/main/java/org/folio/inventory/resources/Holdings.java b/src/main/java/org/folio/inventory/resources/Holdings.java index 561e9bd0f..907f51eb2 100644 --- a/src/main/java/org/folio/inventory/resources/Holdings.java +++ b/src/main/java/org/folio/inventory/resources/Holdings.java @@ -29,6 +29,7 @@ import org.folio.HoldingsRecord; import org.folio.HttpStatus; +import org.folio.inventory.client.wrappers.SourceStorageRecordsClientWrapper; import org.folio.inventory.common.WebContext; import org.folio.inventory.config.InventoryConfiguration; import org.folio.inventory.config.InventoryConfigurationImpl; @@ -38,7 +39,6 @@ import org.folio.inventory.exceptions.UnprocessableEntityException; import org.folio.inventory.storage.Storage; import org.folio.inventory.support.http.server.FailureResponseConsumer; -import org.folio.rest.client.SourceStorageRecordsClient; public class Holdings { @@ -163,7 +163,8 @@ private void updateHoldings(HoldingsRecord holdingsRecord, HoldingsRecordCollect private void updateSuppressFromDiscoveryFlag(WebContext wContext, RoutingContext rContext, HoldingsRecord updatedHoldings) { try { - new SourceStorageRecordsClient(wContext.getOkapiLocation(), wContext.getTenantId(), wContext.getToken(), client) + new SourceStorageRecordsClientWrapper(wContext.getOkapiLocation(), wContext.getTenantId(), + wContext.getToken(), wContext.getUserId(), client) .putSourceStorageRecordsSuppressFromDiscoveryById(updatedHoldings.getId(), HOLDING_ID_TYPE, updatedHoldings.getDiscoverySuppress(), httpClientResponse -> { if (httpClientResponse.result().statusCode() == HttpStatus.HTTP_OK.toInt()) { LOGGER.info(format("Suppress from discovery flag was updated for record in SRS. Holding id: %s", diff --git a/src/test/java/org/folio/inventory/client/ChangeManagerClientWrapperTest.java b/src/test/java/org/folio/inventory/client/ChangeManagerClientWrapperTest.java new file mode 100644 index 000000000..31c0bca82 --- /dev/null +++ b/src/test/java/org/folio/inventory/client/ChangeManagerClientWrapperTest.java @@ -0,0 +1,198 @@ +package org.folio.inventory.client; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.common.Slf4jNotifier; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.matching.RegexPattern; +import com.github.tomakehurst.wiremock.matching.UrlPathPattern; +import io.vertx.core.Future; +import io.vertx.core.Vertx; +import io.vertx.core.buffer.Buffer; +import io.vertx.ext.unit.Async; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.web.client.HttpResponse; +import org.folio.inventory.client.wrappers.ChangeManagerClientWrapper; +import org.folio.rest.jaxrs.model.InitJobExecutionsRqDto; +import org.folio.rest.jaxrs.model.JobExecution; +import org.folio.rest.jaxrs.model.JobProfileInfo; +import org.folio.rest.jaxrs.model.ParsedRecordDto; +import org.folio.rest.jaxrs.model.RawRecordsDto; +import org.folio.rest.jaxrs.model.StatusDto; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.UUID; + +import static api.ApiTestSuite.TENANT_ID; +import static com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_CREATED; +import static com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_OK; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TENANT; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TOKEN; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_URL; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_USER_ID; + +@RunWith(VertxUnitRunner.class) +public class ChangeManagerClientWrapperTest { + private final Vertx vertx = Vertx.vertx(); + private ChangeManagerClientWrapper changeManagerClientWrapper; + private RawRecordsDto stubRawRecordsDto; + private InitJobExecutionsRqDto stubInitJobExecutionsRqDto; + private JobExecution stubJobExecution; + private JobProfileInfo stubJobProfileInfo; + private StatusDto stubStatusDto; + private ParsedRecordDto stubParsedRecordDto; + private static final String TOKEN = "token"; + private static final String USER_ID = "userId"; + + @Rule + public WireMockRule mockServer = new WireMockRule( + WireMockConfiguration.wireMockConfig() + .dynamicPort() + .notifier(new Slf4jNotifier(true))); + + @Before + public void setUp() { + changeManagerClientWrapper = new ChangeManagerClientWrapper(mockServer.baseUrl(), TENANT_ID, TOKEN, USER_ID, + vertx.createHttpClient()); + + stubRawRecordsDto = new RawRecordsDto().withId(UUID.randomUUID().toString()); + stubInitJobExecutionsRqDto = new InitJobExecutionsRqDto().withParentJobId(UUID.randomUUID().toString()); + stubJobExecution = new JobExecution().withId(UUID.randomUUID().toString()); + stubJobProfileInfo = new JobProfileInfo().withId(UUID.randomUUID().toString()); + stubStatusDto = new StatusDto(); + stubParsedRecordDto = new ParsedRecordDto().withId(UUID.randomUUID().toString()); + + WireMock.stubFor(post(new UrlPathPattern(new RegexPattern("/change-manager/jobExecutions"), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.created())); + + WireMock.stubFor(post(new UrlPathPattern(new RegexPattern("/change-manager/jobExecutions/" + stubRawRecordsDto.getId() + "/records"), true)) + .withQueryParam("acceptInstanceId", equalTo("true")) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.created())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/change-manager/jobExecutions/" + stubJobExecution.getId()), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/change-manager/jobExecutions/" + stubJobProfileInfo.getId() + "/jobProfile"), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/change-manager/jobExecutions/" + stubJobExecution.getId() + "/status"), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/change-manager/parsedRecords/" + stubParsedRecordDto.getId()), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + } + + @Test + public void shouldPostChangeManagerJobExecutions(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = changeManagerClientWrapper.postChangeManagerJobExecutions(stubInitJobExecutionsRqDto); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_CREATED); + async.complete(); + }); + } + + @Test + public void shouldPostChangeManagerJobExecutionsRecordsById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = changeManagerClientWrapper + .postChangeManagerJobExecutionsRecordsById(stubRawRecordsDto.getId(), true, stubRawRecordsDto); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_CREATED); + async.complete(); + }); + } + + @Test + public void shouldPutChangeManagerJobExecutionsById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = changeManagerClientWrapper + .putChangeManagerJobExecutionsById(stubJobExecution.getId(), stubJobExecution); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } + + @Test + public void shouldPutChangeManagerJobExecutionsJobProfileById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = changeManagerClientWrapper + .putChangeManagerJobExecutionsJobProfileById(stubJobProfileInfo.getId(), stubJobProfileInfo); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } + + @Test + public void shouldPutChangeManagerJobExecutionsStatusById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = changeManagerClientWrapper + .putChangeManagerJobExecutionsStatusById(stubJobExecution.getId(), stubStatusDto); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } + + @Test + public void shouldPutChangeManagerParsedRecordsById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = changeManagerClientWrapper + .putChangeManagerParsedRecordsById(stubParsedRecordDto.getId(), stubParsedRecordDto); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } +} diff --git a/src/test/java/org/folio/inventory/client/SourceStorageRecordsClientWrapperTest.java b/src/test/java/org/folio/inventory/client/SourceStorageRecordsClientWrapperTest.java new file mode 100644 index 000000000..0d1efd54b --- /dev/null +++ b/src/test/java/org/folio/inventory/client/SourceStorageRecordsClientWrapperTest.java @@ -0,0 +1,141 @@ +package org.folio.inventory.client; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.common.Slf4jNotifier; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.matching.RegexPattern; +import com.github.tomakehurst.wiremock.matching.UrlPathPattern; +import io.vertx.core.Future; +import io.vertx.core.Vertx; +import io.vertx.ext.unit.Async; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.web.client.HttpResponse; +import org.folio.inventory.client.wrappers.SourceStorageRecordsClientWrapper; +import org.folio.rest.jaxrs.model.Record; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import io.vertx.core.buffer.Buffer; +import java.util.UUID; + +import static api.ApiTestSuite.TENANT_ID; +import static com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_CREATED; +import static com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_OK; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TENANT; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TOKEN; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_URL; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_USER_ID; + +@RunWith(VertxUnitRunner.class) +public class SourceStorageRecordsClientWrapperTest { + public static final String RECORD = "Record"; + private final Vertx vertx = Vertx.vertx(); + private SourceStorageRecordsClientWrapper sourceStorageRecordsClientWrapper; + private Record stubRecord; + private static final String TOKEN = "token"; + private static final String USER_ID = "userId"; + + @Rule + public WireMockRule mockServer = new WireMockRule( + WireMockConfiguration.wireMockConfig() + .dynamicPort() + .notifier(new Slf4jNotifier(true))); + + @Before + public void setUp() { + sourceStorageRecordsClientWrapper = new SourceStorageRecordsClientWrapper(mockServer.baseUrl(), TENANT_ID, TOKEN, USER_ID, + vertx.createHttpClient()); + + stubRecord = new Record().withId(UUID.randomUUID().toString()); + + WireMock.stubFor(post(new UrlPathPattern(new RegexPattern("/source-storage/records"), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.created())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/source-storage/records/" + stubRecord.getId()), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/source-storage/records/" + stubRecord.getId() + "/generation"), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/source-storage/records/" + stubRecord.getId() + "/suppress-from-discovery"), true)) + .withQueryParam("idType", equalTo(RECORD)) + .withQueryParam("suppress", equalTo("true")) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + } + + @Test + public void shouldPostSourceStorageRecords(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = sourceStorageRecordsClientWrapper.postSourceStorageRecords(stubRecord); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_CREATED); + async.complete(); + }); + } + + @Test + public void shouldPutSourceStorageRecordsById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = sourceStorageRecordsClientWrapper.putSourceStorageRecordsById(stubRecord.getId(), stubRecord); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } + + @Test + public void shouldPutSourceStorageRecordsGenerationById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = sourceStorageRecordsClientWrapper.putSourceStorageRecordsGenerationById(stubRecord.getId(), stubRecord); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } + + @Test + public void shouldPutSourceStorageRecordsSuppressFromDiscoveryById(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = sourceStorageRecordsClientWrapper + .putSourceStorageRecordsSuppressFromDiscoveryById(stubRecord.getId(), RECORD, true); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } +} diff --git a/src/test/java/org/folio/inventory/client/SourceStorageSnapshotsClientWrapperTest.java b/src/test/java/org/folio/inventory/client/SourceStorageSnapshotsClientWrapperTest.java new file mode 100644 index 000000000..36b4fddc7 --- /dev/null +++ b/src/test/java/org/folio/inventory/client/SourceStorageSnapshotsClientWrapperTest.java @@ -0,0 +1,98 @@ +package org.folio.inventory.client; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.common.Slf4jNotifier; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.matching.RegexPattern; +import com.github.tomakehurst.wiremock.matching.UrlPathPattern; +import io.vertx.core.Future; +import io.vertx.core.Vertx; +import io.vertx.core.buffer.Buffer; +import io.vertx.ext.unit.Async; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.web.client.HttpResponse; +import org.folio.inventory.client.wrappers.SourceStorageSnapshotsClientWrapper; +import org.folio.rest.jaxrs.model.Snapshot; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.UUID; + +import static api.ApiTestSuite.TENANT_ID; +import static com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_CREATED; +import static com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_OK; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TENANT; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_TOKEN; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_URL; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.OKAPI_USER_ID; + +@RunWith(VertxUnitRunner.class) +public class SourceStorageSnapshotsClientWrapperTest { + private final Vertx vertx = Vertx.vertx(); + private SourceStorageSnapshotsClientWrapper sourceStorageSnapshotsClientWrapper; + private Snapshot stubSnapshot; + private static final String TOKEN = "token"; + private static final String USER_ID = "userId"; + + @Rule + public WireMockRule mockServer = new WireMockRule( + WireMockConfiguration.wireMockConfig() + .dynamicPort() + .notifier(new Slf4jNotifier(true))); + + @Before + public void setUp() { + sourceStorageSnapshotsClientWrapper = new SourceStorageSnapshotsClientWrapper(mockServer.baseUrl(), TENANT_ID, TOKEN, USER_ID, + vertx.createHttpClient()); + + stubSnapshot = new Snapshot().withJobExecutionId(UUID.randomUUID().toString()); + + WireMock.stubFor(post(new UrlPathPattern(new RegexPattern("/source-storage/snapshots"), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.created())); + + WireMock.stubFor(put(new UrlPathPattern(new RegexPattern("/source-storage/snapshots/" + stubSnapshot.getJobExecutionId()), true)) + .withHeader(OKAPI_URL, equalTo(mockServer.baseUrl())) + .withHeader(OKAPI_TOKEN, equalTo(TOKEN)) + .withHeader(OKAPI_TENANT, equalTo(TENANT_ID)) + .withHeader(OKAPI_USER_ID, equalTo(USER_ID)) + .willReturn(WireMock.ok())); + } + + @Test + public void shouldPostSourceStorageSnapshots(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = sourceStorageSnapshotsClientWrapper.postSourceStorageSnapshots(stubSnapshot); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_CREATED); + async.complete(); + }); + } + + @Test + public void shouldPutSourceStorageSnapshotsByJobExecutionId(TestContext context) { + Async async = context.async(); + + Future> optionalFuture = sourceStorageSnapshotsClientWrapper + .putSourceStorageSnapshotsByJobExecutionId(stubSnapshot.getJobExecutionId(), stubSnapshot); + + optionalFuture.onComplete(ar -> { + context.assertTrue(ar.succeeded()); + context.assertEquals(ar.result().statusCode(), SC_OK); + async.complete(); + }); + } +} diff --git a/src/test/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandlerTest.java b/src/test/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandlerTest.java index 41304f4ab..85d8bd7d9 100644 --- a/src/test/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandlerTest.java +++ b/src/test/java/org/folio/inventory/dataimport/handlers/actions/CreateInstanceEventHandlerTest.java @@ -87,6 +87,7 @@ import static org.folio.DataImportEventTypes.DI_INVENTORY_INSTANCE_CREATED_READY_FOR_POST_PROCESSING; import static org.folio.DataImportEventTypes.DI_INCOMING_MARC_BIB_RECORD_PARSED; import static org.folio.inventory.TestUtil.buildHttpResponseWithBuffer; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.PAYLOAD_USER_ID; import static org.folio.inventory.dataimport.util.AdditionalFieldsUtil.TAG_005; import static org.folio.inventory.dataimport.util.AdditionalFieldsUtil.dateTime005Formatter; import static org.folio.inventory.dataimport.util.DataImportConstants.UNIQUE_ID_ERROR_MESSAGE; @@ -101,7 +102,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -119,6 +119,7 @@ public class CreateInstanceEventHandlerTest { private static final String MAPPING_RULES_PATH = "src/test/resources/handlers/bib-rules.json"; private static final String MAPPING_METADATA_URL = "/mapping-metadata"; private static final String TENANT_ID = "diku"; + private static final String USER_ID = "userId"; private static final String TOKEN = "dummy"; @Mock @@ -279,7 +280,7 @@ public void setUp() throws IOException { new PrecedingSucceedingTitlesHelper(context -> mockedClient), MappingMetadataCache.getInstance(vertx, httpClient, true), instanceIdStorageService, orderHelperService, httpClient)); - doReturn(sourceStorageClient).when(createInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(createInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), any(), any()); doAnswer(invocationOnMock -> { Instance instanceRecord = invocationOnMock.getArgument(0); Consumer> successHandler = invocationOnMock.getArgument(1); @@ -329,6 +330,7 @@ public void shouldProcessEvent(String content, String acceptInstanceId) throws I context.put(MARC_BIBLIOGRAPHIC.value(), Json.encode(record)); context.put("acceptInstanceId", acceptInstanceId); + context.put(PAYLOAD_USER_ID, USER_ID); Buffer buffer = BufferImpl.buffer("{\"parsedRecord\":{" + "\"id\":\"990fad8b-64ec-4de4-978c-9f8bbed4c6d3\"," + @@ -369,7 +371,8 @@ public void shouldProcessEvent(String content, String acceptInstanceId) throws I assertThat(createdInstance.getJsonArray("notes").getJsonObject(0).getString("instanceNoteTypeId"), notNullValue()); assertThat(createdInstance.getJsonArray("notes").getJsonObject(1).getString("instanceNoteTypeId"), notNullValue()); verify(mockedClient, times(2)).post(any(URL.class), any(JsonObject.class)); - verify(createInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(TENANT_ID))); + verify(createInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), + argThat(tenantId -> tenantId.equals(TENANT_ID)), argThat(USER_ID::equals)); } @Test @@ -453,6 +456,7 @@ public void shouldProcessEventAndUpdateSuppresFromDiscovery() throws Interrupted context.put(MARC_BIBLIOGRAPHIC.value(), Json.encode(record)); context.put("acceptInstanceId", "true"); + context.put(PAYLOAD_USER_ID, USER_ID); Buffer buffer = BufferImpl.buffer("{\"parsedRecord\":{" + "\"id\":\"990fad8b-64ec-4de4-978c-9f8bbed4c6d3\"," + @@ -487,7 +491,7 @@ public void shouldProcessEventAndUpdateSuppresFromDiscovery() throws Interrupted assertEquals("MARC", createdInstance.getString("source")); assertThat(createdInstance.getString("discoverySuppress"), is("true")); verify(mockedClient, times(2)).post(any(URL.class), any(JsonObject.class)); - verify(createInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(TENANT_ID))); + verify(createInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(TENANT_ID)), argThat(USER_ID::equals)); } @Test(expected = ExecutionException.class) diff --git a/src/test/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandlerTest.java b/src/test/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandlerTest.java index b82d0ee9d..19b1027de 100644 --- a/src/test/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandlerTest.java +++ b/src/test/java/org/folio/inventory/dataimport/handlers/actions/ReplaceInstanceEventHandlerTest.java @@ -93,6 +93,7 @@ import static org.folio.inventory.TestUtil.buildHttpResponseWithBuffer; import static org.folio.inventory.dataimport.handlers.actions.ReplaceInstanceEventHandler.ACTION_HAS_NO_MAPPING_MSG; import static org.folio.inventory.dataimport.handlers.actions.ReplaceInstanceEventHandler.MARC_BIB_RECORD_CREATED; +import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.PAYLOAD_USER_ID; import static org.folio.inventory.domain.instances.InstanceSource.CONSORTIUM_MARC; import static org.folio.inventory.domain.instances.InstanceSource.FOLIO; import static org.folio.inventory.domain.instances.InstanceSource.MARC; @@ -114,7 +115,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -137,6 +137,7 @@ public class ReplaceInstanceEventHandlerTest { private static final String INSTANCE_VERSION_AS_STRING = "1"; private static final String MARC_INSTANCE_SOURCE = "MARC"; private static final String LINKED_DATA_INSTANCE_SOURCE = "LINKED_DATA"; + public static final String USER_ID = "userId"; private final String localTenant = "tenant"; private final String consortiumTenant = "consortiumTenant"; private final UUID instanceId = UUID.randomUUID(); @@ -318,8 +319,8 @@ public void setUp() throws IOException { return null; }).when(instanceRecordCollection).update(any(), any(Consumer.class), any(Consumer.class)); - doReturn(sourceStorageClient).when(replaceInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), any()); - doReturn(sourceStorageSnapshotsClient).when(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(replaceInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), any(), any()); doAnswer(invocationOnMock -> completedStage(createResponse(201, null))) .when(mockedClient).post(any(URL.class), any(JsonObject.class)); @@ -546,9 +547,9 @@ public void shouldProcessEventIfConsortiumInstance() throws InterruptedException assertThat(createdInstance.getString("_version"), is(INSTANCE_VERSION_AS_STRING)); verify(mockedClient, times(2)).post(any(URL.class), any(JsonObject.class)); verify(sourceStorageClient).getSourceStorageRecordsFormattedById(anyString(),eq(INSTANCE.value())); - verify(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant))); + verify(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant)), any()); verify(sourceStorageSnapshotsClient).postSourceStorageSnapshots(argThat(snapshot -> snapshot.getJobExecutionId().equals(record.getSnapshotId()))); - verify(replaceInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant))); + verify(replaceInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant)), any()); verify(sourceStorageClient).getSourceStorageRecordsFormattedById(anyString(), eq(INSTANCE.value())); verify(1, getRequestedFor(new UrlPathPattern(new RegexPattern(MAPPING_METADATA_URL + "/.*"), true))); } @@ -640,6 +641,7 @@ public void shouldUpdateSharedFolioInstanceOnCentralTenantIfPayloadContainsCentr HashMap context = new HashMap<>(); context.put(CENTRAL_TENANT_ID_KEY, consortiumTenant); + context.put(PAYLOAD_USER_ID, USER_ID); context.put(MARC_BIBLIOGRAPHIC.value(), Json.encode(record)); context.put(INSTANCE.value(), new JsonObject() .put("id", UUID.randomUUID().toString()) @@ -685,8 +687,8 @@ public void shouldUpdateSharedFolioInstanceOnCentralTenantIfPayloadContainsCentr ArgumentCaptor recordCaptor = ArgumentCaptor.forClass(Record.class); verify(sourceStorageClient).postSourceStorageRecords(recordCaptor.capture()); - verify(replaceInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant))); - verify(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant))); + verify(replaceInstanceEventHandler).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant)), argThat(USER_ID::equals)); + verify(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant)), argThat(USER_ID::equals)); verify(sourceStorageSnapshotsClient).postSourceStorageSnapshots(argThat(snapshot -> snapshot.getJobExecutionId().equals(record.getSnapshotId()))); assertNotNull(recordId, recordCaptor.getValue().getMatchedId()); } @@ -754,8 +756,8 @@ public void shouldUpdateSharedMarcInstanceOnCentralTenantIfPayloadContainsCentra ArgumentCaptor recordCaptor = ArgumentCaptor.forClass(Record.class); verify(sourceStorageClient).putSourceStorageRecordsGenerationById(any(), recordCaptor.capture()); - verify(replaceInstanceEventHandler, times(2)).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant))); - verify(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant))); + verify(replaceInstanceEventHandler, times(2)).getSourceStorageRecordsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant)), any()); + verify(replaceInstanceEventHandler).getSourceStorageSnapshotsClient(any(), any(), argThat(tenantId -> tenantId.equals(consortiumTenant)), any()); verify(sourceStorageSnapshotsClient).postSourceStorageSnapshots(argThat(snapshot -> snapshot.getJobExecutionId().equals(record.getSnapshotId()))); } diff --git a/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java b/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java index 701f1350e..6b1a60b90 100644 --- a/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java +++ b/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java @@ -14,6 +14,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -63,6 +64,10 @@ public class CreateInstanceIngressEventHandlerUnitTest { private static final String MAPPING_RULES_PATH = "src/test/resources/handlers/bib-rules.json"; private static final String BIB_RECORD_PATH = "src/test/resources/handlers/bib-record.json"; + public static final String TOKEN = "token"; + public static final String OKAPI_URL = "okapiUrl"; + public static final String TENANT = "tenant"; + public static final String USER_ID = "userId"; @Rule public MockitoRule initRule = MockitoJUnit.rule(); @@ -88,9 +93,10 @@ public class CreateInstanceIngressEventHandlerUnitTest { @Before public void setUp() { - doReturn("tenant").when(context).getTenantId(); - doReturn("okapiUrl").when(context).getOkapiLocation(); - doReturn("token").when(context).getToken(); + doReturn(TENANT).when(context).getTenantId(); + doReturn(OKAPI_URL).when(context).getOkapiLocation(); + doReturn(TOKEN).when(context).getToken(); + doReturn(USER_ID).when(context).getUserId(); doReturn(instanceCollection).when(storage).getInstanceCollection(context); handler = spy(new CreateInstanceIngressEventHandler(precedingSucceedingTitlesHelper, mappingMetadataCache, idStorageService, httpClient, context, storage)); @@ -170,7 +176,7 @@ public void shouldReturnFailedFuture_ifInstanceValidationFails() throws IOExcept .withMappingParams(Json.encode(new MappingParameters()))))) .when(mappingMetadataCache).getByRecordType(InstanceIngressEventConsumer.class.getSimpleName(), context, MARC_BIB_RECORD_TYPE); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), argThat(USER_ID::equals)); var snapshotHttpResponse = buildHttpResponseWithBuffer(buffer(Json.encode(new Snapshot())), HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); @@ -200,7 +206,7 @@ public void shouldReturnFailedFuture_ifInstanceSavingFailed() throws IOException .withMappingRules(mappingRules.encode()) .withMappingParams(Json.encode(new MappingParameters()))))) .when(mappingMetadataCache).getByRecordType(InstanceIngressEventConsumer.class.getSimpleName(), context, MARC_BIB_RECORD_TYPE); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), argThat(USER_ID::equals)); var snapshotHttpResponse = buildHttpResponseWithBuffer(buffer(Json.encode(new Snapshot())), HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); @@ -234,7 +240,7 @@ public void shouldReturnFailedFuture_ifCreatePrecedingSucceedingTitlesFailed() t .withMappingRules(mappingRules.encode()) .withMappingParams(Json.encode(new MappingParameters()))))) .when(mappingMetadataCache).getByRecordType(InstanceIngressEventConsumer.class.getSimpleName(), context, MARC_BIB_RECORD_TYPE); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), argThat(USER_ID::equals)); var snapshotHttpResponse = buildHttpResponseWithBuffer(buffer(Json.encode(new Snapshot())), HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); doAnswer(i -> { @@ -268,14 +274,13 @@ public void shouldReturnFailedFuture_ifSourceStorageSnapshotsClientReturnsError( .withMappingRules(mappingRules.encode()) .withMappingParams(Json.encode(new MappingParameters()))))) .when(mappingMetadataCache).getByRecordType(InstanceIngressEventConsumer.class.getSimpleName(), context, MARC_BIB_RECORD_TYPE); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), argThat(USER_ID::equals)); doAnswer(i -> { Consumer> successHandler = i.getArgument(1); successHandler.accept(new Success<>(i.getArgument(0))); return null; }).when(instanceCollection).add(any(), any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).createPrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); var snapshotHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_BAD_REQUEST); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); @@ -304,7 +309,7 @@ public void shouldReturnFailedFuture_ifItsFailedToCreateMarcRecordInSrs() throws .withMappingRules(mappingRules.encode()) .withMappingParams(Json.encode(new MappingParameters()))))) .when(mappingMetadataCache).getByRecordType(InstanceIngressEventConsumer.class.getSimpleName(), context, MARC_BIB_RECORD_TYPE); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), argThat(USER_ID::equals)); var snapshotHttpResponse = buildHttpResponseWithBuffer(buffer(Json.encode(new Snapshot())), HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); doAnswer(i -> { @@ -313,7 +318,7 @@ public void shouldReturnFailedFuture_ifItsFailedToCreateMarcRecordInSrs() throws return null; }).when(instanceCollection).add(any(), any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).createPrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any(), any()); var sourceStorageHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_BAD_REQUEST); doReturn(succeededFuture(sourceStorageHttpResponse)).when(sourceStorageClient).postSourceStorageRecords(any()); @@ -347,7 +352,7 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx .withMappingRules(mappingRules.encode()) .withMappingParams(Json.encode(new MappingParameters()))))) .when(mappingMetadataCache).getByRecordType(InstanceIngressEventConsumer.class.getSimpleName(), context, MARC_BIB_RECORD_TYPE); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), argThat(USER_ID::equals)); var snapshotHttpResponse = buildHttpResponseWithBuffer(buffer(Json.encode(new Snapshot())), HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); doAnswer(i -> { @@ -356,7 +361,7 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx return null; }).when(instanceCollection).add(any(), any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).createPrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any(), any()); var sourceStorageHttpResponse = buildHttpResponseWithBuffer(buffer(Json.encode(new Record())), HttpStatus.SC_CREATED); doReturn(succeededFuture(sourceStorageHttpResponse)).when(sourceStorageClient).postSourceStorageRecords(any()); @@ -370,6 +375,7 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx assertThat(instance.getId()).isEqualTo(instanceId); assertThat(instance.getSource()).isEqualTo("LINKED_DATA"); assertThat(instance.getIdentifiers().stream().anyMatch(i -> i.value.equals("(ld) " + linkedDataId))).isTrue(); + verify(handler).getSourceStorageRecordsClient(any(), any(), argThat(TENANT::equals), argThat(USER_ID::equals)); var recordCaptor = ArgumentCaptor.forClass(Record.class); verify(sourceStorageClient).postSourceStorageRecords(recordCaptor.capture()); diff --git a/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java b/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java index bda22bb18..9c1c54fd7 100644 --- a/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java +++ b/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java @@ -12,7 +12,7 @@ import static org.folio.rest.jaxrs.model.InstanceIngressPayload.SourceType.LINKED_DATA; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -62,6 +62,10 @@ public class UpdateInstanceIngressEventHandlerUnitTest { private static final String MAPPING_RULES_PATH = "src/test/resources/handlers/bib-rules.json"; private static final String BIB_RECORD_PATH = "src/test/resources/handlers/bib-record.json"; + public static final String TENANT = "tenant"; + public static final String OKAPI_URL = "okapiUrl"; + public static final String TOKEN = "token"; + public static final String USER_ID = "userId"; @Rule public MockitoRule initRule = MockitoJUnit.rule(); @@ -85,9 +89,10 @@ public class UpdateInstanceIngressEventHandlerUnitTest { @Before public void setUp() { - doReturn("tenant").when(context).getTenantId(); - doReturn("okapiUrl").when(context).getOkapiLocation(); - doReturn("token").when(context).getToken(); + doReturn(TENANT).when(context).getTenantId(); + doReturn(OKAPI_URL).when(context).getOkapiLocation(); + doReturn(TOKEN).when(context).getToken(); + doReturn(USER_ID).when(context).getUserId(); doReturn(instanceCollection).when(storage).getInstanceCollection(context); handler = spy(new UpdateInstanceIngressEventHandler(precedingSucceedingTitlesHelper, mappingMetadataCache, httpClient, context, storage)); @@ -332,8 +337,8 @@ public void shouldReturnFailedFuture_ifPostSourceStorageSnapshotFailed() throws var titles = List.of(JsonObject.of("id", "123")); doReturn(succeededFuture(titles)).when(precedingSucceedingTitlesHelper).getExistingPrecedingSucceedingTitles(any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).deletePrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any()); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), any()); var snapshotHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_BAD_REQUEST); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); var expectedMessage = "Failed to create snapshot in SRS, snapshot id: "; @@ -375,8 +380,8 @@ public void shouldReturnFailedFuture_ifItsFailedToGetRecordByInstanceIdFromSrsAn var titles = List.of(JsonObject.of("id", "123")); doReturn(succeededFuture(titles)).when(precedingSucceedingTitlesHelper).getExistingPrecedingSucceedingTitles(any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).deletePrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any()); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), any()); var snapshotHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); var sourceStorageHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_BAD_REQUEST); @@ -421,8 +426,8 @@ public void shouldReturnFailedFuture_ifItsFailedToPutNewRecordToSRS() throws IOE var titles = List.of(JsonObject.of("id", "123")); doReturn(succeededFuture(titles)).when(precedingSucceedingTitlesHelper).getExistingPrecedingSucceedingTitles(any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).deletePrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any()); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), any()); var snapshotHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); var existedRecordResponse = buildHttpResponseWithBuffer(BufferImpl.buffer("{\"id\":\"5e525f1e-d373-4a07-9aff-b80856bacfef\"}"), HttpStatus.SC_OK); @@ -468,8 +473,8 @@ public void shouldReturnFailedFuture_ifCreatePrecedingSucceedingTitlesFailed() t var titles = List.of(JsonObject.of("id", "123")); doReturn(succeededFuture(titles)).when(precedingSucceedingTitlesHelper).getExistingPrecedingSucceedingTitles(any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).deletePrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any()); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), any()); var snapshotHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); var existedRecordResponse = buildHttpResponseWithBuffer(BufferImpl.buffer("{\"id\":\"5e525f1e-d373-4a07-9aff-b80856bacfef\"}"), HttpStatus.SC_OK); @@ -522,8 +527,8 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx var titles = List.of(JsonObject.of("id", "123")); doReturn(succeededFuture(titles)).when(precedingSucceedingTitlesHelper).getExistingPrecedingSucceedingTitles(any(), any()); doReturn(succeededFuture()).when(precedingSucceedingTitlesHelper).deletePrecedingSucceedingTitles(any(), any()); - doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any()); - doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any()); + doReturn(sourceStorageClient).when(handler).getSourceStorageRecordsClient(any(), any(), any(), any()); + doReturn(sourceStorageSnapshotsClient).when(handler).getSourceStorageSnapshotsClient(any(), any(), any(), any()); var snapshotHttpResponse = buildHttpResponseWithBuffer(HttpStatus.SC_CREATED); doReturn(succeededFuture(snapshotHttpResponse)).when(sourceStorageSnapshotsClient).postSourceStorageSnapshots(any()); var existedRecordResponse = buildHttpResponseWithBuffer(BufferImpl.buffer("{\"matchedId\":\"" + initialSrsId + "\"}"), HttpStatus.SC_OK); @@ -546,6 +551,8 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx var recordCaptor = ArgumentCaptor.forClass(Record.class); verify(sourceStorageClient).putSourceStorageRecordsGenerationById(any(), recordCaptor.capture()); + verify(handler).getSourceStorageRecordsClient(any(), any(), argThat(TENANT::equals), argThat(USER_ID::equals)); + verify(handler).getSourceStorageSnapshotsClient(any(), any(), argThat(TENANT::equals), argThat(USER_ID::equals)); var recordSentToSRS = recordCaptor.getValue(); assertThat(recordSentToSRS.getId()).isNotNull(); assertThat(recordSentToSRS.getId()).isNotEqualTo(initialSrsId);