Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Bugfix release v1.0.3 (Ramsons R2 2024 Bug Fix) #92

Merged
merged 6 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.3 2024-12-30
* DCB transaction status synchronization (MODTLR-112)
* Resolve central tenant ID dynamically (MODTLR-118)
*
## 1.0.2 2024-12-12
* Copy Secure Patron name when cloning users (MODTLR-116)
* Support for intermediate requests (MODTLR-98)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<groupId>org.folio</groupId>
<artifactId>mod-tlr</artifactId>
<name>mod-tlr</name>
<version>1.0.3-SNAPSHOT</version>
<version>1.0.4-SNAPSHOT</version>
<description>FOLIO mod-tlr module</description>
<packaging>jar</packaging>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.folio.client.feign;

import org.folio.domain.dto.ConsortiaConfiguration;
import org.folio.spring.config.FeignClientConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name = "consortia-configuration", url = "consortia-configuration", configuration = FeignClientConfiguration.class)
public interface ConsortiaConfigurationClient {

@GetMapping
ConsortiaConfiguration getConfiguration();
}
13 changes: 0 additions & 13 deletions src/main/java/org/folio/domain/Constants.java

This file was deleted.

99 changes: 50 additions & 49 deletions src/main/java/org/folio/listener/kafka/KafkaEventListener.java
Original file line number Diff line number Diff line change
@@ -1,114 +1,115 @@
package org.folio.listener.kafka;

import static org.folio.domain.Constants.CENTRAL_TENANT_ID;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;

import org.folio.domain.dto.Loan;
import org.folio.domain.dto.Request;
import org.folio.domain.dto.RequestsBatchUpdate;
import org.folio.domain.dto.User;
import org.folio.domain.dto.UserGroup;
import org.folio.exception.KafkaEventDeserializationException;
import org.folio.service.ConsortiaService;
import org.folio.service.KafkaEventHandler;
import org.folio.service.impl.LoanEventHandler;
import org.folio.service.impl.RequestBatchUpdateEventHandler;
import org.folio.service.impl.RequestEventHandler;
import org.folio.service.impl.UserEventHandler;
import org.folio.service.impl.UserGroupEventHandler;
import org.folio.spring.DefaultFolioExecutionContext;
import org.folio.spring.FolioExecutionContext;
import org.folio.spring.FolioModuleMetadata;
import org.folio.spring.integration.XOkapiHeaders;
import org.folio.spring.scope.FolioExecutionContextSetter;
import org.folio.spring.service.SystemUserScopedExecutionService;
import org.folio.support.KafkaEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;

