Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ class SubscriptionApiTest {

@Test
void round_trip_subscription_should_work_ok() throws InterruptedException {
final String postUrl = String.format("%s/client-subscriptions", baseUrl);
final String callbackUrl = "https://my-callback-url";
final String postUrl = String.format("%s/client-subscriptions?callbackUrl=%s", baseUrl, callbackUrl);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
final String body = "{\"eventTypes\":[\"PRISON_COURT_REGISTER_GENERATED\",\"CUSTODIAL_RESULT\"],\n" +
"\"notificationEndpoint\":{\"webhookUrl\":\"https://my-callback-url\"}}";
final String body = "{\"eventTypes\":[\"PRISON_COURT_REGISTER_GENERATED\",\"CUSTODIAL_RESULT\"]}";
final ResponseEntity<String> postResult = http.exchange(
postUrl,
HttpMethod.POST,
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ apply {
}

dependencies {
implementation(group: 'uk.gov.hmcts.cp', name: 'api-cp-crime-hearing-case-event-subscription', version: '1.0.4')
implementation(group: 'uk.gov.hmcts.cp', name: 'api-cp-crime-hearing-case-event-subscription', version: '1.0.6')

// This is proving to be a real puzzle. This is actually included in the api published pom
// ( though with scope of "runtime" )
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package uk.gov.hmcts.cp.subscription.controllers;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;
import uk.gov.hmcts.cp.openapi.api.NotificationApi;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayload;
Expand All @@ -18,8 +18,7 @@ public class NotificationController implements NotificationApi {
private final NotificationService notificationService;

@Override
@Transactional
public ResponseEntity<Void> createNotificationPCR(final PcrEventPayload pcrEventPayload) {
public ResponseEntity<Void> createNotificationPCR(@Valid final PcrEventPayload pcrEventPayload) {
notificationService.processPcrEvent(pcrEventPayload.getMaterialId());
return new ResponseEntity<>(HttpStatus.ACCEPTED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.HtmlUtils;

import uk.gov.hmcts.cp.openapi.api.SubscriptionApi;
import uk.gov.hmcts.cp.openapi.model.ClientSubscription;
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.openapi.model.CreateClientSubscriptionRequest;
import uk.gov.hmcts.cp.subscription.services.SubscriptionService;

import java.util.UUID;
Expand All @@ -24,16 +27,18 @@

@Override
@Transactional
public ResponseEntity<ClientSubscription> createClientSubscription(final ClientSubscriptionRequest request) {
log.info("createClientSubscription clientId:{}", CLIENT_ID);
final ClientSubscription response = subscriptionService.saveSubscription(request);
public ResponseEntity<ClientSubscription> createClientSubscription(final String callbackUrl,
final CreateClientSubscriptionRequest request) {
log.info("createClientSubscription callbackUrl:{} clientId:{}", HtmlUtils.htmlEscape(callbackUrl), CLIENT_ID);
final ClientSubscription response = subscriptionService.saveSubscription(callbackUrl, request);
log.info("createClientSubscription created subscription:{}", response.getClientSubscriptionId());
return new ResponseEntity<>(response, HttpStatus.CREATED);
}

@Override
@Transactional
public ResponseEntity<ClientSubscription> updateClientSubscription(final UUID clientSubscriptionId, final ClientSubscriptionRequest request) {
public ResponseEntity<ClientSubscription> updateClientSubscription(final UUID clientSubscriptionId,
final ClientSubscriptionRequest request) {
log.info("updateClientSubscription clientSubscriptionId:{} clientId:{}", clientSubscriptionId, CLIENT_ID);
final ClientSubscription response = subscriptionService.updateSubscription(clientSubscriptionId, request);
return new ResponseEntity<>(response, HttpStatus.OK);
Expand All @@ -54,4 +59,5 @@
subscriptionService.deleteSubscription(clientSubscriptionId);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package uk.gov.hmcts.cp.subscription.controllers;
package uk.gov.hmcts.cp.subscription.controllers.advice;

import feign.FeignException;
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;

Expand All @@ -31,6 +33,14 @@ public ResponseEntity<String> handleClientException(final HttpClientErrorExcepti
.body(exception.getMessage());
}

@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<String> handleHttpMessageNotReadable(final HttpMessageNotReadableException exception) {
log.error("Invalid request body: {}", exception.getMessage());
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body("");
}

@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleUnknownException(final Exception exception) {
log.error("Exception {}", exception.getMessage());
Expand All @@ -50,4 +60,10 @@ public ResponseEntity<String> handleFeignException(final FeignException ex) {
.status(status)
.body(ex.contentUTF8());
}

@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Void> handleConstraintViolation(final ConstraintViolationException ex) {
log.error("Exception {}", ex.getMessage());
return ResponseEntity.badRequest().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.mapstruct.NullValueMappingStrategy;
import uk.gov.hmcts.cp.openapi.model.ClientSubscription;
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.openapi.model.CreateClientSubscriptionRequest;
import uk.gov.hmcts.cp.openapi.model.EventType;
import uk.gov.hmcts.cp.openapi.model.NotificationEndpoint;
import uk.gov.hmcts.cp.subscription.entities.ClientSubscriptionEntity;
Expand All @@ -24,10 +25,10 @@

@Mapping(target = "id", expression = "java(null)")
@Mapping(source = "request.eventTypes", target = "eventTypes", qualifiedByName = "mapWithSortedEventTypes")
@Mapping(source = "request.notificationEndpoint", target = "notificationEndpoint", qualifiedByName = "mapFromNotificationEndpoint")
@Mapping(target = "notificationEndpoint", expression = "java(callbackUrl)")
@Mapping(target = "createdAt", expression = "java(clockService.nowOffsetUTC())")
@Mapping(target = "updatedAt", expression = "java(clockService.nowOffsetUTC())")
ClientSubscriptionEntity mapCreateRequestToEntity(@Context ClockService clockService, ClientSubscriptionRequest request);
ClientSubscriptionEntity mapCreateRequestToEntity(@Context ClockService clockService, final String callbackUrl, CreateClientSubscriptionRequest request);

Check failure on line 31 in src/main/java/uk/gov/hmcts/cp/subscription/mappers/SubscriptionMapper.java

View workflow job for this annotation

GitHub Actions / pmd-analysis

Final parameter in abstract method

Declaring a method parameter as final for an interface method is useless because the implementation may choose to not respect it. FinalParameterInAbstractMethod (Priority: 1, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#finalparameterinabstractmethod

@Mapping(source = "existing.id", target = "id")
@Mapping(source = "request.eventTypes", target = "eventTypes", qualifiedByName = "mapWithSortedEventTypes")
Expand All @@ -43,16 +44,16 @@

@Named("mapWithSortedEventTypes")
static List<EntityEventType> sortedEventTypes(final List<EventType> events) {
final List<String> sorted = events.stream().map(e -> e.name()).sorted().collect(toList());
return sorted.stream().map(e -> EntityEventType.valueOf(e)).toList();
final List<String> sorted = events.stream().map(Enum::name).sorted().collect(toList());
return sorted.stream().map(EntityEventType::valueOf).toList();
}

@Named("mapFromNotificationEndpoint")
static String mapFromNotificationEndpoint(final NotificationEndpoint notificationEndpoint) {
return notificationEndpoint.getWebhookUrl().toString();
return notificationEndpoint.getCallbackUrl();
}

static NotificationEndpoint mapToNotificationEndpoint(final String endpointUrl) {
return NotificationEndpoint.builder().webhookUrl(endpointUrl).build();
return NotificationEndpoint.builder().callbackUrl(endpointUrl).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.stereotype.Service;
import uk.gov.hmcts.cp.openapi.model.ClientSubscription;
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.openapi.model.CreateClientSubscriptionRequest;
import uk.gov.hmcts.cp.subscription.entities.ClientSubscriptionEntity;
import uk.gov.hmcts.cp.subscription.mappers.SubscriptionMapper;
import uk.gov.hmcts.cp.subscription.repositories.SubscriptionRepository;
Expand All @@ -20,8 +21,8 @@ public class SubscriptionService {
private final SubscriptionRepository subscriptionRepository;
private final SubscriptionMapper mapper;

public ClientSubscription saveSubscription(final ClientSubscriptionRequest request) {
final ClientSubscriptionEntity entity = mapper.mapCreateRequestToEntity(clockService, request);
public ClientSubscription saveSubscription(final String callbackUrl, final CreateClientSubscriptionRequest request) {
final ClientSubscriptionEntity entity = mapper.mapCreateRequestToEntity(clockService, callbackUrl, request);
return mapper.mapEntityToResponse(clockService, subscriptionRepository.save(entity));
}

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package uk.gov.hmcts.cp.subscription.controllers;
package uk.gov.hmcts.cp.subscription.integration;

import feign.FeignException;
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;

@RestControllerAdvice
@Component("integrationGlobalExceptionHandler")
public class GlobalExceptionHandler {

private static final String NOT_FOUND_MESSAGE = "No row with the given identifier exists";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import org.springframework.test.web.servlet.MockMvc;
import uk.gov.hmcts.cp.openapi.model.ClientSubscriptionRequest;
import uk.gov.hmcts.cp.openapi.model.NotificationEndpoint;
import uk.gov.hmcts.cp.subscription.config.TestContainersInitialise;
import uk.gov.hmcts.cp.subscription.integration.config.TestContainersInitialise;
import uk.gov.hmcts.cp.subscription.entities.ClientSubscriptionEntity;
import uk.gov.hmcts.cp.subscription.model.EntityEventType;
import uk.gov.hmcts.cp.subscription.repositories.SubscriptionRepository;
Expand All @@ -32,10 +32,10 @@ public abstract class IntegrationTestBase {
@Autowired
protected SubscriptionRepository subscriptionRepository;

NotificationEndpoint notificationEndpoint = NotificationEndpoint.builder()
.webhookUrl("https://my-callback-url")
protected NotificationEndpoint notificationEndpoint = NotificationEndpoint.builder()
.callbackUrl("https://my-callback-url")
.build();
ClientSubscriptionRequest request = ClientSubscriptionRequest.builder()
protected ClientSubscriptionRequest request = ClientSubscriptionRequest.builder()
.notificationEndpoint(notificationEndpoint)
.eventTypes(List.of(PRISON_COURT_REGISTER_GENERATED, CUSTODIAL_RESULT))
.build();
Expand Down
Loading
Loading