From c65e9a0df562156c90443ef0b9b13857246b1558 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:50:22 +0000 Subject: [PATCH 1/2] chore(deps-dev): bump org.folio.okapi:okapi-testing Bumps the dev-deps group with 1 update: [org.folio.okapi:okapi-testing](https://github.com/folio-org/okapi). Updates `org.folio.okapi:okapi-testing` from 6.0.3 to 6.1.0 - [Release notes](https://github.com/folio-org/okapi/releases) - [Changelog](https://github.com/folio-org/okapi/blob/master/NEWS.md) - [Commits](https://github.com/folio-org/okapi/compare/v6.0.3...v6.1.0) --- updated-dependencies: - dependency-name: org.folio.okapi:okapi-testing dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-deps ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 51bd97fde..fe41be2e6 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ 2.3.0-SNAPSHOT 2.11.0 - 6.0.3 + 6.1.0 5.11.3 1.20.3 2.13.0 From 36211656b45d4cb48319d591449cc9cd4b7ff667 Mon Sep 17 00:00:00 2001 From: Viacheslav Kolesnyk <94473337+viacheslavkol@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:23:34 +0100 Subject: [PATCH 2/2] feat(call-number-types): Publish domain events on changes (#1118) * feat(call-number-types): Publish domain events on changes Implements: MODINVSTOR-1275 --- NEWS.md | 1 + README.MD | 3 + descriptors/ModuleDescriptor-template.json | 1 + .../java/org/folio/InventoryKafkaTopic.java | 2 + .../persist/CallNumberTypeRepository.java | 16 ++++ .../folio/rest/impl/CallNumberTypeApi.java | 93 ++++--------------- .../callnumber/CallNumberTypeService.java | 88 ++++++++++++++++++ .../CallNumberTypeDomainEventPublisher.java | 42 +++++++++ .../rest/impl/CallNumberTypeApiTest.java | 40 +++++--- .../folio/rest/impl/CallNumberTypesIT.java | 69 ++++++++++++++ .../topic/KafkaAdminClientServiceTest.java | 3 +- 11 files changed, 266 insertions(+), 92 deletions(-) create mode 100644 src/main/java/org/folio/persist/CallNumberTypeRepository.java create mode 100644 src/main/java/org/folio/services/callnumber/CallNumberTypeService.java create mode 100644 src/main/java/org/folio/services/domainevent/CallNumberTypeDomainEventPublisher.java create mode 100644 src/test/java/org/folio/rest/impl/CallNumberTypesIT.java diff --git a/NEWS.md b/NEWS.md index e126c59c8..df66b67e8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -13,6 +13,7 @@ * Service points synchronization: implement processors ([MODINVSTOR-1246](https://folio-org.atlassian.net/browse/MODINVSTOR-1246)) * Service points synchronization: create a verticle ([MODINVSTOR-1245](https://folio-org.atlassian.net/browse/MODINVSTOR-1245)) * Do not return routing service points by default ([MODINVSTOR-1219](https://folio-org.atlassian.net/browse/MODINVSTOR-1219)) +* Implement Kafka Event Publishing for Call-Number Type CRUD Operations ([MODINVSTOR-1275](https://folio-org.atlassian.net/browse/MODINVSTOR-1275)) ### Bug fixes * Description ([ISSUE](https://folio-org.atlassian.net/browse/ISSUE)) diff --git a/README.MD b/README.MD index a4b8f3a63..cfe9f1508 100644 --- a/README.MD +++ b/README.MD @@ -106,6 +106,7 @@ These properties can be changed by setting env variable. * `KAFKA_DOMAIN_TOPIC_NUM_PARTITIONS` Default value - `50` * `KAFKA_CLASSIFICATION_TYPE_TOPIC_NUM_PARTITIONS` Default value - `1` +* `KAFKA_CALL_NUMBER_TYPE_TOPIC_NUM_PARTITIONS` Default value - `1` * `KAFKA_LOCATION_TOPIC_NUM_PARTITIONS` Default value - `1` * `KAFKA_LIBRARY_TOPIC_NUM_PARTITIONS` Default value - `1` * `KAFKA_CAMPUS_TOPIC_NUM_PARTITIONS` Default value - `1` @@ -142,6 +143,7 @@ These environment variables configure Kafka, for details see [Kafka](#kafka): * `REPLICATION_FACTOR` * `KAFKA_DOMAIN_TOPIC_NUM_PARTITIONS` * `KAFKA_CLASSIFICATION_TYPE_TOPIC_NUM_PARTITIONS` +* `KAFKA_CALL_NUMBER_TYPE_TOPIC_NUM_PARTITIONS` * `KAFKA_SUBJECT_TYPE_TOPIC_NUM_PARTITIONS` * `KAFKA_REINDEX_RECORDS_TOPIC_NUM_PARTITIONS` * `KAFKA_SUBJECT_SOURCE_TOPIC_NUM_PARTITIONS` @@ -149,6 +151,7 @@ These environment variables configure Kafka, for details see [Kafka](#kafka): These environment variables configure Kafka topic for specific business-related topics * `KAFKA_CLASSIFICATION_TYPE_TOPIC_NUM_PARTITIONS` +* `KAFKA_CALL_NUMBER_TYPE_TOPIC_NUM_PARTITIONS` * `KAFKA_LOCATION_TOPIC_NUM_PARTITIONS` * `KAFKA_LIBRARY_TOPIC_NUM_PARTITIONS` * `KAFKA_CAMPUS_TOPIC_NUM_PARTITIONS` diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 07d017494..c0eb51e2d 100755 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -2890,6 +2890,7 @@ { "name": "REPLICATION_FACTOR", "value": "1" }, { "name": "KAFKA_DOMAIN_TOPIC_NUM_PARTITIONS", "value": "50"}, { "name": "KAFKA_CLASSIFICATION_TYPE_TOPIC_NUM_PARTITIONS", "value": "1"}, + { "name": "KAFKA_CALL_NUMBER_TYPE_TOPIC_NUM_PARTITIONS", "value": "1"}, { "name": "KAFKA_LOCATION_TOPIC_NUM_PARTITIONS", "value": "1"}, { "name": "KAFKA_LIBRARY_TOPIC_NUM_PARTITIONS", "value": "1"}, { "name": "KAFKA_CAMPUS_TOPIC_NUM_PARTITIONS", "value": "1"}, diff --git a/src/main/java/org/folio/InventoryKafkaTopic.java b/src/main/java/org/folio/InventoryKafkaTopic.java index b5e3e7281..5ae58d4ec 100644 --- a/src/main/java/org/folio/InventoryKafkaTopic.java +++ b/src/main/java/org/folio/InventoryKafkaTopic.java @@ -12,6 +12,7 @@ public enum InventoryKafkaTopic implements KafkaTopic { BOUND_WITH("bound-with"), CAMPUS("campus"), CLASSIFICATION_TYPE("classification-type"), + CALL_NUMBER_TYPE("call-number-type"), HOLDINGS_RECORD("holdings-record"), INSTANCE("instance"), INSTANCE_CONTRIBUTION("instance-contribution"), @@ -34,6 +35,7 @@ public enum InventoryKafkaTopic implements KafkaTopic { */ private static final Map> TOPIC_PARTITION_MAP = Map.of( CLASSIFICATION_TYPE, Pair.of("KAFKA_CLASSIFICATION_TYPE_TOPIC_NUM_PARTITIONS", "1"), + CALL_NUMBER_TYPE, Pair.of("KAFKA_CALL_NUMBER_TYPE_TOPIC_NUM_PARTITIONS", "1"), LOCATION, Pair.of("KAFKA_LOCATION_TOPIC_NUM_PARTITIONS", "1"), LIBRARY, Pair.of("KAFKA_LIBRARY_TOPIC_NUM_PARTITIONS", "1"), CAMPUS, Pair.of("KAFKA_CAMPUS_TOPIC_NUM_PARTITIONS", "1"), diff --git a/src/main/java/org/folio/persist/CallNumberTypeRepository.java b/src/main/java/org/folio/persist/CallNumberTypeRepository.java new file mode 100644 index 000000000..9805d541c --- /dev/null +++ b/src/main/java/org/folio/persist/CallNumberTypeRepository.java @@ -0,0 +1,16 @@ +package org.folio.persist; + +import static org.folio.rest.persist.PgUtil.postgresClient; +import static org.folio.services.callnumber.CallNumberTypeService.CALL_NUMBER_TYPE_TABLE; + +import io.vertx.core.Context; +import java.util.Map; +import org.folio.rest.jaxrs.model.CallNumberType; + +public class CallNumberTypeRepository extends AbstractRepository { + + public CallNumberTypeRepository(Context context, Map okapiHeaders) { + super(postgresClient(context, okapiHeaders), CALL_NUMBER_TYPE_TABLE, CallNumberType.class); + } + +} diff --git a/src/main/java/org/folio/rest/impl/CallNumberTypeApi.java b/src/main/java/org/folio/rest/impl/CallNumberTypeApi.java index da8e9f566..edf3b6d08 100644 --- a/src/main/java/org/folio/rest/impl/CallNumberTypeApi.java +++ b/src/main/java/org/folio/rest/impl/CallNumberTypeApi.java @@ -6,75 +6,55 @@ package org.folio.rest.impl; +import static io.vertx.core.Future.succeededFuture; import static org.folio.rest.support.EndpointFailureHandler.handleFailure; -import static org.folio.rest.tools.messages.Messages.DEFAULT_LANGUAGE; import io.vertx.core.AsyncResult; import io.vertx.core.Context; -import io.vertx.core.Future; import io.vertx.core.Handler; import java.util.Map; import javax.ws.rs.core.Response; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.folio.rest.annotations.Validate; -import org.folio.rest.exceptions.BadRequestException; import org.folio.rest.jaxrs.model.CallNumberType; -import org.folio.rest.jaxrs.model.CallNumberTypes; -import org.folio.rest.persist.PgUtil; -import org.folio.rest.persist.PostgresClient; -import org.folio.rest.tools.messages.MessageConsts; -import org.folio.rest.tools.messages.Messages; -import org.folio.rest.tools.utils.TenantTool; +import org.folio.services.callnumber.CallNumberTypeService; public class CallNumberTypeApi implements org.folio.rest.jaxrs.resource.CallNumberTypes { - private static final Logger log = LogManager.getLogger(); - - private static final String REFERENCE_TABLE = "call_number_type"; - private static final String SYSTEM_CALL_NUMBER_TYPE_SOURCE = "system"; - - private final Messages messages = Messages.getInstance(); - @Validate @Override public void getCallNumberTypes(String query, String totalRecords, int offset, int limit, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - PgUtil.get(REFERENCE_TABLE, CallNumberType.class, CallNumberTypes.class, query, offset, limit, - okapiHeaders, vertxContext, GetCallNumberTypesResponse.class, asyncResultHandler); + new CallNumberTypeService(vertxContext, okapiHeaders).getByQuery(query, offset, limit) + .onSuccess(response -> asyncResultHandler.handle(succeededFuture(response))) + .onFailure(handleFailure(asyncResultHandler)); } @Validate @Override public void postCallNumberTypes(CallNumberType entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - PgUtil.post(REFERENCE_TABLE, entity, okapiHeaders, vertxContext, PostCallNumberTypesResponse.class, - asyncResultHandler); + new CallNumberTypeService(vertxContext, okapiHeaders).create(entity) + .onSuccess(response -> asyncResultHandler.handle(succeededFuture(response))) + .onFailure(handleFailure(asyncResultHandler)); } @Validate @Override public void getCallNumberTypesById(String id, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - PgUtil.getById(REFERENCE_TABLE, CallNumberType.class, id, - okapiHeaders, vertxContext, GetCallNumberTypesByIdResponse.class, asyncResultHandler); + new CallNumberTypeService(vertxContext, okapiHeaders).getByTypeId(id) + .onSuccess(response -> asyncResultHandler.handle(succeededFuture(response))) + .onFailure(handleFailure(asyncResultHandler)); } @Validate @Override public void deleteCallNumberTypesById(String id, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - try { - String tenantId = TenantTool.tenantId(okapiHeaders); - checkIfSystemCallNumberType(id, vertxContext, tenantId, "System call number type couldn't be deleted") - .compose(callNumberType -> PgUtil.deleteById(REFERENCE_TABLE, id, okapiHeaders, vertxContext, - DeleteCallNumberTypesByIdResponse.class)) - .onFailure(handleFailure(asyncResultHandler)) - .onSuccess(event -> asyncResultHandler.handle(Future.succeededFuture(event))); - } catch (Exception e) { - internalServerErrorDuringDelete(e, asyncResultHandler); - } + new CallNumberTypeService(vertxContext, okapiHeaders).delete(id) + .onSuccess(response -> asyncResultHandler.handle(succeededFuture(response))) + .onFailure(handleFailure(asyncResultHandler)); } @Validate @@ -84,47 +64,8 @@ public void putCallNumberTypesById(String id, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - try { - String tenantId = TenantTool.tenantId(okapiHeaders); - checkIfSystemCallNumberType(id, vertxContext, tenantId, "System call number type couldn't be updated") - .compose(callNumberType -> PgUtil.put(REFERENCE_TABLE, - entity, - id, - okapiHeaders, - vertxContext, - PutCallNumberTypesByIdResponse.class)) - .onFailure(handleFailure(asyncResultHandler)) - .onSuccess(event -> asyncResultHandler.handle(Future.succeededFuture(event))); - } catch (Exception e) { - internalServerErrorDuringPut(e, asyncResultHandler); - } - } - - private Future checkIfSystemCallNumberType(String id, Context vertxContext, String tenantId, - String message) { - var instance = PostgresClient.getInstance(vertxContext.owner(), tenantId); - return instance.getById(REFERENCE_TABLE, id, CallNumberType.class) - .compose(callNumberType -> { - if (isSystemSource(callNumberType)) { - return Future.failedFuture(new BadRequestException(message)); - } - return Future.succeededFuture(callNumberType); - }); - } - - private boolean isSystemSource(CallNumberType callNumberType) { - return SYSTEM_CALL_NUMBER_TYPE_SOURCE.equals(callNumberType.getSource()); - } - - private void internalServerErrorDuringDelete(Throwable e, Handler> handler) { - log.error(e.getMessage(), e); - handler.handle(Future.succeededFuture(DeleteCallNumberTypesByIdResponse - .respond500WithTextPlain(messages.getMessage(DEFAULT_LANGUAGE, MessageConsts.InternalServerError)))); - } - - private void internalServerErrorDuringPut(Throwable e, Handler> handler) { - log.error(e.getMessage(), e); - handler.handle(Future.succeededFuture(PutCallNumberTypesByIdResponse - .respond500WithTextPlain(messages.getMessage(DEFAULT_LANGUAGE, MessageConsts.InternalServerError)))); + new CallNumberTypeService(vertxContext, okapiHeaders).update(id, entity) + .onSuccess(response -> asyncResultHandler.handle(succeededFuture(response))) + .onFailure(handleFailure(asyncResultHandler)); } } diff --git a/src/main/java/org/folio/services/callnumber/CallNumberTypeService.java b/src/main/java/org/folio/services/callnumber/CallNumberTypeService.java new file mode 100644 index 000000000..2c1e6037f --- /dev/null +++ b/src/main/java/org/folio/services/callnumber/CallNumberTypeService.java @@ -0,0 +1,88 @@ +package org.folio.services.callnumber; + +import static org.folio.rest.persist.PgUtil.deleteById; +import static org.folio.rest.persist.PgUtil.get; +import static org.folio.rest.persist.PgUtil.getById; +import static org.folio.rest.persist.PgUtil.post; +import static org.folio.rest.persist.PgUtil.put; + +import io.vertx.core.Context; +import io.vertx.core.Future; +import java.util.Map; +import javax.ws.rs.core.Response; +import org.folio.persist.CallNumberTypeRepository; +import org.folio.rest.exceptions.BadRequestException; +import org.folio.rest.jaxrs.model.CallNumberType; +import org.folio.rest.jaxrs.model.CallNumberTypes; +import org.folio.rest.jaxrs.resource.CallNumberTypes.DeleteCallNumberTypesByIdResponse; +import org.folio.rest.jaxrs.resource.CallNumberTypes.GetCallNumberTypesByIdResponse; +import org.folio.rest.jaxrs.resource.CallNumberTypes.GetCallNumberTypesResponse; +import org.folio.rest.jaxrs.resource.CallNumberTypes.PostCallNumberTypesResponse; +import org.folio.rest.jaxrs.resource.CallNumberTypes.PutCallNumberTypesByIdResponse; +import org.folio.services.domainevent.CallNumberTypeDomainEventPublisher; + +public class CallNumberTypeService { + + public static final String CALL_NUMBER_TYPE_TABLE = "call_number_type"; + + private static final String SYSTEM_CALL_NUMBER_TYPE_SOURCE = "system"; + + private final Context context; + private final Map okapiHeaders; + private final CallNumberTypeRepository repository; + private final CallNumberTypeDomainEventPublisher domainEventService; + + public CallNumberTypeService(Context context, Map okapiHeaders) { + this.context = context; + this.okapiHeaders = okapiHeaders; + + this.repository = new CallNumberTypeRepository(context, okapiHeaders); + this.domainEventService = new CallNumberTypeDomainEventPublisher(context, okapiHeaders); + } + + public Future getByQuery(String cql, int offset, int limit) { + return get(CALL_NUMBER_TYPE_TABLE, CallNumberType.class, CallNumberTypes.class, + cql, offset, limit, okapiHeaders, context, GetCallNumberTypesResponse.class); + } + + public Future getByTypeId(String id) { + return getById(CALL_NUMBER_TYPE_TABLE, CallNumberType.class, id, okapiHeaders, context, + GetCallNumberTypesByIdResponse.class); + } + + public Future create(CallNumberType type) { + return post(CALL_NUMBER_TYPE_TABLE, type, okapiHeaders, context, PostCallNumberTypesResponse.class) + .onSuccess(domainEventService.publishCreated()); + } + + public Future update(String id, CallNumberType type) { + return getIfNotSystemCallNumberType(id, "System call number type couldn't be updated") + .compose(oldType -> put(CALL_NUMBER_TYPE_TABLE, type, id, okapiHeaders, context, + PutCallNumberTypesByIdResponse.class) + .onSuccess(domainEventService.publishUpdated(oldType)) + ); + } + + public Future delete(String id) { + return getIfNotSystemCallNumberType(id, "System call number type couldn't be deleted") + .compose(oldType -> deleteById(CALL_NUMBER_TYPE_TABLE, id, okapiHeaders, context, + DeleteCallNumberTypesByIdResponse.class) + .onSuccess(domainEventService.publishRemoved(oldType)) + ); + } + + private Future getIfNotSystemCallNumberType(String id, String errorMessage) { + return repository.getById(id) + .compose(callNumberType -> { + if (isSystemSource(callNumberType)) { + return Future.failedFuture(new BadRequestException(errorMessage)); + } + return Future.succeededFuture(callNumberType); + }); + } + + private boolean isSystemSource(CallNumberType callNumberType) { + return SYSTEM_CALL_NUMBER_TYPE_SOURCE.equals(callNumberType.getSource()); + } + +} diff --git a/src/main/java/org/folio/services/domainevent/CallNumberTypeDomainEventPublisher.java b/src/main/java/org/folio/services/domainevent/CallNumberTypeDomainEventPublisher.java new file mode 100644 index 000000000..fed03d59d --- /dev/null +++ b/src/main/java/org/folio/services/domainevent/CallNumberTypeDomainEventPublisher.java @@ -0,0 +1,42 @@ +package org.folio.services.domainevent; + +import static io.vertx.core.Future.succeededFuture; +import static org.folio.InventoryKafkaTopic.CALL_NUMBER_TYPE; +import static org.folio.rest.tools.utils.TenantTool.tenantId; + +import io.vertx.core.Context; +import io.vertx.core.Future; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; +import org.folio.persist.CallNumberTypeRepository; +import org.folio.rest.jaxrs.model.CallNumberType; + +public class CallNumberTypeDomainEventPublisher + extends AbstractDomainEventPublisher { + + public CallNumberTypeDomainEventPublisher(Context context, Map okapiHeaders) { + super(new CallNumberTypeRepository(context, okapiHeaders), + new CommonDomainEventPublisher<>(context, okapiHeaders, + CALL_NUMBER_TYPE.fullTopicName(tenantId(okapiHeaders)))); + } + + @Override + protected Future>> getRecordIds(Collection types) { + return succeededFuture(types.stream() + .map(type -> pair(type.getId(), type)) + .toList() + ); + } + + @Override + protected CallNumberType convertDomainToEvent(String instanceId, CallNumberType type) { + return type; + } + + @Override + protected String getId(CallNumberType type) { + return type.getId(); + } +} diff --git a/src/test/java/org/folio/rest/impl/CallNumberTypeApiTest.java b/src/test/java/org/folio/rest/impl/CallNumberTypeApiTest.java index 97b32211d..3d43ba25e 100644 --- a/src/test/java/org/folio/rest/impl/CallNumberTypeApiTest.java +++ b/src/test/java/org/folio/rest/impl/CallNumberTypeApiTest.java @@ -6,6 +6,7 @@ import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import io.vertx.core.AsyncResult; @@ -67,15 +68,20 @@ public void shouldRespondWith204_whenAttemptToDeleteNotSystemType() { @Test public void shouldHandleException_whenPut() { var callNumberTypesApi = Mockito.spy(CallNumberTypeApi.class); - Handler> errorHandler = Mockito.mock(Handler.class); - try (MockedStatic mockedTenantTool = Mockito.mockStatic(TenantTool.class)) { - mockedTenantTool.when(() -> TenantTool.tenantId(any())).thenThrow(new RuntimeException("Test")); + var errorHandler = Mockito.>>mock(); + var pgClient = mock(PostgresClient.class); + try (MockedStatic mockedTenantTool = Mockito.mockStatic(TenantTool.class); + MockedStatic mockedPgUtil = Mockito.mockStatic(PgUtil.class)) { + mockedTenantTool.when(() -> TenantTool.tenantId(anyMap())).thenReturn("Test"); + mockedPgUtil.when(() -> PgUtil.postgresClient(any(), any())).thenReturn(pgClient); + when(pgClient.getById(anyString(), any(), any(Class.class))) + .thenReturn(Future.succeededFuture(new CallNumberType().withSource("system"))); callNumberTypesApi.putCallNumberTypesById(null, null, null, errorHandler, - null); + mock(Context.class)); Mockito.verify(errorHandler).handle(any()); } @@ -84,14 +90,19 @@ public void shouldHandleException_whenPut() { @Test public void shouldHandleException_whenDelete() { var callNumberTypesApi = Mockito.spy(CallNumberTypeApi.class); - Handler> errorHandler = Mockito.mock(Handler.class); - try (MockedStatic mockedTenantTool = Mockito.mockStatic(TenantTool.class)) { - mockedTenantTool.when(() -> TenantTool.tenantId(any())).thenThrow(new RuntimeException("Test")); + var errorHandler = Mockito.>>mock(); + var pgClient = mock(PostgresClient.class); + try (MockedStatic mockedTenantTool = Mockito.mockStatic(TenantTool.class); + MockedStatic mockedPgUtil = Mockito.mockStatic(PgUtil.class)) { + mockedTenantTool.when(() -> TenantTool.tenantId(anyMap())).thenReturn("Test"); + mockedPgUtil.when(() -> PgUtil.postgresClient(any(), any())).thenReturn(pgClient); + when(pgClient.getById(anyString(), any(), any(Class.class))) + .thenReturn(Future.succeededFuture(new CallNumberType().withSource("system"))); callNumberTypesApi.deleteCallNumberTypesById(null, null, errorHandler, - null); + mock(Context.class)); Mockito.verify(errorHandler).handle(any()); } @@ -102,19 +113,19 @@ public void shouldCallPgUtilPutWithProperArgumentsAndHandleError() { //Given var callNumberTypesApi = Mockito.spy(CallNumberTypeApi.class); var entity = new CallNumberType(); - String id = "id"; + var id = "id"; Map okapiHeaders = Collections.emptyMap(); - Handler> errorHandler = Mockito.mock(Handler.class); - Context vertex = Mockito.mock(Context.class); - var mockedPgClient = Mockito.mock(PostgresClient.class); + Handler> errorHandler = mock(Handler.class); + Context vertex = mock(Context.class); + var mockedPgClient = mock(PostgresClient.class); when(mockedPgClient.getById(any(), any(), eq(CallNumberType.class))).thenReturn(Future.succeededFuture(entity)); try (MockedStatic mockedTenantTool = Mockito.mockStatic(TenantTool.class); MockedStatic mockedPgUtil = Mockito.mockStatic(PgUtil.class); MockedStatic mockedPgClientStat = Mockito.mockStatic(PostgresClient.class)) { mockedTenantTool.when(() -> TenantTool.tenantId(anyMap())).thenReturn("Test"); - mockedPgClientStat.when(() -> PostgresClient.getInstance(any(), any())).thenReturn(mockedPgClient); + mockedPgClientStat.when(() -> PgUtil.postgresClient(any(), any())).thenReturn(mockedPgClient); mockedPgUtil.when(() -> PgUtil.put( anyString(), any(), @@ -145,8 +156,7 @@ public void shouldCallPgUtilPutWithProperArgumentsAndHandleError() { private UUID create(String name, String source) { var requestBody = new JsonObject().put(NAME_FIELD, name).put(SOURCE_FIELD, source); var createResponse = callNumberTypesClient.create(requestBody); - var callNumberTypeId = createResponse.getId(); - return callNumberTypeId; + return createResponse.getId(); } private void assertCallNumberType(UUID callNumberTypeId, String name, String source) { diff --git a/src/test/java/org/folio/rest/impl/CallNumberTypesIT.java b/src/test/java/org/folio/rest/impl/CallNumberTypesIT.java new file mode 100644 index 000000000..c5dda72f7 --- /dev/null +++ b/src/test/java/org/folio/rest/impl/CallNumberTypesIT.java @@ -0,0 +1,69 @@ +package org.folio.rest.impl; + +import static org.folio.services.callnumber.CallNumberTypeService.CALL_NUMBER_TYPE_TABLE; + +import java.util.List; +import java.util.function.Function; +import java.util.function.UnaryOperator; +import org.folio.rest.jaxrs.model.CallNumberType; +import org.folio.rest.jaxrs.model.CallNumberTypes; +import org.folio.rest.jaxrs.model.Metadata; + +class CallNumberTypesIT extends BaseReferenceDataIntegrationTest { + + @Override + protected String referenceTable() { + return CALL_NUMBER_TYPE_TABLE; + } + + @Override + protected String resourceUrl() { + return "/call-number-types"; + } + + @Override + protected Class targetClass() { + return CallNumberType.class; + } + + @Override + protected Class collectionClass() { + return CallNumberTypes.class; + } + + @Override + protected CallNumberType sampleRecord() { + return new CallNumberType().withName("test-type").withSource("test-source"); + } + + @Override + protected Function> collectionRecordsExtractor() { + return CallNumberTypes::getCallNumberTypes; + } + + @Override + protected List> recordFieldExtractors() { + return List.of(CallNumberType::getName, CallNumberType::getSource); + } + + @Override + protected Function idExtractor() { + return CallNumberType::getId; + } + + @Override + protected Function metadataExtractor() { + return CallNumberType::getMetadata; + } + + @Override + protected UnaryOperator recordModifyingFunction() { + return callNumberType -> callNumberType.withName("name-updated").withSource("source-updated"); + } + + @Override + protected List queries() { + return List.of("name==test-type", "source=test-source"); + } + +} diff --git a/src/test/java/org/folio/services/kafka/topic/KafkaAdminClientServiceTest.java b/src/test/java/org/folio/services/kafka/topic/KafkaAdminClientServiceTest.java index 9ae91d8fd..ec1497ff1 100644 --- a/src/test/java/org/folio/services/kafka/topic/KafkaAdminClientServiceTest.java +++ b/src/test/java/org/folio/services/kafka/topic/KafkaAdminClientServiceTest.java @@ -43,7 +43,8 @@ public class KafkaAdminClientServiceTest { "folio.foo-tenant.inventory.location", "folio.foo-tenant.inventory.library", "folio.foo-tenant.inventory.campus", "folio.foo-tenant.inventory.subject-type", "folio.foo-tenant.inventory.institution", "folio.foo-tenant.inventory.reindex-records", - "folio.foo-tenant.inventory.subject-source", "folio.foo-tenant.inventory.instance-date-type"); + "folio.foo-tenant.inventory.subject-source", "folio.foo-tenant.inventory.instance-date-type", + "folio.foo-tenant.inventory.call-number-type"); private KafkaAdminClient mockClient; private Vertx vertx;