Skip to content

Commit

Permalink
Merge branch 'master' into MODINVSTOR-1292
Browse files Browse the repository at this point in the history
  • Loading branch information
julianladisch committed Dec 4, 2024
2 parents b0e3016 + 3621165 commit 85327a7
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 93 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
* Add item barcode right truncation search index ([MODINVSTOR-1292](https://folio-org.atlassian.net/browse/MODINVSTOR-1292))
Expand Down
3 changes: 3 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -142,13 +143,15 @@ 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`


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`
Expand Down
1 change: 1 addition & 0 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<folio-s3-client.version>2.3.0-SNAPSHOT</folio-s3-client.version>
<google-code-gson.version>2.11.0</google-code-gson.version>

<okapi-testing.version>6.0.3</okapi-testing.version>
<okapi-testing.version>6.1.0</okapi-testing.version>
<junit.version>5.11.3</junit.version>
<testcontainers.version>1.20.3</testcontainers.version>
<joda-time.version>2.13.0</joda-time.version>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/folio/InventoryKafkaTopic.java
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand All @@ -34,6 +35,7 @@ public enum InventoryKafkaTopic implements KafkaTopic {
*/
private static final Map<InventoryKafkaTopic, Pair<String, String>> 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"),
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/org/folio/persist/CallNumberTypeRepository.java
Original file line number Diff line number Diff line change
@@ -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<CallNumberType> {

public CallNumberTypeRepository(Context context, Map<String, String> okapiHeaders) {
super(postgresClient(context, okapiHeaders), CALL_NUMBER_TYPE_TABLE, CallNumberType.class);
}

}
93 changes: 17 additions & 76 deletions src/main/java/org/folio/rest/impl/CallNumberTypeApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> okapiHeaders,
Handler<AsyncResult<Response>> 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<String, String> okapiHeaders,
Handler<AsyncResult<Response>> 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<String, String> okapiHeaders,
Handler<AsyncResult<Response>> 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<String, String> okapiHeaders,
Handler<AsyncResult<Response>> 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
Expand All @@ -84,47 +64,8 @@ public void putCallNumberTypesById(String id,
Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> 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<CallNumberType> 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<AsyncResult<Response>> handler) {
log.error(e.getMessage(), e);
handler.handle(Future.succeededFuture(DeleteCallNumberTypesByIdResponse
.respond500WithTextPlain(messages.getMessage(DEFAULT_LANGUAGE, MessageConsts.InternalServerError))));
}

private void internalServerErrorDuringPut(Throwable e, Handler<AsyncResult<Response>> 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));
}
}
Original file line number Diff line number Diff line change
@@ -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<String, String> okapiHeaders;
private final CallNumberTypeRepository repository;
private final CallNumberTypeDomainEventPublisher domainEventService;

public CallNumberTypeService(Context context, Map<String, String> okapiHeaders) {
this.context = context;
this.okapiHeaders = okapiHeaders;

this.repository = new CallNumberTypeRepository(context, okapiHeaders);
this.domainEventService = new CallNumberTypeDomainEventPublisher(context, okapiHeaders);
}

public Future<Response> 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<Response> getByTypeId(String id) {
return getById(CALL_NUMBER_TYPE_TABLE, CallNumberType.class, id, okapiHeaders, context,
GetCallNumberTypesByIdResponse.class);
}

public Future<Response> create(CallNumberType type) {
return post(CALL_NUMBER_TYPE_TABLE, type, okapiHeaders, context, PostCallNumberTypesResponse.class)
.onSuccess(domainEventService.publishCreated());
}

public Future<Response> 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<Response> 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<CallNumberType> 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());
}

}
Original file line number Diff line number Diff line change
@@ -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<CallNumberType, CallNumberType> {

public CallNumberTypeDomainEventPublisher(Context context, Map<String, String> okapiHeaders) {
super(new CallNumberTypeRepository(context, okapiHeaders),
new CommonDomainEventPublisher<>(context, okapiHeaders,
CALL_NUMBER_TYPE.fullTopicName(tenantId(okapiHeaders))));
}

@Override
protected Future<List<Pair<String, CallNumberType>>> getRecordIds(Collection<CallNumberType> 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();
}
}
Loading

0 comments on commit 85327a7

Please sign in to comment.