Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ dependencies {
// Yet we still need to add it manually. Grrr. TBC.
implementation "io.swagger.core.v3:swagger-annotations:2.2.42"
implementation("org.owasp.encoder:encoder:1.4.0")
implementation 'org.awaitility:awaitility:4.2.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestTemplate;
import uk.gov.hmcts.cp.subscription.services.ClockService;
import uk.gov.hmcts.cp.subscription.services.exceptions.MaterialMetadataNotReadyException;
import uk.gov.hmcts.cp.subscription.services.exceptions.CallbackUrlDeliveryException;

import java.time.Clock;
import java.util.Map;

@Configuration
public class AppConfig {
Expand All @@ -29,12 +25,4 @@ public RestClient restClient() {
public ClockService clockService() {
return new ClockService(Clock.systemDefaultZone());
}

@Bean
public RetryTemplate retryTemplate() {
return RetryTemplateConfig.retryConfig().toRetryTemplate( Map.of(
MaterialMetadataNotReadyException.class, true,
CallbackUrlDeliveryException.class, true
));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.awaitility.core.ConditionTimeoutException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
Expand Down Expand Up @@ -79,4 +80,12 @@ public ResponseEntity<String> handleUnsupportedOperation(final UnsupportedOperat
.status(HttpStatus.NOT_IMPLEMENTED)
.body("Unsupported");
}

@ExceptionHandler(ConditionTimeoutException.class)
public ResponseEntity<String> handleConditionTimeout(final ConditionTimeoutException ex) {
log.error("Material metadata timed out: {}", ex.getMessage());
return ResponseEntity
.status(HttpStatus.GATEWAY_TIMEOUT)
.body("Material metadata not ready");
}
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,63 @@
package uk.gov.hmcts.cp.subscription.services;

import lombok.RequiredArgsConstructor;
import static java.time.Duration.ofSeconds;
import static org.awaitility.Awaitility.await;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import uk.gov.hmcts.cp.material.openapi.api.MaterialApi;
import uk.gov.hmcts.cp.material.openapi.model.MaterialMetadata;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayload;
import uk.gov.hmcts.cp.subscription.model.EntityEventType;
import uk.gov.hmcts.cp.subscription.services.exceptions.MaterialMetadataNotReadyException;

import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;

@Service
@RequiredArgsConstructor
@Slf4j
public class NotificationService {

private final MaterialApi materialApi;
private final DocumentService documentService;
@Qualifier("retryTemplate")
private final RetryTemplate materialRetryTemplate;
private final Duration waitTimeout;
private final Duration pollInterval;

@Autowired
public NotificationService(final MaterialApi materialApi,
final DocumentService documentService) {
this(materialApi, documentService, ofSeconds(30), ofSeconds(5));
}

public NotificationService(final MaterialApi materialApi,
final DocumentService documentService,
final Duration waitTimeout,
final Duration pollInterval) {
this.materialApi = materialApi;
this.documentService = documentService;
this.waitTimeout = waitTimeout;
this.pollInterval = pollInterval;
}

public void processInboundEvent(final PcrEventPayload pcrEventPayload) {
final MaterialMetadata materialMetadata = materialRetryTemplate.execute(context ->
waitForMaterialMetadata(pcrEventPayload.getMaterialId()));
final MaterialMetadata materialMetadata = waitForMaterialMetadata(pcrEventPayload.getMaterialId());

final EntityEventType eventType = EntityEventType.valueOf(pcrEventPayload.getEventType().name());
documentService.saveDocumentMapping(materialMetadata.getMaterialId(), eventType);
}

private MaterialMetadata waitForMaterialMetadata(final UUID materialId) {
final MaterialMetadata response = materialApi.getMaterialMetadataByMaterialId(materialId);
if (response == null) {
throw new MaterialMetadataNotReadyException("PCR - Material metadata not ready for materialId: " + materialId);
}
return response;
final AtomicReference<MaterialMetadata> materialResponse = new AtomicReference<>();
await()
.atMost(waitTimeout)
.pollInterval(pollInterval)
.until(() -> {
final MaterialMetadata response = materialApi.getMaterialMetadataByMaterialId(materialId);
materialResponse.set(response);
return response != null;
});
return materialResponse.get();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.gov.hmcts.cp.subscription.services;

import lombok.Builder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
Expand Down Expand Up @@ -77,12 +78,28 @@ void get_document_content_should_return_response() {
}

private Material createMaterial() {
// TODO Lets make material have a builder so we can make it immutable!
Material material = new Material();
material.setContentUrl("http://material-servce");
MaterialMetadata materialMetadata = new MaterialMetadata();
materialMetadata.setFileName("file.pdf");
material.setMetadata(materialMetadata);
return material;
return TestMaterialBuilder.builder()
.contentUrl("http://material-servce")
.fileName("file.pdf")
.build()
.toMaterial();
}

@Builder
private static final class TestMaterialBuilder {

private final String contentUrl;
private final String fileName;

Material toMaterial() {
Material material = new Material();
material.setContentUrl(contentUrl);

MaterialMetadata metadata = new MaterialMetadata();
metadata.setFileName(fileName);
material.setMetadata(metadata);

return material;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.retry.support.RetryTemplate;
import org.awaitility.core.ConditionTimeoutException;

import uk.gov.hmcts.cp.material.openapi.api.MaterialApi;
import uk.gov.hmcts.cp.material.openapi.model.MaterialMetadata;
import uk.gov.hmcts.cp.openapi.model.EventType;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayload;
import uk.gov.hmcts.cp.subscription.services.DocumentService;
import uk.gov.hmcts.cp.subscription.services.NotificationService;
import uk.gov.hmcts.cp.subscription.services.exceptions.MaterialMetadataNotReadyException;

import java.util.UUID;

import static java.time.Duration.ofMillis;
import static java.util.UUID.randomUUID;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
Expand All @@ -34,16 +34,16 @@ class NotificationServiceTest {
@Mock
private DocumentService documentService;

@Mock
private RetryTemplate materialRetryTemplate;

@InjectMocks
private NotificationService notificationService;

@BeforeEach
void setUp() {
when(materialRetryTemplate.execute(any())).thenAnswer(invocation ->
invocation.getArgument(0, org.springframework.retry.RetryCallback.class).doWithRetry(null));
notificationService = new NotificationService(
materialApi,
documentService,
ofMillis(100),
ofMillis(10)
);
}

@Test
Expand Down Expand Up @@ -72,6 +72,6 @@ void shouldThrowExceptionWhenMaterialMetadataNotReady() {
.build();
when(materialApi.getMaterialMetadataByMaterialId(any(UUID.class))).thenReturn(null);

assertThrows(MaterialMetadataNotReadyException.class, () -> notificationService.processInboundEvent(payload));
assertThrows(ConditionTimeoutException.class, () -> notificationService.processInboundEvent(payload));
}
}
Loading