@Component
@Log4j2
@RequiredArgsConstructor
public class KafkaEventListener {
private static final ObjectMapper objectMapper = new ObjectMapper();
private final RequestEventHandler requestEventHandler;
private final LoanEventHandler loanEventHandler;
private final UserGroupEventHandler userGroupEventHandler;
private final UserEventHandler userEventHandler;
private final SystemUserScopedExecutionService systemUserScopedExecutionService;
private final RequestBatchUpdateEventHandler requestBatchEventHandler;

public KafkaEventListener(@Autowired RequestEventHandler requestEventHandler,
@Autowired RequestBatchUpdateEventHandler requestBatchEventHandler,
@Autowired SystemUserScopedExecutionService systemUserScopedExecutionService,
@Autowired UserGroupEventHandler userGroupEventHandler,
@Autowired UserEventHandler userEventHandler) {

this.requestEventHandler = requestEventHandler;
this.systemUserScopedExecutionService = systemUserScopedExecutionService;
this.userGroupEventHandler = userGroupEventHandler;
this.requestBatchEventHandler = requestBatchEventHandler;
this.userEventHandler = userEventHandler;
}
private final ConsortiaService consortiaService;
private final FolioModuleMetadata folioModuleMetadata;

@KafkaListener(
topicPattern = "${folio.environment}\\.\\w+\\.circulation\\.request",
groupId = "${spring.kafka.consumer.group-id}"
)
public void handleRequestEvent(String eventString, MessageHeaders messageHeaders) {
log.debug("handleRequestEvent:: event: {}", () -> eventString);
KafkaEvent<Request> event = deserialize(eventString, messageHeaders, Request.class);
log.info("handleRequestEvent:: event received: {}", event::getId);
handleEvent(event, requestEventHandler);
log.info("handleRequestEvent:: event consumed: {}", event::getId);
public void handleRequestEvent(String eventString, @Headers Map<String, Object> messageHeaders) {
handleEvent(eventString, requestEventHandler, messageHeaders, Request.class);
}

@KafkaListener(
topicPattern = "${folio.environment}\\.\\w+\\.circulation\\.request-queue-reordering",
topicPattern = "${folio.environment}\\.\\w+\\.circulation\\.loan",
groupId = "${spring.kafka.consumer.group-id}"
)
public void handleRequestBatchUpdateEvent(String eventString, MessageHeaders messageHeaders) {
log.debug("handleRequestBatchUpdateEvent:: event: {}", () -> eventString);
KafkaEvent<RequestsBatchUpdate> event = deserialize(eventString, messageHeaders, RequestsBatchUpdate.class);
log.info("handleRequestBatchUpdateEvent:: event received: {}", event::getId);
handleEvent(event, requestBatchEventHandler);
log.info("handleRequestBatchUpdateEvent:: event consumed: {}", event::getId);
public void handleLoanEvent(String eventString, @Headers Map<String, Object> messageHeaders) {
handleEvent(eventString, loanEventHandler, messageHeaders, Loan.class);
}

private <T> void handleEvent(KafkaEvent<T> event, KafkaEventHandler<T> handler) {
try {
systemUserScopedExecutionService.executeAsyncSystemUserScoped(CENTRAL_TENANT_ID,
() -> handler.handle(event));
} catch (Exception e) {
log.error("handleEvent:: Failed to handle Kafka event in tenant {}", CENTRAL_TENANT_ID);
}
@KafkaListener(
topicPattern = "${folio.environment}\\.\\w+\\.circulation\\.request-queue-reordering",
groupId = "${spring.kafka.consumer.group-id}"
)
public void handleRequestBatchUpdateEvent(String eventString, @Headers Map<String, Object> messageHeaders) {
handleEvent(eventString, requestBatchEventHandler, messageHeaders, RequestsBatchUpdate.class);
}

@KafkaListener(
topicPattern = "${folio.environment}\\.\\w+\\.users\\.userGroup",
groupId = "${spring.kafka.consumer.group-id}"
)
public void handleUserGroupEvent(String eventString, MessageHeaders messageHeaders) {
KafkaEvent<UserGroup> event = deserialize(eventString, messageHeaders, UserGroup.class);

log.info("handleUserGroupEvent:: event received: {}", event::getId);
log.debug("handleUserGroupEvent:: event: {}", () -> event);
handleEvent(event, userGroupEventHandler);
public void handleUserGroupEvent(String eventString, @Headers Map<String, Object> messageHeaders) {
handleEvent(eventString, userGroupEventHandler, messageHeaders, UserGroup.class);
}

@KafkaListener(
topicPattern = "${folio.environment}\\.\\w+\\.users\\.users",
groupId = "${spring.kafka.consumer.group-id}"
)
public void handleUserEvent(String eventString, MessageHeaders messageHeaders) {
KafkaEvent<User> event = deserialize(eventString, messageHeaders, User.class);
public void handleUserEvent(String eventString, @Headers Map<String, Object> messageHeaders) {
handleEvent(eventString, userEventHandler, messageHeaders, User.class);
}

private <T> void handleEvent(String eventString, KafkaEventHandler<T> handler,
Map<String, Object> messageHeaders, Class<T> payloadType) {

log.info("handleUserEvent:: event received: {}", event::getId);
handleEvent(event, userEventHandler);
log.debug("handleEvent:: event: {}", () -> eventString);
KafkaEvent<T> event = deserialize(eventString, messageHeaders, payloadType);
log.info("handleEvent:: event received: {}", event::getId);

FolioExecutionContext context = DefaultFolioExecutionContext.fromMessageHeaders(
folioModuleMetadata, messageHeaders);

try (FolioExecutionContextSetter contextSetter = new FolioExecutionContextSetter(context)) {
String centralTenantId = consortiaService.getCentralTenantId();
systemUserScopedExecutionService.executeAsyncSystemUserScoped(centralTenantId,
() -> handler.handle(event));
} catch (Exception e) {
log.error("handleEvent:: failed to handle event {}", event.getId(), e);
}
log.info("handleEvent:: event consumed: {}", event::getId);
}

private static <T> KafkaEvent<T> deserialize(String eventString, MessageHeaders messageHeaders,
private static <T> KafkaEvent<T> deserialize(String eventString, Map<String, Object> messageHeaders,
Class<T> dataType) {

try {
Expand All @@ -125,7 +126,7 @@ private static <T> KafkaEvent<T> deserialize(String eventString, MessageHeaders
}
}

private static String getHeaderValue(MessageHeaders headers, String headerName) {
private static String getHeaderValue(Map<String, Object> headers, String headerName) {
log.debug("getHeaderValue:: headers: {}, headerName: {}", () -> headers, () -> headerName);
var headerValue = headers.get(headerName);
var value = headerValue == null
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/folio/repository/EcsTlrRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ public interface EcsTlrRepository extends JpaRepository<EcsTlrEntity, UUID> {
Optional<EcsTlrEntity> findByPrimaryRequestId(UUID primaryRequestId);
Optional<EcsTlrEntity> findByInstanceId(UUID instanceId);
List<EcsTlrEntity> findByPrimaryRequestIdIn(List<UUID> primaryRequestIds);
List<EcsTlrEntity> findByItemId(UUID itemId);
}
1 change: 1 addition & 0 deletions src/main/java/org/folio/service/ConsortiaService.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
public interface ConsortiaService {
TenantCollection getAllConsortiumTenants(String consortiumId);
Collection<Tenant> getAllConsortiumTenants();
String getCentralTenantId();
}
5 changes: 3 additions & 2 deletions src/main/java/org/folio/service/DcbService.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public interface DcbService {
void createBorrowerTransaction(EcsTlrEntity ecsTlr, Request request);
void createBorrowingPickupTransaction(EcsTlrEntity ecsTlr, Request request);
void createPickupTransaction(EcsTlrEntity ecsTlr, Request request);
void updateTransactionStatuses(TransactionStatus.StatusEnum newStatus, EcsTlrEntity ecsTlr);
TransactionStatusResponse getTransactionStatus(UUID transactionId, String tenantId);
TransactionStatusResponse updateTransactionStatus(UUID transactionId,
TransactionStatus.StatusEnum newStatus, String tenantId);
void updateTransactionStatus(UUID transactionId, TransactionStatus.StatusEnum newStatus,
String tenantId);
}
13 changes: 13 additions & 0 deletions src/main/java/org/folio/service/impl/ConsortiaServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.util.Optional;

import org.folio.client.feign.ConsortiaClient;
import org.folio.client.feign.ConsortiaConfigurationClient;
import org.folio.domain.dto.ConsortiaConfiguration;
import org.folio.domain.dto.Tenant;
import org.folio.domain.dto.TenantCollection;
import org.folio.domain.dto.UserTenant;
Expand All @@ -21,6 +23,7 @@
@RequiredArgsConstructor
public class ConsortiaServiceImpl implements ConsortiaService {
private final ConsortiaClient consortiaClient;
private final ConsortiaConfigurationClient consortiaConfigurationClient;
private final UserTenantsService userTenantsService;

@Override
Expand All @@ -40,4 +43,14 @@ public Collection<Tenant> getAllConsortiumTenants() {
log.info("getAllConsortiumTenants:: found {} consortium tenants", tenants::size);
return tenants;
}

@Override
public String getCentralTenantId() {
log.info("getCentralTenantId:: resolving central tenant ID");
String centralTenantId = Optional.ofNullable(consortiaConfigurationClient.getConfiguration())
.map(ConsortiaConfiguration::getCentralTenantId)
.orElseThrow();
log.info("getCentralTenantId:: central tenant ID: {}", centralTenantId);
return centralTenantId;
}
}
Loading
Loading