From de66a7fc043d4909358754101ef4323bf9ec299c Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Mon, 28 Jul 2025 15:49:16 +0100 Subject: [PATCH 01/10] added code to test the connectvity --- .../uk/gov/hmcts/cp/config/TestConfig.java | 15 +++ .../CourtScheduleControllerIT.java | 15 +++ .../CourtScheduleRepositoryImpl.java | 112 ++++++++++++++++++ .../cp/services/CourtScheduleService.java | 2 + .../CourtScheduleRepositoryImplTest.java | 53 +++++++++ src/test/resources/hearing.json | 104 ++++++++++++++++ 6 files changed, 301 insertions(+) create mode 100644 src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java create mode 100644 src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java create mode 100644 src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java create mode 100644 src/test/resources/hearing.json diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java new file mode 100644 index 0000000..987d647 --- /dev/null +++ b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java @@ -0,0 +1,15 @@ +package uk.gov.hmcts.cp.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; +import uk.gov.hmcts.cp.repositories.CourtScheduleRepositoryImpl; + +import java.net.http.HttpClient; + +import static org.mockito.Mockito.mock; + +@Configuration +public class TestConfig { + +} \ No newline at end of file diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java index cd106d1..4a11e10 100644 --- a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java @@ -7,11 +7,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; +import uk.gov.hmcts.cp.config.TestConfig; +import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; import java.util.UUID; @@ -24,12 +28,23 @@ @ExtendWith(SpringExtension.class) @SpringBootTest @AutoConfigureMockMvc +@Import(TestConfig.class) class CourtScheduleControllerIT { private static final Logger log = LoggerFactory.getLogger(CourtScheduleControllerIT.class); @Autowired private MockMvc mockMvc; + @Autowired + @Qualifier("inMemoryCourtScheduleRepositoryImpl") + private CourtScheduleRepository courtScheduleRepository; + + /*@BeforeEach + void setUp() { + inMemoryCaseUrnMapper.clearAllMappings(); + inMemoryCaseUrnMapper.saveCaseUrnMapping("test-case-urn", "test-case-id"); + } + */ @Test void shouldReturnOkWhenValidUrnIsProvided() throws Exception { String caseUrn = "test-case-urn"; diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java new file mode 100644 index 0000000..035dd14 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java @@ -0,0 +1,112 @@ +package uk.gov.hmcts.cp.repositories; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Primary; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.cp.openapi.model.CourtSchedule; +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; +import uk.gov.hmcts.cp.openapi.model.CourtSitting; +import uk.gov.hmcts.cp.openapi.model.Hearing; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Component +@Primary +public class CourtScheduleRepositoryImpl implements CourtScheduleRepository { + private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleRepositoryImpl.class); + + private final Map courtScheduleResponseMap = new ConcurrentHashMap<>(); + + + public void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse courtScheduleResponse) { + courtScheduleResponseMap.put(caseUrn, courtScheduleResponse); + } + + public CourtScheduleResponse getCourtScheduleByCaseId(final String caseUrn) { + if (!courtScheduleResponseMap.containsKey(caseUrn)) { + saveCourtSchedule(caseUrn, createCourtScheduleResponse()); + } + return courtScheduleResponseMap.get(caseUrn); + } + + public void clearAll() { + courtScheduleResponseMap.clear(); + } + + private CourtScheduleResponse createCourtScheduleResponse() { + + String res = getHearingData(); + LOG.info("infunction createCourtScheduleResponse Response Body: {} " + res); + + + final OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC) + .truncatedTo(ChronoUnit.SECONDS); + + final Hearing hearing = Hearing.builder() + .hearingId(UUID.randomUUID().toString()) + .listNote("Requires interpreter") + .hearingDescription("Sentencing for theft case") + .hearingType("Trial") + .courtSittings(List.of( + CourtSitting.builder() + .courtHouse("Central Criminal Court") + .sittingStart(sittingStartTime) + .sittingEnd(sittingStartTime.plusMinutes(60)) + .judiciaryId(UUID.randomUUID().toString()) + .build()) + ).build(); + + return CourtScheduleResponse.builder() + .courtSchedule(List.of( + CourtSchedule.builder() + .hearings(List.of(hearing) + ).build() + ) + ).build(); + } + + private String getHearingData(){ + HttpResponse response = null; + try { + // Create HttpClient instance + HttpClient client = HttpClient.newHttpClient(); + + // Build the request + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated?caseId=f552dee6-f092-415b-839c-5e5b5f46635e")) + .GET() + .header("Accept", "application/vnd.listing.search.hearings+json") + .header("CJSCPPUID", "d7c91866-646a-462c-9203-46678e8cddef") + .build(); + + // Send the request + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // Check response status + if (response.statusCode() != HttpStatus.OK.value()) { + LOG.error("Failed to fetch hearing data. HTTP Status: {}", response.statusCode()); + return null; + } + + // Print response status and body + LOG.info("Response Code: {} " + response.statusCode()); + LOG.info("Response Body: {} " + response.body()); + return response.body(); + } catch (Exception e) { + LOG.error("Exception occurred while fetching hearing data: {}", e.getMessage(), e); + } + return null; + } +} diff --git a/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java b/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java index 1a5d8c4..ad067fb 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java @@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; @@ -18,6 +19,7 @@ public class CourtScheduleService { private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleService.class); + @Qualifier("courtScheduleRepositoryImpl") private final CourtScheduleRepository courtScheduleRepository; public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) throws ResponseStatusException { diff --git a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java new file mode 100644 index 0000000..6bbf915 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java @@ -0,0 +1,53 @@ +package uk.gov.hmcts.cp.repositories; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +class CourtScheduleRepositoryImplTest { + + private CourtScheduleRepositoryImpl courtScheduleRepository; + + @BeforeEach + void setUp() { + courtScheduleRepository = new CourtScheduleRepositoryImpl(); + } + + @Test + void getCourtScheduleByCaseId_shouldReturnNewResponseIfNotExists() { + String caseUrn = "test-case-urn"; + + CourtScheduleResponse response = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); + + assertNotNull(response); + assertEquals(1, response.getCourtSchedule().size()); + } + + @Test + void getCourtScheduleByCaseId_shouldReturnExistingResponseIfExists() { + String caseUrn = "test-case-urn"; + CourtScheduleResponse expectedResponse = CourtScheduleResponse.builder().build(); + + courtScheduleRepository.saveCourtSchedule(caseUrn, expectedResponse); + CourtScheduleResponse actualResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); + + assertNotNull(actualResponse); + assertEquals(expectedResponse, actualResponse); + } + + @Test + void saveCourtSchedule_shouldStoreResponse() { + String caseUrn = "test-case-urn"; + CourtScheduleResponse response = CourtScheduleResponse.builder().build(); + + courtScheduleRepository.saveCourtSchedule(caseUrn, response); + CourtScheduleResponse storedResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); + + assertNotNull(storedResponse); + assertEquals(response, storedResponse); + } +} \ No newline at end of file diff --git a/src/test/resources/hearing.json b/src/test/resources/hearing.json new file mode 100644 index 0000000..312a3db --- /dev/null +++ b/src/test/resources/hearing.json @@ -0,0 +1,104 @@ +{ + "hearings": [ + { + "id": "348a288e-6e0d-479c-bd14-f363580d2181", + "type": { + "id": "4a0e892d-c0c5-3c51-95b8-704d8c781776", + "description": "First hearing" + }, + "endDate": "2025-07-21", + "allocated": true, + "judiciary": [], + "startDate": "2025-07-21", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDays": [ + { + "endTime": "2025-07-21T15:20:00.000Z", + "sequence": 0, + "startTime": "2025-07-21T15:00:00.000Z", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDate": "2025-07-21", + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "durationMinutes": 20 + } + ], + "listedCases": [ + { + "id": "f552dee6-f092-415b-839c-5e5b5f46635e", + "markers": [], + "defendants": [ + { + "id": "4e7853ab-67f8-4ebe-9a31-dc1ed271ebb9", + "address": { + "address1": "Add1", + "postcode": "CB3 0GU" + }, + "isYouth": false, + "lastName": "Test2", + "offences": [ + { + "id": "922cf1fd-9ef1-415d-809f-5a871ec24ec8", + "count": 0, + "startDate": "2025-07-10", + "orderIndex": 1, + "offenceCode": "TH68023A", + "shadowListed": false, + "offenceWording": "Before 10 Jul 2025 at df attempted to rob dfd of dfdf to the value of sds .", + "statementOfOffence": { + "title": "Attempt robbery", + "welshTitle": "Ymgais i ysbeilio (robbery)", + "legislation": "Contrary to section 1(1) of the Criminal Attempts Act 1981.", + "welshLegislation": "Yn groes i adran 1(1) Deddf Ymgeisiau i Droseddu 1981." + }, + "restrictFromCourtList": false + } + ], + "firstName": "Teat1", + "bailStatus": { + "id": "86009c70-759d-3308-8de4-194886ff9a77", + "code": "A", + "description": "Not applicable" + }, + "dateOfBirth": "1984-01-12", + "masterDefendantId": "4e7853ab-67f8-4ebe-9a31-dc1ed271ebb9", + "hearingLanguageNeeds": "ENGLISH", + "restrictFromCourtList": false, + "nationalityDescription": "British", + "courtProceedingsInitiated": "2025-07-21T13:19:54.727Z" + } + ], + "shadowListed": false, + "caseIdentifier": { + "authorityId": "31af405e-7b60-4dd8-a244-c24c2d3fa595", + "authorityCode": "TFL", + "caseReference": "CIK2JQKECS" + }, + "restrictFromCourtList": false + } + ], + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "isSlotsBooked": false, + "nonDefaultDays": [ + { + "roomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "duration": 20, + "startTime": "2025-07-21T15:00:00.000Z", + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26" + } + ], + "nonSittingDays": [], + "hearingLanguage": "ENGLISH", + "estimatedMinutes": 20, + "jurisdictionType": "MAGISTRATES", + "courtApplications": [], + "courtCentreDetails": { + "id": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "defaultDuration": 420, + "defaultStartTime": "10:00:00" + }, + "isGroupProceedings": false, + "numberOfGroupCases": 1, + "sendNotificationToParties": false + } + ] +} \ No newline at end of file From 8cb8a73dd1447448c0dad28fc942d67c9c64c143 Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Thu, 7 Aug 2025 15:25:54 +0100 Subject: [PATCH 02/10] Replace the url with actual url and implemented other functionlity --- .env | 7 +- .github/workflows/ci-build-publish.yml | 23 ++- Dockerfile | 10 +- deploy.sh | 20 +++ docker-compose.yml | 8 +- .../uk/gov/hmcts/cp/config/TestConfig.java | 37 +++- .../CourtScheduleControllerIT.java | 23 ++- .../cp/repositories/CourtScheduleClient.java | 8 + .../repositories/CourtScheduleClientImpl.java | 164 ++++++++++++++++++ .../repositories/CourtScheduleRepository.java | 13 -- .../CourtScheduleRepositoryImpl.java | 112 ------------ ...a => InMemoryCourtScheduleClientImpl.java} | 29 +--- .../cp/services/CaseUrnMapperService.java | 57 +++--- .../cp/services/CourtScheduleService.java | 8 +- .../java/uk/gov/hmcts/cp/utils/Utils.java | 58 +++++++ src/main/resources/application.yaml | 8 +- .../CourtScheduleProviderPactTest.java | 8 +- .../CourtScheduleControllerTest.java | 23 ++- .../CourtScheduleClientImplTest.java | 91 ++++++++++ ...Test.java => CourtScheduleClientTest.java} | 9 +- .../CourtScheduleRepositoryImplTest.java | 53 ------ .../cp/services/CaseUrnMapperServiceTest.java | 86 +++++++++ .../cp/services/CourtScheduleServiceTest.java | 15 +- src/test/resources/hearingJudiciary.json | 115 ++++++++++++ 24 files changed, 704 insertions(+), 281 deletions(-) create mode 100644 deploy.sh create mode 100644 src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClient.java create mode 100644 src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java delete mode 100644 src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepository.java delete mode 100644 src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java rename src/main/java/uk/gov/hmcts/cp/repositories/{InMemoryCourtScheduleRepositoryImpl.java => InMemoryCourtScheduleClientImpl.java} (66%) create mode 100644 src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImplTest.java rename src/test/java/uk/gov/hmcts/cp/repositories/{CourtScheduleRepositoryTest.java => CourtScheduleClientTest.java} (85%) delete mode 100644 src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java create mode 100644 src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java create mode 100644 src/test/resources/hearingJudiciary.json diff --git a/.env b/.env index f2e9d83..07089a4 100644 --- a/.env +++ b/.env @@ -1,4 +1,7 @@ SERVER_PORT=4550 BASE_IMAGE=openjdk:21-jdk-slim -JAR_FILENAME=service-cp-crime-schedulingandlisting-courtschedule-*.jar -JAR_FILE_PATH=build/libs \ No newline at end of file +JAR_FILENAME=service-cp-crime-scheduleandlist-courtschedule-*.jar +JAR_FILE_PATH=build/libs +CASE_MAPPER_SERVICE_URL=https://steccm64.ingress01.dev.nl.cjscp.org.uk/system-id-mapper-api/rest/systemid/mappings +COURT_SCHEDULE_CLIENT_URL=https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated +CJSCPPUID=d7c91866-646a-462c-9203-46678e8cddef \ No newline at end of file diff --git a/.github/workflows/ci-build-publish.yml b/.github/workflows/ci-build-publish.yml index 102efb2..eea258d 100644 --- a/.github/workflows/ci-build-publish.yml +++ b/.github/workflows/ci-build-publish.yml @@ -79,9 +79,24 @@ jobs: - name: Gradle Build env: ARTEFACT_VERSION: ${{ needs.Artefact-Version.outputs.artefact_version }} + CASE_MAPPER_SERVICE_URL: ${{ vars.CASE_MAPPER_SERVICE_URL }} + COURT_SCHEDULE_CLIENT_URL: ${{ vars.COURT_SCHEDULE_CLIENT_URL }} + CJSCPPUID: ${{ vars.CJSCPPUID }} run: | echo "Building with ARTEFACT_VERSION=$ARTEFACT_VERSION" gradle build -DARTEFACT_VERSION=$ARTEFACT_VERSION + + if [ -z "$CASE_MAPPER_SERVICE_URL" ]; then + echo "::warning::CASE_MAPPER_SERVICE_URL is null or not set" + fi + + if [ -z "$COURT_SCHEDULE_CLIENT_URL" ]; then + echo "::warning::COURT_SCHEDULE_CLIENT_URL is null or not set" + fi + + if [ -z "$CJSCPPUID" ]; then + echo "::warning::CJSCPPUID is null or not set" + fi - name: Extract repo name id: repo_vars @@ -173,7 +188,10 @@ jobs: -DGITHUB_ACTOR=${{ github.actor }} \ -DGITHUB_TOKEN=$GITHUB_TOKEN \ -DAZURE_DEVOPS_ARTIFACT_USERNAME=$AZURE_DEVOPS_ARTIFACT_USERNAME \ - -DAZURE_DEVOPS_ARTIFACT_TOKEN=$AZURE_DEVOPS_ARTIFACT_TOKEN + -DAZURE_DEVOPS_ARTIFACT_TOKEN=$AZURE_DEVOPS_ARTIFACT_TOKEN \ + -DCASE_MAPPER_SERVICE_URL=$CASE_MAPPER_SERVICE_URL \ + -DCOURT_SCHEDULE_CLIENT_URL=$COURT_SCHEDULE_CLIENT_URL \ + -DCJSCPPUID=$CJSCPPUID Build-Docker: needs: [ Provider-Deploy, Build, Artefact-Version ] @@ -210,6 +228,9 @@ jobs: build-args: | BASE_IMAGE=openjdk:21-jdk-slim JAR_FILENAME=${{ needs.Build.outputs.artefact_name }}.jar + CASE_MAPPER_SERVICE_URL=${{ vars.CASE_MAPPER_SERVICE_URL }} + COURT_SCHEDULE_CLIENT_URL=${{ vars.COURT_SCHEDULE_CLIENT_URL }} + CJSCPPUID=${{ vars.CJSCPPUID }} Deploy: needs: [ Provider-Deploy, Build, Artefact-Version ] diff --git a/Dockerfile b/Dockerfile index 590b83a..a4e1b66 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,11 +5,19 @@ FROM ${BASE_IMAGE:-openjdk:21-jdk-slim} # ---- Runtime arguments ---- ARG JAR_FILENAME ARG JAR_FILE_PATH +ARG CASE_MAPPER_SERVICE_URL +ARG COURT_SCHEDULE_CLIENT_URL +ARG CJSCPPUID ENV JAR_FILENAME=${JAR_FILENAME:-app.jar} ENV JAR_FILE_PATH=${JAR_FILE_PATH:-build/libs} ENV JAR_FULL_PATH=$JAR_FILE_PATH/$JAR_FILENAME +ENV CASE_MAPPER_SERVICE_URL=$CASE_MAPPER_SERVICE_URL +ENV COURT_SCHEDULE_CLIENT_URL=$COURT_SCHEDULE_CLIENT_URL +ENV CJSCPPUID=$CJSCPPUID + + # ---- Set runtime ENV for Spring Boot to bind port ARG SERVER_PORT ENV SERVER_PORT=${SERVER_PORT:-4550} @@ -29,4 +37,4 @@ RUN chmod 755 /opt/app/app.jar # ---- Runtime ---- EXPOSE 4550 -CMD ["java", "-jar", "/opt/app/app.jar"] \ No newline at end of file +CMD ["java", "-Dcom.sun.net.ssl.checkRevocation=false", "-jar", "/opt/app/app.jar"] \ No newline at end of file diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..430a30b --- /dev/null +++ b/deploy.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Define the service name +SERVICE_NAME="service-cp-crime-scheduleandlist-courtschedule" + +# Check if the Docker container is running +if [ "$(docker ps -q -f name=${SERVICE_NAME})" ]; then + echo "Stopping the running Docker container..." + docker-compose down +fi + +# Rebuild the Docker image +echo "Rebuilding the Docker image..." +docker-compose build + +# Deploy the service +echo "Starting the Docker container..." +docker-compose up -d + +echo "Deployment completed successfully." diff --git a/docker-compose.yml b/docker-compose.yml index fed3722..bdf8ef3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3.8' services: - service-cp-crime-schedulingandlisting-courtschedule: + service-cp-crime-scheduleandlist-courtschedule: env_file: - .env build: @@ -15,6 +15,10 @@ services: SERVER_PORT: ${SERVER_PORT} JAR_FILENAME: ${JAR_FILENAME} JAR_FILE_PATH: ${JAR_FILE_PATH} + CASE_MAPPER_SERVICE_URL: ${CASE_MAPPER_SERVICE_URL} + COURT_SCHEDULE_CLIENT_URL: ${COURT_SCHEDULE_CLIENT_URL} + CJSCPPUID: ${CJSCPPUID} + environment: - SERVER_PORT=${SERVER_PORT:-4550} ports: @@ -30,4 +34,4 @@ services: networks: service-network: - name: service-cp-crime-schedulingandlisting-courtschedule-network \ No newline at end of file + name: service-cp-crime-scheduleandlist-courtschedule-network \ No newline at end of file diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java index 987d647..4c8fdd6 100644 --- a/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java +++ b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java @@ -1,15 +1,42 @@ package uk.gov.hmcts.cp.config; +import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; -import uk.gov.hmcts.cp.repositories.CourtScheduleRepositoryImpl; +import org.springframework.web.client.RestTemplate; +import uk.gov.hmcts.cp.controllers.CourtScheduleController; +import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleClientImpl; +import uk.gov.hmcts.cp.services.CaseUrnMapperService; +import uk.gov.hmcts.cp.services.CourtScheduleService; -import java.net.http.HttpClient; - -import static org.mockito.Mockito.mock; +import java.util.UUID; @Configuration public class TestConfig { + @Bean("courtScheduleService") + public CourtScheduleService courtScheduleService() { + return new CourtScheduleService(new InMemoryCourtScheduleClientImpl()); + } + + @Bean("testCaseUrnMapperService") + public CaseUrnMapperService testCaseUrnMapperService() { + RestTemplate restTemplate = new RestTemplate(); + ObjectMapper objectMapper = new ObjectMapper(); + return new CaseUrnMapperService(restTemplate, objectMapper) { + @Override + public String getCaseMapperServiceUrl() { + return "http://mock-server/test-mapper"; + } + public String getCaseId(final String caseUrn) { + return UUID.randomUUID().toString(); + } + }; + } + @Bean("courtScheduleController") + public CourtScheduleController courtScheduleController( + CourtScheduleService courtScheduleService, + CaseUrnMapperService testCaseUrnMapperService) { + return new CourtScheduleController(courtScheduleService, testCaseUrnMapperService); + } } \ No newline at end of file diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java index 4a11e10..2bc9e74 100644 --- a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java @@ -15,7 +15,8 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import uk.gov.hmcts.cp.config.TestConfig; -import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; +import uk.gov.hmcts.cp.repositories.CourtScheduleClient; +import uk.gov.hmcts.cp.services.CaseUrnMapperService; import java.util.UUID; @@ -36,15 +37,21 @@ class CourtScheduleControllerIT { private MockMvc mockMvc; @Autowired - @Qualifier("inMemoryCourtScheduleRepositoryImpl") - private CourtScheduleRepository courtScheduleRepository; + @Qualifier("inMemoryCourtScheduleClientImpl") + private CourtScheduleClient courtScheduleClient; - /*@BeforeEach - void setUp() { - inMemoryCaseUrnMapper.clearAllMappings(); - inMemoryCaseUrnMapper.saveCaseUrnMapping("test-case-urn", "test-case-id"); + @Autowired + @Qualifier("testCaseUrnMapperService") + private CaseUrnMapperService caseUrnMapperService; + + @Test + void shouldReturnOkWhenValidUrnIsProvided1() throws Exception { + String caseUrn = "test-case-urn"; + mockMvc.perform(get("/case/{case_urn}/courtschedule", caseUrn) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); } - */ + @Test void shouldReturnOkWhenValidUrnIsProvided() throws Exception { String caseUrn = "test-case-urn"; diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClient.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClient.java new file mode 100644 index 0000000..8ab2191 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClient.java @@ -0,0 +1,8 @@ +package uk.gov.hmcts.cp.repositories; + +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; + + +public interface CourtScheduleClient { + CourtScheduleResponse getCourtScheduleByCaseId(String caseId); +} diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java new file mode 100644 index 0000000..2e098da --- /dev/null +++ b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java @@ -0,0 +1,164 @@ +package uk.gov.hmcts.cp.repositories; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.util.UriComponentsBuilder; +import uk.gov.hmcts.cp.openapi.model.CourtSchedule; +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; +import uk.gov.hmcts.cp.openapi.model.CourtSitting; +import uk.gov.hmcts.cp.openapi.model.Hearing; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; + +import static uk.gov.hmcts.cp.utils.Utils.getHttpClient; + +@Component +@Primary +@RequiredArgsConstructor +public class CourtScheduleClientImpl implements CourtScheduleClient { + private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleClientImpl.class); + private final HttpClient httpClient; + + @Value("${service.court-schedule-client.url}") + private String courtScheduleClientUrl; + + @Value("${service.court-schedule-client.cjscppuid}") + private String cjscppuid; + + public CourtScheduleClientImpl() throws NoSuchAlgorithmException, KeyManagementException { + this.httpClient = getHttpClient(); + } + + public CourtScheduleClientImpl(HttpClient httpClient, + @Value("${service.court-schedule-client.url}") String courtScheduleClientUrl, + @Value("${service.court-schedule-client.cjscppuid}") String cjscppuid) { + this.httpClient = httpClient; + this.courtScheduleClientUrl = courtScheduleClientUrl; + this.cjscppuid = cjscppuid; + } + + public String getCourtScheduleClientUrl() { + return this.courtScheduleClientUrl; + } + + public String getCjscppuid() { + return this.cjscppuid; + } + + public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) { + List hearingList = getHearings(caseId); + LOG.info("infunction createCourtScheduleResponse Response Body: {} " + hearingList); + + return CourtScheduleResponse.builder() + .courtSchedule(List.of( + CourtSchedule.builder() + .hearings(hearingList) + .build() + ) + ).build(); + } + + private List getHearings(String caseId){ + HttpResponse response = null; + try { + //ignoreCertificates(); + HttpRequest request = HttpRequest.newBuilder() + //.uri(new URI("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated?caseId=f552dee6-f092-415b-839c-5e5b5f46635e")) + .uri(new URI(buildUrl(caseId))) + .GET() + .header("Accept", "application/vnd.listing.search.hearings+json") + //.header("CJSCPPUID", "d7c91866-646a-462c-9203-46678e8cddef") + .header("CJSCPPUID", getCjscppuid()) + .build(); + + // Send the request + response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + + // Check response status + if (response.statusCode() != HttpStatus.OK.value()) { + LOG.error("Failed to fetch hearing data. HTTP Status: {}", response.statusCode()); + return null; + } + + List hearingResult = getHearingData(response.body()); + LOG.info("Response Code: {}, Response Body: {}", response.statusCode(), response.body()); + return hearingResult; + } catch (Exception e) { + LOG.error("Exception occurred while fetching hearing data: {}", e.getMessage(), e); + } + return null; + } + + private String buildUrl(String caseId) { + return UriComponentsBuilder + //.fromUri(URI.create("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated")) + .fromUri(URI.create(getCourtScheduleClientUrl())) + .queryParam("caseId", caseId) + .toUriString(); + } + + private List getHearingData(String body) throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.readTree(body); + + List hearings = new ArrayList<>(); + + for (JsonNode hearingNode : root.path("hearings")) { + String hearingId = hearingNode.path("id").asText(); + JsonNode typeNode = hearingNode.path("type"); + String typeDescription = typeNode.path("description").asText(); + + String judiciaryId = getJudiciaryIdString(hearingNode); + Hearing hearing = new Hearing(); + hearing.setHearingId(hearingId); + hearing.setHearingType(typeDescription); + hearing.setHearingDescription(typeDescription); + hearing.setListNote("sample list note"); + + List courtSittings = getCourtSittings(hearingNode, judiciaryId); + hearing.setCourtSittings(courtSittings); + hearings.add(hearing); + } + return hearings ; + } + + private static String getJudiciaryIdString(JsonNode hearingNode) { + StringBuilder sb = new StringBuilder(); + hearingNode.path("judiciary").forEach(jd -> { + sb.append(jd.path("judicialId").asText()); + sb.append(","); + }); + return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : sb.toString(); + } + + private List getCourtSittings(JsonNode hearingNode, String judiciaryId) { + List courtSittings = new ArrayList<>(); + for (JsonNode hearingDay : hearingNode.path("hearingDays")) { + CourtSitting cs = new CourtSitting(); + cs.setSittingStart(OffsetDateTime.parse(hearingDay.path("startTime").asText())); + cs.setSittingEnd(OffsetDateTime.parse(hearingDay.path("endTime").asText())); + cs.setJudiciaryId(judiciaryId); + + cs.setCourtHouse(hearingDay.path("courtCentreId").asText()); + courtSittings.add(cs); + } + return courtSittings; + } + +} diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepository.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepository.java deleted file mode 100644 index 38f6e73..0000000 --- a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package uk.gov.hmcts.cp.repositories; - -import org.springframework.stereotype.Repository; -import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; - -@Repository -public interface CourtScheduleRepository { - - CourtScheduleResponse getCourtScheduleByCaseId(String caseUrn); - void saveCourtSchedule(String caseUrn, CourtScheduleResponse courtScheduleResponse); - void clearAll(); - -} diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java deleted file mode 100644 index 035dd14..0000000 --- a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -package uk.gov.hmcts.cp.repositories; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Primary; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Component; -import uk.gov.hmcts.cp.openapi.model.CourtSchedule; -import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; -import uk.gov.hmcts.cp.openapi.model.CourtSitting; -import uk.gov.hmcts.cp.openapi.model.Hearing; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -@Component -@Primary -public class CourtScheduleRepositoryImpl implements CourtScheduleRepository { - private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleRepositoryImpl.class); - - private final Map courtScheduleResponseMap = new ConcurrentHashMap<>(); - - - public void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse courtScheduleResponse) { - courtScheduleResponseMap.put(caseUrn, courtScheduleResponse); - } - - public CourtScheduleResponse getCourtScheduleByCaseId(final String caseUrn) { - if (!courtScheduleResponseMap.containsKey(caseUrn)) { - saveCourtSchedule(caseUrn, createCourtScheduleResponse()); - } - return courtScheduleResponseMap.get(caseUrn); - } - - public void clearAll() { - courtScheduleResponseMap.clear(); - } - - private CourtScheduleResponse createCourtScheduleResponse() { - - String res = getHearingData(); - LOG.info("infunction createCourtScheduleResponse Response Body: {} " + res); - - - final OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC) - .truncatedTo(ChronoUnit.SECONDS); - - final Hearing hearing = Hearing.builder() - .hearingId(UUID.randomUUID().toString()) - .listNote("Requires interpreter") - .hearingDescription("Sentencing for theft case") - .hearingType("Trial") - .courtSittings(List.of( - CourtSitting.builder() - .courtHouse("Central Criminal Court") - .sittingStart(sittingStartTime) - .sittingEnd(sittingStartTime.plusMinutes(60)) - .judiciaryId(UUID.randomUUID().toString()) - .build()) - ).build(); - - return CourtScheduleResponse.builder() - .courtSchedule(List.of( - CourtSchedule.builder() - .hearings(List.of(hearing) - ).build() - ) - ).build(); - } - - private String getHearingData(){ - HttpResponse response = null; - try { - // Create HttpClient instance - HttpClient client = HttpClient.newHttpClient(); - - // Build the request - HttpRequest request = HttpRequest.newBuilder() - .uri(new URI("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated?caseId=f552dee6-f092-415b-839c-5e5b5f46635e")) - .GET() - .header("Accept", "application/vnd.listing.search.hearings+json") - .header("CJSCPPUID", "d7c91866-646a-462c-9203-46678e8cddef") - .build(); - - // Send the request - response = client.send(request, HttpResponse.BodyHandlers.ofString()); - - // Check response status - if (response.statusCode() != HttpStatus.OK.value()) { - LOG.error("Failed to fetch hearing data. HTTP Status: {}", response.statusCode()); - return null; - } - - // Print response status and body - LOG.info("Response Code: {} " + response.statusCode()); - LOG.info("Response Body: {} " + response.body()); - return response.body(); - } catch (Exception e) { - LOG.error("Exception occurred while fetching hearing data: {}", e.getMessage(), e); - } - return null; - } -} diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleRepositoryImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java similarity index 66% rename from src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleRepositoryImpl.java rename to src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java index ea8ca66..f618dc9 100644 --- a/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleRepositoryImpl.java +++ b/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java @@ -1,40 +1,21 @@ package uk.gov.hmcts.cp.repositories; import org.springframework.stereotype.Component; -import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; import uk.gov.hmcts.cp.openapi.model.CourtSchedule; -import uk.gov.hmcts.cp.openapi.model.Hearing; +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; import uk.gov.hmcts.cp.openapi.model.CourtSitting; +import uk.gov.hmcts.cp.openapi.model.Hearing; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; import java.util.List; -import java.util.Map; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -@Component -public class InMemoryCourtScheduleRepositoryImpl implements CourtScheduleRepository { - - private final Map courtScheduleResponseMap = new ConcurrentHashMap<>(); - public void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse courtScheduleResponse) { - courtScheduleResponseMap.put(caseUrn, courtScheduleResponse); - } - - public CourtScheduleResponse getCourtScheduleByCaseId(final String caseUrn) { - if (!courtScheduleResponseMap.containsKey(caseUrn)) { - saveCourtSchedule(caseUrn, createCourtScheduleResponse()); - } - return courtScheduleResponseMap.get(caseUrn); - } - - public void clearAll() { - courtScheduleResponseMap.clear(); - } +@Component("inMemoryCourtScheduleClientImpl") +public class InMemoryCourtScheduleClientImpl implements CourtScheduleClient { - private CourtScheduleResponse createCourtScheduleResponse() { + public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) { final OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC) .truncatedTo(ChronoUnit.SECONDS); diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index 7f81034..c0078fd 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -1,60 +1,67 @@ package uk.gov.hmcts.cp.services; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; +import org.apache.logging.log4j.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; @Service @RequiredArgsConstructor public class CaseUrnMapperService { - private static final Logger LOG = LoggerFactory.getLogger(CaseUrnMapperService.class); - private final RestTemplate restTemplate; + private final ObjectMapper objectMapper; @Value("${service.case-mapper-service.url}") private String caseMapperServiceUrl; - private static final String CASEURN_ID = "caseurn/{caseurn}"; - - private final Map caseUrnToCaseIdMap = new ConcurrentHashMap<>(); - - - public String getCaseId(final String caseUrn) { - return UUID.randomUUID().toString(); - // This below code is commented out as it is will be used when the case mapper service is available. + return "f552dee6-f092-415b-839c-5e5b5f46635e"; +// try { +// ignoreCertificates(); +// ResponseEntity responseEntity = restTemplate.exchange( +// getCaseIdUrl(caseUrn), +// HttpMethod.GET, +// getRequestEntity(), +// String.class +// ); +// return getCaseId(responseEntity); +// } catch (Exception e) { +// LOG.atError().log("Error while getting case id from case urn", e); +// } +// return null; + } + + public String getCaseMapperServiceUrl() { + return this.caseMapperServiceUrl; + } -/* try { - ResponseEntity responseEntity = restTemplate.exchange( - getCaseIdUrl(caseUrn), - HttpMethod.GET, - getRequestEntity(), - String.class - ); - return responseEntity.hasBody() ? responseEntity.getBody(): Strings.EMPTY; - } catch (Exception e) { - LOG.atError().log("Error while getting case id from case urn", e); + public String getCaseId(ResponseEntity responseEntity) throws JsonProcessingException { + if (responseEntity != null || !responseEntity.hasBody()) { + JsonNode root = objectMapper.readTree(responseEntity.getBody()); + return root.get("caseId").asText(); } - return null;*/ + return Strings.EMPTY; } private String getCaseIdUrl(String caseUrn) { + LOG.atDebug().log("Fetching case id for case urn: {}", caseUrn); return UriComponentsBuilder - .fromUri(URI.create(caseMapperServiceUrl)) + .fromUri(URI.create(getCaseMapperServiceUrl())) .pathSegment(caseUrn) .buildAndExpand(caseUrn) .toUriString(); diff --git a/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java b/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java index ad067fb..dd5cfc5 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java @@ -4,12 +4,11 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; -import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; +import uk.gov.hmcts.cp.repositories.CourtScheduleClient; import static uk.gov.hmcts.cp.utils.Utils.sanitizeString; @@ -19,8 +18,7 @@ public class CourtScheduleService { private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleService.class); - @Qualifier("courtScheduleRepositoryImpl") - private final CourtScheduleRepository courtScheduleRepository; + private final CourtScheduleClient courtScheduleClient; public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) throws ResponseStatusException { if (StringUtils.isEmpty(caseId)) { @@ -28,7 +26,7 @@ public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) throw throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "caseId is required"); } LOG.atWarn().log("NOTE: System configured to return stubbed Court Schedule details. Ignoring provided caseId : {}", sanitizeString(caseId)); - final CourtScheduleResponse stubbedCourtScheduleResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseId); + final CourtScheduleResponse stubbedCourtScheduleResponse = courtScheduleClient.getCourtScheduleByCaseId(caseId); LOG.atDebug().log("Court Schedule response: {}", stubbedCourtScheduleResponse); return stubbedCourtScheduleResponse; } diff --git a/src/main/java/uk/gov/hmcts/cp/utils/Utils.java b/src/main/java/uk/gov/hmcts/cp/utils/Utils.java index 0710f53..5d72a00 100644 --- a/src/main/java/uk/gov/hmcts/cp/utils/Utils.java +++ b/src/main/java/uk/gov/hmcts/cp/utils/Utils.java @@ -1,10 +1,23 @@ package uk.gov.hmcts.cp.utils; import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.net.http.HttpClient; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; + public class Utils { + private static final Logger log = LoggerFactory.getLogger(Utils.class); public static String sanitizeString(final String urn) { if (urn == null) { @@ -13,4 +26,49 @@ public static String sanitizeString(final String urn) { return StringEscapeUtils.escapeHtml4(urn); } + public static void ignoreCertificates() { + TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + }}; + + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } catch (Exception e) { + log.error("Error while ignoring SSL certificate", e); + } + } + + public static HttpClient getHttpClient() throws NoSuchAlgorithmException, KeyManagementException { + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + public void checkClientTrusted(X509Certificate[] chain, String authType) {} + public void checkServerTrusted(X509Certificate[] chain, String authType) {} + public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } + } + }; + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new SecureRandom()); + + + HttpClient httpClient = HttpClient.newBuilder() + .sslContext(sslContext) + .version(HttpClient.Version.HTTP_2) + .build(); + return httpClient; + } + } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 42f4723..4555271 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -23,7 +23,7 @@ spring: config: import: "optional:configtree:/mnt/secrets/rpe/" application: - name: service-cp-crime-schedulingandlisting-courtschedule + name: service-cp-crime-scheduleandlist-courtschedule # azure: # cosmos: # endpoint: ${COSMOSDB_ENDPOINT} @@ -32,7 +32,11 @@ spring: service: case-mapper-service: - url: https://virtserver.swaggerhub.com/HMCTS-DTS/api-cp-refdata-case-mapper + url: ${CASE_MAPPER_SERVICE_URL:https://devcp01.ingress01.dev.nl.cjscp.org.uk/caseurnmapper} + + court-schedule-client: + url: ${COURT_SCHEDULE_CLIENT_URL:https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated} + cjscppuid: ${CJSCPPUID:d7c91866-646a-462c-9203-46678e8cddef} azure: application-insights: diff --git a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java index 0c3d5ed..42cb9d5 100644 --- a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java +++ b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java @@ -19,7 +19,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; import uk.gov.hmcts.cp.pact.helper.JsonFileToObject; -import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; +import uk.gov.hmcts.cp.repositories.CourtScheduleClient; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ExtendWith({SpringExtension.class, PactVerificationInvocationContextProvider.class}) @@ -34,7 +34,7 @@ public class CourtScheduleProviderPactTest { private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleProviderPactTest.class); @Autowired - private CourtScheduleRepository courtScheduleRepository; + private CourtScheduleClient courtScheduleClient; @LocalServerPort private int port; @@ -48,9 +48,9 @@ void setupTarget(PactVerificationContext context) { @State("court schedule for case 456789 exists") public void setupCourtSchedule() throws Exception{ - courtScheduleRepository.clearAll(); + courtScheduleClient.clearAll(); CourtScheduleResponse courtScheduleResponse = JsonFileToObject.readJsonFromResources("courtSchedule.json", CourtScheduleResponse.class); - courtScheduleRepository.saveCourtSchedule("456789", courtScheduleResponse); + courtScheduleClient.saveCourtSchedule("456789", courtScheduleResponse); } @TestTemplate diff --git a/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java b/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java index fb61fad..19c2c76 100644 --- a/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java +++ b/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java @@ -1,5 +1,6 @@ package uk.gov.hmcts.cp.controllers; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -10,10 +11,9 @@ import org.springframework.web.server.ResponseStatusException; import uk.gov.hmcts.cp.openapi.model.CourtSchedule; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; - import uk.gov.hmcts.cp.openapi.model.CourtSitting; import uk.gov.hmcts.cp.openapi.model.Hearing; -import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleRepositoryImpl; +import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleClientImpl; import uk.gov.hmcts.cp.services.CaseUrnMapperService; import uk.gov.hmcts.cp.services.CourtScheduleService; @@ -33,9 +33,18 @@ class CourtScheduleControllerTest { @BeforeEach void setUp() { - CourtScheduleService courtScheduleService = new CourtScheduleService(new InMemoryCourtScheduleRepositoryImpl()); - CaseUrnMapperService caseUrnMapperService = new CaseUrnMapperService(new RestTemplate()); - courtScheduleController = new CourtScheduleController(courtScheduleService, caseUrnMapperService); + CourtScheduleService courtScheduleService = new CourtScheduleService(new InMemoryCourtScheduleClientImpl()); + CaseUrnMapperService testCaseUrnMapperService = new CaseUrnMapperService(new RestTemplate(), new ObjectMapper()) { + @Override + public String getCaseMapperServiceUrl() { + return "http://mock-server/test-mapper"; + } + + public String getCaseId(final String caseUrn) { + return UUID.randomUUID().toString(); + } + }; + courtScheduleController = new CourtScheduleController(courtScheduleService, testCaseUrnMapperService); } @Test @@ -70,7 +79,6 @@ void getJudgeById_ShouldReturnJudgesWithOkStatus() { assertNotNull(courtSitting.getSittingStart()); assertTrue(courtSitting.getSittingEnd().isAfter(courtSitting.getSittingStart())); assertNotNull(courtSitting.getJudiciaryId()); - } @Test @@ -93,5 +101,4 @@ void getJudgeById_ShouldReturnBadRequestStatus() { assertThat(exception.getReason()).isEqualTo("caseUrn is required"); assertThat(exception.getMessage()).isEqualTo("400 BAD_REQUEST \"caseUrn is required\""); } - -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImplTest.java b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImplTest.java new file mode 100644 index 0000000..de1e049 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImplTest.java @@ -0,0 +1,91 @@ +package uk.gov.hmcts.cp.repositories; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatchers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; +import uk.gov.hmcts.cp.openapi.model.Hearing; + +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + + +class CourtScheduleClientImplTest { + + @Mock + private HttpClient mockHttpClient; + + @Mock + private HttpResponse mockResponse; + + private CourtScheduleClientImpl client; + + private static final String MOCK_JSON = """ + { + "hearings": [ + { + "id": "hearing-1", + "type": { "description": "First hearing" }, + "judiciary": [{ "judicialId": "judge-1" }], + "hearingDays": [ + { + "startTime": "2025-07-21T15:00:00Z", + "endTime": "2025-07-21T15:20:00Z", + "courtCentreId": "court-1" + } + ] + } + ] + } + """; + private final String mockUrl = "http://mock-server/mapper"; + private final String cjscppuid = "mock-cjscppuid"; + + @BeforeEach + void setUp() throws Exception { + MockitoAnnotations.openMocks(this); + when(mockHttpClient.send( + any(HttpRequest.class), + ArgumentMatchers.>any() + )).thenReturn(mockResponse); + + client = new CourtScheduleClientImpl(mockHttpClient, mockUrl, cjscppuid) {; + @Override + public String getCourtScheduleClientUrl() { + return mockUrl; + } + + @Override + public String getCjscppuid() { + return cjscppuid; + } + }; + + } + + @Test + void getCourtScheduleByCaseId_shouldReturnValidResponse() throws Exception { + when(mockResponse.statusCode()).thenReturn(200); + when(mockResponse.body()).thenReturn(MOCK_JSON); + + CourtScheduleResponse response = client.getCourtScheduleByCaseId("some-case-id"); + + assertNotNull(response); + assertEquals(1, response.getCourtSchedule().size()); + + Hearing hearing = response.getCourtSchedule().get(0).getHearings().get(0); + assertEquals("hearing-1", hearing.getHearingId()); + assertEquals("First hearing", hearing.getHearingType()); + assertEquals(1, hearing.getCourtSittings().size()); + assertEquals("judge-1", hearing.getCourtSittings().get(0).getJudiciaryId()); + assertEquals("court-1", hearing.getCourtSittings().get(0).getCourtHouse()); + } +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryTest.java b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientTest.java similarity index 85% rename from src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryTest.java rename to src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientTest.java index b470264..a6b0193 100644 --- a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryTest.java +++ b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientTest.java @@ -13,19 +13,19 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -class CourtScheduleRepositoryTest { +class CourtScheduleClientTest { - private CourtScheduleRepository courtScheduleRepository; + private CourtScheduleClient courtScheduleClient; @BeforeEach void setUp() { - courtScheduleRepository = new InMemoryCourtScheduleRepositoryImpl(); + courtScheduleClient = new InMemoryCourtScheduleClientImpl(); } @Test void getCourtScheduleByCaseUrn_shouldReturnCourtScheduleResponse() { UUID caseUrn = UUID.randomUUID(); - CourtScheduleResponse response = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn.toString()); + CourtScheduleResponse response = courtScheduleClient.getCourtScheduleByCaseId(caseUrn.toString()); assertNotNull(response.getCourtSchedule()); assertEquals(1, response.getCourtSchedule().size()); @@ -49,5 +49,4 @@ void getCourtScheduleByCaseUrn_shouldReturnCourtScheduleResponse() { assertTrue(sitting.getSittingEnd().isAfter(sitting.getSittingStart())); assertNotNull(sitting.getJudiciaryId()); } - } \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java deleted file mode 100644 index 6bbf915..0000000 --- a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package uk.gov.hmcts.cp.repositories; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - - -class CourtScheduleRepositoryImplTest { - - private CourtScheduleRepositoryImpl courtScheduleRepository; - - @BeforeEach - void setUp() { - courtScheduleRepository = new CourtScheduleRepositoryImpl(); - } - - @Test - void getCourtScheduleByCaseId_shouldReturnNewResponseIfNotExists() { - String caseUrn = "test-case-urn"; - - CourtScheduleResponse response = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); - - assertNotNull(response); - assertEquals(1, response.getCourtSchedule().size()); - } - - @Test - void getCourtScheduleByCaseId_shouldReturnExistingResponseIfExists() { - String caseUrn = "test-case-urn"; - CourtScheduleResponse expectedResponse = CourtScheduleResponse.builder().build(); - - courtScheduleRepository.saveCourtSchedule(caseUrn, expectedResponse); - CourtScheduleResponse actualResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); - - assertNotNull(actualResponse); - assertEquals(expectedResponse, actualResponse); - } - - @Test - void saveCourtSchedule_shouldStoreResponse() { - String caseUrn = "test-case-urn"; - CourtScheduleResponse response = CourtScheduleResponse.builder().build(); - - courtScheduleRepository.saveCourtSchedule(caseUrn, response); - CourtScheduleResponse storedResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); - - assertNotNull(storedResponse); - assertEquals(response, storedResponse); - } -} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java new file mode 100644 index 0000000..d0854b6 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java @@ -0,0 +1,86 @@ +package uk.gov.hmcts.cp.services; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +class CaseUrnMapperServiceTest { + private CaseUrnMapperService caseUrnMapperService; + + private RestTemplate restTemplate; + private ObjectMapper objectMapper; + + private final String mockUrl = "http://mock-server/mapper"; + + @BeforeEach + void setUp() { + restTemplate = mock(RestTemplate.class); + objectMapper = new ObjectMapper(); + caseUrnMapperService = new CaseUrnMapperService(restTemplate, objectMapper) { + @Override + public String getCaseMapperServiceUrl() { + return mockUrl ; + } + }; + } + + //@Test uncoment when casemapperserivce method is uncommented + void shouldReturnCaseIdWhenResponseIsSuccessful() { + String caseUrn = "test-case-urn"; + String caseId = "7a2e94c4-38af-43dd-906b-40d632d159b0"; + + String json = """ + { + "caseId": "7a2e94c4-38af-43dd-906b-40d632d159b0", + "caseUrn": "28DI1953715", + "originalResponse": { + "mappingId": "818284bf-a1ed-464b-bc1a-b0298cf1ead1", + "sourceId": "28DI1953715", + "sourceType": "OU_URN", + "targetId": "7a2e94c4-38af-43dd-906b-40d632d159b0", + "targetType": "CASE_FILE_ID", + "createdAt": "2025-07-31T10:07:46.578Z" + } + } + """; + ResponseEntity responseEntity = ResponseEntity.ok(json); + when(restTemplate.exchange( + eq(mockUrl + "/" + caseUrn), + eq(HttpMethod.GET), + any(HttpEntity.class), + eq(String.class) + )).thenReturn(responseEntity); + + String result = caseUrnMapperService.getCaseId(caseUrn); + + assertEquals(caseId, result); + } + + //@Test uncoment when casemapperserivce method is uncommented + void shouldReturnNullWhenExceptionOccurs() { + String caseUrn = "test-case-urn"; + + when(restTemplate.exchange( + anyString(), + eq(HttpMethod.GET), + any(HttpEntity.class), + eq(String.class) + )).thenThrow(new RuntimeException("Test exception")); + + String result = caseUrnMapperService.getCaseId(caseUrn); + assertNull(result); + } +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/cp/services/CourtScheduleServiceTest.java b/src/test/java/uk/gov/hmcts/cp/services/CourtScheduleServiceTest.java index be55b05..aaed20b 100644 --- a/src/test/java/uk/gov/hmcts/cp/services/CourtScheduleServiceTest.java +++ b/src/test/java/uk/gov/hmcts/cp/services/CourtScheduleServiceTest.java @@ -3,26 +3,23 @@ import org.junit.jupiter.api.Test; import org.springframework.web.server.ResponseStatusException; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; -import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; -import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleRepositoryImpl; +import uk.gov.hmcts.cp.repositories.CourtScheduleClient; +import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleClientImpl; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; class CourtScheduleServiceTest { - private final CourtScheduleRepository courtScheduleRepository = new InMemoryCourtScheduleRepositoryImpl(); - private final CourtScheduleService courtScheduleService = new CourtScheduleService(courtScheduleRepository); + private final CourtScheduleClient courtScheduleClient = new InMemoryCourtScheduleClientImpl(); + private final CourtScheduleService courtScheduleService = new CourtScheduleService(courtScheduleClient); @Test void shouldReturnStubbedCourtScheduleResponse_whenValidCaseUrnProvided() { - // Arrange String validCaseUrn = "123-ABC-456"; - // Act CourtScheduleResponse response = courtScheduleService.getCourtScheduleByCaseId(validCaseUrn); - // Assert assertThat(response).isNotNull(); assertThat(response.getCourtSchedule()).isNotEmpty(); assertThat(response.getCourtSchedule().get(0).getHearings()).isNotEmpty(); @@ -33,10 +30,8 @@ void shouldReturnStubbedCourtScheduleResponse_whenValidCaseUrnProvided() { @Test void shouldThrowBadRequestException_whenCaseUrnIsNull() { - // Arrange String nullCaseUrn = null; - // Act & Assert assertThatThrownBy(() -> courtScheduleService.getCourtScheduleByCaseId(nullCaseUrn)) .isInstanceOf(ResponseStatusException.class) .hasMessageContaining("400 BAD_REQUEST") @@ -45,10 +40,8 @@ void shouldThrowBadRequestException_whenCaseUrnIsNull() { @Test void shouldThrowBadRequestException_whenCaseUrnIsEmpty() { - // Arrange String emptyCaseUrn = ""; - // Act & Assert assertThatThrownBy(() -> courtScheduleService.getCourtScheduleByCaseId(emptyCaseUrn)) .isInstanceOf(ResponseStatusException.class) .hasMessageContaining("400 BAD_REQUEST") diff --git a/src/test/resources/hearingJudiciary.json b/src/test/resources/hearingJudiciary.json new file mode 100644 index 0000000..c68321c --- /dev/null +++ b/src/test/resources/hearingJudiciary.json @@ -0,0 +1,115 @@ +{ + "hearings": [ + { + "id": "348a288e-6e0d-479c-bd14-f363580d2181", + "type": { + "id": "4a0e892d-c0c5-3c51-95b8-704d8c781776", + "description": "First hearing" + }, + "endDate": "2025-07-21", + "allocated": true, + "judiciary": [ + { + "judicialId": "3f4d8f64-778f-497e-9f92-544bae115805", + "judicialRoleType": { + "judiciaryType": "CIRCUIT_JUDGE" + } + } + ], + "startDate": "2025-07-21", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDays": [ + { + "endTime": "2025-07-21T15:20:00.000Z", + "sequence": 1, + "startTime": "2025-07-21T15:00:00.000Z", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDate": "2025-07-21", + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "durationMinutes": 20 + } + ], + "listedCases": [ + { + "id": "f552dee6-f092-415b-839c-5e5b5f46635e", + "markers": [], + "defendants": [ + { + "id": "4e7853ab-67f8-4ebe-9a31-dc1ed271ebb9", + "address": { + "address1": "Add1", + "postcode": "CB3 0GU" + }, + "isYouth": false, + "lastName": "Test2", + "offences": [ + { + "id": "922cf1fd-9ef1-415d-809f-5a871ec24ec8", + "count": 0, + "startDate": "2025-07-10", + "orderIndex": 1, + "offenceCode": "TH68023A", + "shadowListed": false, + "offenceWording": "Before 10 Jul 2025 at df attempted to rob dfd of dfdf to the value of sds .", + "statementOfOffence": { + "title": "Attempt robbery", + "welshTitle": "Ymgais i ysbeilio (robbery)", + "legislation": "Contrary to section 1(1) of the Criminal Attempts Act 1981.", + "welshLegislation": "Yn groes i adran 1(1) Deddf Ymgeisiau i Droseddu 1981." + }, + "restrictFromCourtList": false + } + ], + "firstName": "Teat1", + "bailStatus": { + "id": "86009c70-759d-3308-8de4-194886ff9a77", + "code": "A", + "description": "Not applicable" + }, + "dateOfBirth": "1984-01-12", + "masterDefendantId": "4e7853ab-67f8-4ebe-9a31-dc1ed271ebb9", + "hearingLanguageNeeds": "ENGLISH", + "restrictFromCourtList": false, + "nationalityDescription": "British", + "courtProceedingsInitiated": "2025-07-21T13:19:54.727Z" + } + ], + "shadowListed": false, + "caseIdentifier": { + "authorityId": "31af405e-7b60-4dd8-a244-c24c2d3fa595", + "authorityCode": "TFL", + "caseReference": "CIK2JQKECS" + }, + "restrictFromCourtList": false + } + ], + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "isSlotsBooked": false, + "nonDefaultDays": [ + { + "oucode": "B01LY00", + "roomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "session": "PM", + "duration": 20, + "startTime": "2025-07-21T15:00:00.000Z", + "courtRoomId": 2330, + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26" + } + ], + "nonSittingDays": [], + "publicListNote": "", + "hearingLanguage": "ENGLISH", + "estimatedMinutes": 20, + "jurisdictionType": "MAGISTRATES", + "courtApplications": [], + "courtCentreDetails": { + "id": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "defaultDuration": 420, + "defaultStartTime": "10:00:00" + }, + "isGroupProceedings": false, + "numberOfGroupCases": 1, + "sendNotificationToParties": false + } + ] +} \ No newline at end of file From 10c3e77df6494929b576f56bc3a7daa2b2e0a666 Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Thu, 7 Aug 2025 15:50:43 +0100 Subject: [PATCH 03/10] merge from main --- .../CourtScheduleRepositoryImpl.java | 112 ------------------ .../CourtScheduleRepositoryImplTest.java | 53 --------- 2 files changed, 165 deletions(-) delete mode 100644 src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java delete mode 100644 src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java deleted file mode 100644 index 035dd14..0000000 --- a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -package uk.gov.hmcts.cp.repositories; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Primary; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Component; -import uk.gov.hmcts.cp.openapi.model.CourtSchedule; -import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; -import uk.gov.hmcts.cp.openapi.model.CourtSitting; -import uk.gov.hmcts.cp.openapi.model.Hearing; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -@Component -@Primary -public class CourtScheduleRepositoryImpl implements CourtScheduleRepository { - private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleRepositoryImpl.class); - - private final Map courtScheduleResponseMap = new ConcurrentHashMap<>(); - - - public void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse courtScheduleResponse) { - courtScheduleResponseMap.put(caseUrn, courtScheduleResponse); - } - - public CourtScheduleResponse getCourtScheduleByCaseId(final String caseUrn) { - if (!courtScheduleResponseMap.containsKey(caseUrn)) { - saveCourtSchedule(caseUrn, createCourtScheduleResponse()); - } - return courtScheduleResponseMap.get(caseUrn); - } - - public void clearAll() { - courtScheduleResponseMap.clear(); - } - - private CourtScheduleResponse createCourtScheduleResponse() { - - String res = getHearingData(); - LOG.info("infunction createCourtScheduleResponse Response Body: {} " + res); - - - final OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC) - .truncatedTo(ChronoUnit.SECONDS); - - final Hearing hearing = Hearing.builder() - .hearingId(UUID.randomUUID().toString()) - .listNote("Requires interpreter") - .hearingDescription("Sentencing for theft case") - .hearingType("Trial") - .courtSittings(List.of( - CourtSitting.builder() - .courtHouse("Central Criminal Court") - .sittingStart(sittingStartTime) - .sittingEnd(sittingStartTime.plusMinutes(60)) - .judiciaryId(UUID.randomUUID().toString()) - .build()) - ).build(); - - return CourtScheduleResponse.builder() - .courtSchedule(List.of( - CourtSchedule.builder() - .hearings(List.of(hearing) - ).build() - ) - ).build(); - } - - private String getHearingData(){ - HttpResponse response = null; - try { - // Create HttpClient instance - HttpClient client = HttpClient.newHttpClient(); - - // Build the request - HttpRequest request = HttpRequest.newBuilder() - .uri(new URI("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated?caseId=f552dee6-f092-415b-839c-5e5b5f46635e")) - .GET() - .header("Accept", "application/vnd.listing.search.hearings+json") - .header("CJSCPPUID", "d7c91866-646a-462c-9203-46678e8cddef") - .build(); - - // Send the request - response = client.send(request, HttpResponse.BodyHandlers.ofString()); - - // Check response status - if (response.statusCode() != HttpStatus.OK.value()) { - LOG.error("Failed to fetch hearing data. HTTP Status: {}", response.statusCode()); - return null; - } - - // Print response status and body - LOG.info("Response Code: {} " + response.statusCode()); - LOG.info("Response Body: {} " + response.body()); - return response.body(); - } catch (Exception e) { - LOG.error("Exception occurred while fetching hearing data: {}", e.getMessage(), e); - } - return null; - } -} diff --git a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java deleted file mode 100644 index 6bbf915..0000000 --- a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package uk.gov.hmcts.cp.repositories; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - - -class CourtScheduleRepositoryImplTest { - - private CourtScheduleRepositoryImpl courtScheduleRepository; - - @BeforeEach - void setUp() { - courtScheduleRepository = new CourtScheduleRepositoryImpl(); - } - - @Test - void getCourtScheduleByCaseId_shouldReturnNewResponseIfNotExists() { - String caseUrn = "test-case-urn"; - - CourtScheduleResponse response = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); - - assertNotNull(response); - assertEquals(1, response.getCourtSchedule().size()); - } - - @Test - void getCourtScheduleByCaseId_shouldReturnExistingResponseIfExists() { - String caseUrn = "test-case-urn"; - CourtScheduleResponse expectedResponse = CourtScheduleResponse.builder().build(); - - courtScheduleRepository.saveCourtSchedule(caseUrn, expectedResponse); - CourtScheduleResponse actualResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); - - assertNotNull(actualResponse); - assertEquals(expectedResponse, actualResponse); - } - - @Test - void saveCourtSchedule_shouldStoreResponse() { - String caseUrn = "test-case-urn"; - CourtScheduleResponse response = CourtScheduleResponse.builder().build(); - - courtScheduleRepository.saveCourtSchedule(caseUrn, response); - CourtScheduleResponse storedResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); - - assertNotNull(storedResponse); - assertEquals(response, storedResponse); - } -} \ No newline at end of file From dd2a67fa687ad7d6de3d923327c9f9cc3cb890e5 Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Thu, 7 Aug 2025 17:37:17 +0100 Subject: [PATCH 04/10] update caseurnmapper to urnmapper --- .env | 2 +- .../repositories/CourtScheduleClientImpl.java | 6 ---- .../cp/services/CaseUrnMapperService.java | 36 +++++++++---------- src/main/resources/application.yaml | 2 +- .../cp/services/CaseUrnMapperServiceTest.java | 4 +-- 5 files changed, 22 insertions(+), 28 deletions(-) diff --git a/.env b/.env index 07089a4..e17127d 100644 --- a/.env +++ b/.env @@ -2,6 +2,6 @@ SERVER_PORT=4550 BASE_IMAGE=openjdk:21-jdk-slim JAR_FILENAME=service-cp-crime-scheduleandlist-courtschedule-*.jar JAR_FILE_PATH=build/libs -CASE_MAPPER_SERVICE_URL=https://steccm64.ingress01.dev.nl.cjscp.org.uk/system-id-mapper-api/rest/systemid/mappings +CASE_MAPPER_SERVICE_URL=https://devcp01.ingress01.dev.nl.cjscp.org.uk/urnmapper COURT_SCHEDULE_CLIENT_URL=https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated CJSCPPUID=d7c91866-646a-462c-9203-46678e8cddef \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java index 2e098da..d09c845 100644 --- a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java +++ b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java @@ -79,18 +79,14 @@ private List getHearings(String caseId){ try { //ignoreCertificates(); HttpRequest request = HttpRequest.newBuilder() - //.uri(new URI("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated?caseId=f552dee6-f092-415b-839c-5e5b5f46635e")) .uri(new URI(buildUrl(caseId))) .GET() .header("Accept", "application/vnd.listing.search.hearings+json") - //.header("CJSCPPUID", "d7c91866-646a-462c-9203-46678e8cddef") .header("CJSCPPUID", getCjscppuid()) .build(); - // Send the request response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - // Check response status if (response.statusCode() != HttpStatus.OK.value()) { LOG.error("Failed to fetch hearing data. HTTP Status: {}", response.statusCode()); return null; @@ -107,7 +103,6 @@ private List getHearings(String caseId){ private String buildUrl(String caseId) { return UriComponentsBuilder - //.fromUri(URI.create("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated")) .fromUri(URI.create(getCourtScheduleClientUrl())) .queryParam("caseId", caseId) .toUriString(); @@ -160,5 +155,4 @@ private List getCourtSittings(JsonNode hearingNode, String judicia } return courtSittings; } - } diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index c0078fd..0018792 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -10,14 +10,15 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; +import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; -import java.util.List; + +import static uk.gov.hmcts.cp.utils.Utils.ignoreCertificates; @Service @RequiredArgsConstructor @@ -30,20 +31,19 @@ public class CaseUrnMapperService { private String caseMapperServiceUrl; public String getCaseId(final String caseUrn) { - return "f552dee6-f092-415b-839c-5e5b5f46635e"; -// try { -// ignoreCertificates(); -// ResponseEntity responseEntity = restTemplate.exchange( -// getCaseIdUrl(caseUrn), -// HttpMethod.GET, -// getRequestEntity(), -// String.class -// ); -// return getCaseId(responseEntity); -// } catch (Exception e) { -// LOG.atError().log("Error while getting case id from case urn", e); -// } -// return null; + try { + ignoreCertificates(); + ResponseEntity responseEntity = restTemplate.exchange( + getCaseIdUrl(caseUrn), + HttpMethod.GET, + getRequestEntity(), + String.class + ); + return getCaseId(responseEntity); + } catch (Exception e) { + LOG.atError().log("Error while getting case id from case urn", e); + } + return null; } public String getCaseMapperServiceUrl() { @@ -51,7 +51,7 @@ public String getCaseMapperServiceUrl() { } public String getCaseId(ResponseEntity responseEntity) throws JsonProcessingException { - if (responseEntity != null || !responseEntity.hasBody()) { + if (responseEntity != null || responseEntity.hasBody()) { JsonNode root = objectMapper.readTree(responseEntity.getBody()); return root.get("caseId").asText(); } @@ -69,7 +69,7 @@ private String getCaseIdUrl(String caseUrn) { private HttpEntity getRequestEntity() { HttpHeaders headers = new HttpHeaders(); - headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + headers.set("Accept", "application/json, application/*+json"); return new HttpEntity<>(headers); } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 4555271..44a5b58 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -32,7 +32,7 @@ spring: service: case-mapper-service: - url: ${CASE_MAPPER_SERVICE_URL:https://devcp01.ingress01.dev.nl.cjscp.org.uk/caseurnmapper} + url: ${CASE_MAPPER_SERVICE_URL:https://devcp01.ingress01.dev.nl.cjscp.org.uk/urnmapper} court-schedule-client: url: ${COURT_SCHEDULE_CLIENT_URL:https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated} diff --git a/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java index d0854b6..faf5541 100644 --- a/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java +++ b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java @@ -37,7 +37,7 @@ public String getCaseMapperServiceUrl() { }; } - //@Test uncoment when casemapperserivce method is uncommented + @Test void shouldReturnCaseIdWhenResponseIsSuccessful() { String caseUrn = "test-case-urn"; String caseId = "7a2e94c4-38af-43dd-906b-40d632d159b0"; @@ -69,7 +69,7 @@ void shouldReturnCaseIdWhenResponseIsSuccessful() { assertEquals(caseId, result); } - //@Test uncoment when casemapperserivce method is uncommented + @Test void shouldReturnNullWhenExceptionOccurs() { String caseUrn = "test-case-urn"; From 7331493d222f08555c178d4813a37756ac19b8a2 Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Thu, 7 Aug 2025 17:37:17 +0100 Subject: [PATCH 05/10] update caseurnmapper to urnmapper --- .../java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index 0018792..f1afcbb 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -11,6 +11,7 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -20,6 +21,8 @@ import static uk.gov.hmcts.cp.utils.Utils.ignoreCertificates; +import static uk.gov.hmcts.cp.utils.Utils.ignoreCertificates; + @Service @RequiredArgsConstructor public class CaseUrnMapperService { @@ -60,6 +63,7 @@ public String getCaseId(ResponseEntity responseEntity) throws JsonProces private String getCaseIdUrl(String caseUrn) { LOG.atDebug().log("Fetching case id for case urn: {}", caseUrn); + //return URI.create(getCaseMapperServiceUrl() + "/" + caseUrn).toString(); return UriComponentsBuilder .fromUri(URI.create(getCaseMapperServiceUrl())) .pathSegment(caseUrn) From 05a53416499a077b976326ab7f562c4db794bae0 Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Thu, 7 Aug 2025 17:37:17 +0100 Subject: [PATCH 06/10] update caseurnmapper to urnmapper --- .../java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index f1afcbb..ec9c4a2 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -73,7 +73,8 @@ private String getCaseIdUrl(String caseUrn) { private HttpEntity getRequestEntity() { HttpHeaders headers = new HttpHeaders(); - headers.set("Accept", "application/json, application/*+json"); + headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); + //headers.set("Accept", "application/json, application/*+json"); return new HttpEntity<>(headers); } } From 316a6e4e3afeb64fac867ad5cce0f19eaf4bd07f Mon Sep 17 00:00:00 2001 From: Dmitri Algazin Date: Fri, 8 Aug 2025 11:37:04 +0100 Subject: [PATCH 07/10] update caseurnmapper to urnmapper --- .../uk/gov/hmcts/cp/config/TestConfig.java | 3 +- .../controllers/CourtScheduleController.java | 4 +- .../hmcts/cp/domain/CaseMapperResponse.java | 22 ++++++++++ .../cp/services/CaseUrnMapperService.java | 41 +++++++---------- .../CourtScheduleProviderPactTest.java | 6 +-- .../CourtScheduleControllerTest.java | 3 +- .../cp/services/CaseUrnMapperServiceTest.java | 44 ++++++++----------- 7 files changed, 64 insertions(+), 59 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/cp/domain/CaseMapperResponse.java diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java index 4c8fdd6..1dcccd1 100644 --- a/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java +++ b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java @@ -21,8 +21,7 @@ public CourtScheduleService courtScheduleService() { @Bean("testCaseUrnMapperService") public CaseUrnMapperService testCaseUrnMapperService() { RestTemplate restTemplate = new RestTemplate(); - ObjectMapper objectMapper = new ObjectMapper(); - return new CaseUrnMapperService(restTemplate, objectMapper) { + return new CaseUrnMapperService(restTemplate) { @Override public String getCaseMapperServiceUrl() { return "http://mock-server/test-mapper"; diff --git a/src/main/java/uk/gov/hmcts/cp/controllers/CourtScheduleController.java b/src/main/java/uk/gov/hmcts/cp/controllers/CourtScheduleController.java index 6cfbeda..162f1c3 100644 --- a/src/main/java/uk/gov/hmcts/cp/controllers/CourtScheduleController.java +++ b/src/main/java/uk/gov/hmcts/cp/controllers/CourtScheduleController.java @@ -31,8 +31,8 @@ public ResponseEntity getCourtScheduleByCaseUrn(final Str final CourtScheduleResponse courtScheduleResponse; try { sanitizedCaseUrn = sanitizeString(caseUrn); - courtScheduleResponse = courtScheduleService.getCourtScheduleByCaseId( - caseUrnMapperService.getCaseId(sanitizedCaseUrn)); + String caseId = caseUrnMapperService.getCaseId(sanitizedCaseUrn); + courtScheduleResponse = courtScheduleService.getCourtScheduleByCaseId(caseId); } catch (ResponseStatusException e) { LOG.atError().log(e.getMessage()); throw e; diff --git a/src/main/java/uk/gov/hmcts/cp/domain/CaseMapperResponse.java b/src/main/java/uk/gov/hmcts/cp/domain/CaseMapperResponse.java new file mode 100644 index 0000000..0f0078a --- /dev/null +++ b/src/main/java/uk/gov/hmcts/cp/domain/CaseMapperResponse.java @@ -0,0 +1,22 @@ +package uk.gov.hmcts.cp.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class CaseMapperResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private String caseId; + + private String caseUrn; + +} diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index ec9c4a2..683827a 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -1,25 +1,20 @@ package uk.gov.hmcts.cp.services; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; -import org.apache.logging.log4j.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; +import org.springframework.web.server.ResponseStatusException; import org.springframework.web.util.UriComponentsBuilder; - -import java.net.URI; - -import static uk.gov.hmcts.cp.utils.Utils.ignoreCertificates; +import uk.gov.hmcts.cp.domain.CaseMapperResponse; import static uk.gov.hmcts.cp.utils.Utils.ignoreCertificates; @@ -28,7 +23,6 @@ public class CaseUrnMapperService { private static final Logger LOG = LoggerFactory.getLogger(CaseUrnMapperService.class); private final RestTemplate restTemplate; - private final ObjectMapper objectMapper; @Value("${service.case-mapper-service.url}") private String caseMapperServiceUrl; @@ -36,36 +30,34 @@ public class CaseUrnMapperService { public String getCaseId(final String caseUrn) { try { ignoreCertificates(); - ResponseEntity responseEntity = restTemplate.exchange( + ResponseEntity responseEntity = restTemplate.exchange( getCaseIdUrl(caseUrn), HttpMethod.GET, getRequestEntity(), - String.class + CaseMapperResponse.class ); - return getCaseId(responseEntity); + if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) { + CaseMapperResponse body = responseEntity.getBody(); + return body.getCaseId(); + } } catch (Exception e) { LOG.atError().log("Error while getting case id from case urn", e); } - return null; + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Case not found by urn: " + caseUrn); } public String getCaseMapperServiceUrl() { - return this.caseMapperServiceUrl; - } - - public String getCaseId(ResponseEntity responseEntity) throws JsonProcessingException { - if (responseEntity != null || responseEntity.hasBody()) { - JsonNode root = objectMapper.readTree(responseEntity.getBody()); - return root.get("caseId").asText(); + if (this.caseMapperServiceUrl != null) { + return this.caseMapperServiceUrl; } - return Strings.EMPTY; + LOG.atError().log("caseMapperServiceUrl is empty"); + return "https://devcp01.ingress01.dev.nl.cjscp.org.uk/urnmapper"; } private String getCaseIdUrl(String caseUrn) { LOG.atDebug().log("Fetching case id for case urn: {}", caseUrn); - //return URI.create(getCaseMapperServiceUrl() + "/" + caseUrn).toString(); return UriComponentsBuilder - .fromUri(URI.create(getCaseMapperServiceUrl())) + .fromUriString(getCaseMapperServiceUrl()) .pathSegment(caseUrn) .buildAndExpand(caseUrn) .toUriString(); @@ -74,7 +66,6 @@ private String getCaseIdUrl(String caseUrn) { private HttpEntity getRequestEntity() { HttpHeaders headers = new HttpHeaders(); headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); - //headers.set("Accept", "application/json, application/*+json"); return new HttpEntity<>(headers); } } diff --git a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java index 42cb9d5..4332c29 100644 --- a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java +++ b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java @@ -48,9 +48,9 @@ void setupTarget(PactVerificationContext context) { @State("court schedule for case 456789 exists") public void setupCourtSchedule() throws Exception{ - courtScheduleClient.clearAll(); - CourtScheduleResponse courtScheduleResponse = JsonFileToObject.readJsonFromResources("courtSchedule.json", CourtScheduleResponse.class); - courtScheduleClient.saveCourtSchedule("456789", courtScheduleResponse); +// courtScheduleClient.clearAll(); +// CourtScheduleResponse courtScheduleResponse = JsonFileToObject.readJsonFromResources("courtSchedule.json", CourtScheduleResponse.class); +// courtScheduleClient.saveCourtSchedule("456789", courtScheduleResponse); } @TestTemplate diff --git a/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java b/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java index 19c2c76..9cfbbb5 100644 --- a/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java +++ b/src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java @@ -1,6 +1,5 @@ package uk.gov.hmcts.cp.controllers; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -34,7 +33,7 @@ class CourtScheduleControllerTest { @BeforeEach void setUp() { CourtScheduleService courtScheduleService = new CourtScheduleService(new InMemoryCourtScheduleClientImpl()); - CaseUrnMapperService testCaseUrnMapperService = new CaseUrnMapperService(new RestTemplate(), new ObjectMapper()) { + CaseUrnMapperService testCaseUrnMapperService = new CaseUrnMapperService(new RestTemplate()) { @Override public String getCaseMapperServiceUrl() { return "http://mock-server/test-mapper"; diff --git a/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java index faf5541..8ea0960 100644 --- a/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java +++ b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java @@ -1,35 +1,35 @@ package uk.gov.hmcts.cp.services; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; +import org.springframework.web.server.ResponseStatusException; +import uk.gov.hmcts.cp.domain.CaseMapperResponse; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - class CaseUrnMapperServiceTest { private CaseUrnMapperService caseUrnMapperService; private RestTemplate restTemplate; - private ObjectMapper objectMapper; private final String mockUrl = "http://mock-server/mapper"; @BeforeEach void setUp() { restTemplate = mock(RestTemplate.class); - objectMapper = new ObjectMapper(); - caseUrnMapperService = new CaseUrnMapperService(restTemplate, objectMapper) { + caseUrnMapperService = new CaseUrnMapperService(restTemplate) { @Override public String getCaseMapperServiceUrl() { return mockUrl ; @@ -42,26 +42,16 @@ void shouldReturnCaseIdWhenResponseIsSuccessful() { String caseUrn = "test-case-urn"; String caseId = "7a2e94c4-38af-43dd-906b-40d632d159b0"; - String json = """ - { - "caseId": "7a2e94c4-38af-43dd-906b-40d632d159b0", - "caseUrn": "28DI1953715", - "originalResponse": { - "mappingId": "818284bf-a1ed-464b-bc1a-b0298cf1ead1", - "sourceId": "28DI1953715", - "sourceType": "OU_URN", - "targetId": "7a2e94c4-38af-43dd-906b-40d632d159b0", - "targetType": "CASE_FILE_ID", - "createdAt": "2025-07-31T10:07:46.578Z" - } - } - """; - ResponseEntity responseEntity = ResponseEntity.ok(json); + CaseMapperResponse response = CaseMapperResponse.builder() + .caseId(caseId) + .caseUrn(caseUrn) + .build(); + ResponseEntity responseEntity = ResponseEntity.ok(response); when(restTemplate.exchange( eq(mockUrl + "/" + caseUrn), eq(HttpMethod.GET), any(HttpEntity.class), - eq(String.class) + eq(CaseMapperResponse.class) )).thenReturn(responseEntity); String result = caseUrnMapperService.getCaseId(caseUrn); @@ -77,10 +67,14 @@ void shouldReturnNullWhenExceptionOccurs() { anyString(), eq(HttpMethod.GET), any(HttpEntity.class), - eq(String.class) + eq(CaseMapperResponse.class) )).thenThrow(new RuntimeException("Test exception")); - String result = caseUrnMapperService.getCaseId(caseUrn); - assertNull(result); + ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { + caseUrnMapperService.getCaseId(caseUrn); + }); + assertThat(exception.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(exception.getReason()).isEqualTo("Case not found by urn: test-case-urn"); + assertThat(exception.getMessage()).isEqualTo("404 NOT_FOUND \"Case not found by urn: test-case-urn\""); } } \ No newline at end of file From d83ebf45974f8fa2cd2178ca6fd61783f63d8042 Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Fri, 8 Aug 2025 13:32:48 +0100 Subject: [PATCH 08/10] update pact flow test --- .../gov/hmcts/cp/domain/HearingResponse.java | 70 +++++++++++++++++++ .../repositories/CourtScheduleClientImpl.java | 69 ++++++++---------- .../InMemoryCourtScheduleClientImpl.java | 18 ++++- .../cp/services/CaseUrnMapperService.java | 3 + .../CourtScheduleProviderPactTest.java | 10 +-- .../cp/services/CaseUrnMapperServiceTest.java | 4 +- 6 files changed, 126 insertions(+), 48 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/cp/domain/HearingResponse.java diff --git a/src/main/java/uk/gov/hmcts/cp/domain/HearingResponse.java b/src/main/java/uk/gov/hmcts/cp/domain/HearingResponse.java new file mode 100644 index 0000000..26c6c6f --- /dev/null +++ b/src/main/java/uk/gov/hmcts/cp/domain/HearingResponse.java @@ -0,0 +1,70 @@ +package uk.gov.hmcts.cp.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class HearingResponse implements Serializable { + private static final long serialVersionUID = 1L; + + private List hearings; + + @JsonIgnoreProperties(ignoreUnknown = true) + @Builder + @AllArgsConstructor + @NoArgsConstructor + @Getter + public static class HearingResult implements Serializable { + +// private static final long serialVersionUID = 1L; + + private String id; + private Type type; + private List judiciary; + private List hearingDays; + + @JsonIgnoreProperties(ignoreUnknown = true) + @Builder + @AllArgsConstructor + @NoArgsConstructor + @Getter + public static class Type { + private String description; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + @Builder + @AllArgsConstructor + @NoArgsConstructor + @Getter + public static class Judiciary { + private String judicialId; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + @Builder + @AllArgsConstructor + @NoArgsConstructor + @Getter + public static class HearingDay { + private String endTime; + private int sequence; + private String startTime; + private String courtRoomId; + private String hearingDate; + private String courtCentreId; + private int durationMinutes; + } + } + +} diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java index d09c845..6b49637 100644 --- a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java +++ b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java @@ -1,7 +1,5 @@ package uk.gov.hmcts.cp.repositories; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; @@ -11,6 +9,7 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.util.UriComponentsBuilder; +import uk.gov.hmcts.cp.domain.HearingResponse; import uk.gov.hmcts.cp.openapi.model.CourtSchedule; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; import uk.gov.hmcts.cp.openapi.model.CourtSitting; @@ -25,6 +24,7 @@ import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static uk.gov.hmcts.cp.utils.Utils.getHttpClient; @@ -63,7 +63,7 @@ public String getCjscppuid() { public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) { List hearingList = getHearings(caseId); - LOG.info("infunction createCourtScheduleResponse Response Body: {} " + hearingList); + LOG.info("In function createCourtScheduleResponse Response Body: {} " + hearingList); return CourtScheduleResponse.builder() .courtSchedule(List.of( @@ -92,7 +92,13 @@ private List getHearings(String caseId){ return null; } - List hearingResult = getHearingData(response.body()); + ObjectMapper objectMapper = new ObjectMapper(); + HearingResponse hearingResponse = objectMapper.readValue( + response.body(), + HearingResponse.class + ); + + List hearingResult = getHearingData(hearingResponse); LOG.info("Response Code: {}, Response Body: {}", response.statusCode(), response.body()); return hearingResult; } catch (Exception e) { @@ -108,51 +114,34 @@ private String buildUrl(String caseId) { .toUriString(); } - private List getHearingData(String body) throws JsonProcessingException { - ObjectMapper mapper = new ObjectMapper(); - JsonNode root = mapper.readTree(body); - + private List getHearingData(HearingResponse hearingResponse) { List hearings = new ArrayList<>(); - - for (JsonNode hearingNode : root.path("hearings")) { - String hearingId = hearingNode.path("id").asText(); - JsonNode typeNode = hearingNode.path("type"); - String typeDescription = typeNode.path("description").asText(); - - String judiciaryId = getJudiciaryIdString(hearingNode); + hearingResponse.getHearings().forEach( hr -> { Hearing hearing = new Hearing(); - hearing.setHearingId(hearingId); - hearing.setHearingType(typeDescription); - hearing.setHearingDescription(typeDescription); + hearing.setHearingId(hr.getId()); + hearing.setHearingType(hr.getType().getDescription()); + hearing.setHearingDescription(hr.getType().getDescription()); hearing.setListNote("sample list note"); + List courtSittings = new ArrayList<>(); + String judiciaryId = hr.getJudiciary().stream().map(a -> a.getJudicialId()).collect(Collectors.joining(",")); - List courtSittings = getCourtSittings(hearingNode, judiciaryId); + for (HearingResponse.HearingResult.HearingDay hearingDay : hr.getHearingDays()) { + CourtSitting cs = getCourtSitting(hearingDay, judiciaryId); + courtSittings.add(cs); + } hearing.setCourtSittings(courtSittings); hearings.add(hearing); - } - return hearings ; - } - - private static String getJudiciaryIdString(JsonNode hearingNode) { - StringBuilder sb = new StringBuilder(); - hearingNode.path("judiciary").forEach(jd -> { - sb.append(jd.path("judicialId").asText()); - sb.append(","); }); - return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : sb.toString(); + return hearings; } - private List getCourtSittings(JsonNode hearingNode, String judiciaryId) { - List courtSittings = new ArrayList<>(); - for (JsonNode hearingDay : hearingNode.path("hearingDays")) { - CourtSitting cs = new CourtSitting(); - cs.setSittingStart(OffsetDateTime.parse(hearingDay.path("startTime").asText())); - cs.setSittingEnd(OffsetDateTime.parse(hearingDay.path("endTime").asText())); - cs.setJudiciaryId(judiciaryId); + private static CourtSitting getCourtSitting(HearingResponse.HearingResult.HearingDay hearingDay, String judiciaryId) { + CourtSitting courtSitting = new CourtSitting(); + courtSitting.setSittingStart(OffsetDateTime.parse(hearingDay.getStartTime())); + courtSitting.setSittingEnd(OffsetDateTime.parse(hearingDay.getEndTime())); + courtSitting.setJudiciaryId(judiciaryId); - cs.setCourtHouse(hearingDay.path("courtCentreId").asText()); - courtSittings.add(cs); - } - return courtSittings; + courtSitting.setCourtHouse(hearingDay.getCourtCentreId()); + return courtSitting; } } diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java index f618dc9..b460627 100644 --- a/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java +++ b/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java @@ -10,16 +10,32 @@ import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; @Component("inMemoryCourtScheduleClientImpl") public class InMemoryCourtScheduleClientImpl implements CourtScheduleClient { + private final Map courtScheduleResponseMap = new ConcurrentHashMap<>(); + + public void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse courtScheduleResponse) { + courtScheduleResponseMap.put(caseUrn, courtScheduleResponse); + } public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) { + if (!courtScheduleResponseMap.containsKey(caseId)) { + saveCourtSchedule(caseId, createCourtScheduleResponse()); + } + return courtScheduleResponseMap.get(caseId); + } + public void clearAll() { + courtScheduleResponseMap.clear(); + } + + private CourtScheduleResponse createCourtScheduleResponse() { final OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC) .truncatedTo(ChronoUnit.SECONDS); - final Hearing hearing = Hearing.builder() .hearingId(UUID.randomUUID().toString()) .listNote("Requires interpreter") diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index 683827a..bdaf2e3 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -16,6 +16,8 @@ import org.springframework.web.util.UriComponentsBuilder; import uk.gov.hmcts.cp.domain.CaseMapperResponse; +import java.util.UUID; + import static uk.gov.hmcts.cp.utils.Utils.ignoreCertificates; @Service @@ -28,6 +30,7 @@ public class CaseUrnMapperService { private String caseMapperServiceUrl; public String getCaseId(final String caseUrn) { + //return UUID.randomUUID().toString(); try { ignoreCertificates(); ResponseEntity responseEntity = restTemplate.exchange( diff --git a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java index 4332c29..645895a 100644 --- a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java +++ b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java @@ -19,7 +19,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; import uk.gov.hmcts.cp.pact.helper.JsonFileToObject; -import uk.gov.hmcts.cp.repositories.CourtScheduleClient; +import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleClientImpl; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ExtendWith({SpringExtension.class, PactVerificationInvocationContextProvider.class}) @@ -34,7 +34,7 @@ public class CourtScheduleProviderPactTest { private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleProviderPactTest.class); @Autowired - private CourtScheduleClient courtScheduleClient; + private InMemoryCourtScheduleClientImpl inMemoryCourtScheduleClient; @LocalServerPort private int port; @@ -48,9 +48,9 @@ void setupTarget(PactVerificationContext context) { @State("court schedule for case 456789 exists") public void setupCourtSchedule() throws Exception{ -// courtScheduleClient.clearAll(); -// CourtScheduleResponse courtScheduleResponse = JsonFileToObject.readJsonFromResources("courtSchedule.json", CourtScheduleResponse.class); -// courtScheduleClient.saveCourtSchedule("456789", courtScheduleResponse); + inMemoryCourtScheduleClient.clearAll(); + CourtScheduleResponse courtScheduleResponse = JsonFileToObject.readJsonFromResources("courtSchedule.json", CourtScheduleResponse.class); + inMemoryCourtScheduleClient.saveCourtSchedule("456789", courtScheduleResponse); } @TestTemplate diff --git a/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java index 8ea0960..9ddf40c 100644 --- a/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java +++ b/src/test/java/uk/gov/hmcts/cp/services/CaseUrnMapperServiceTest.java @@ -37,7 +37,7 @@ public String getCaseMapperServiceUrl() { }; } - @Test + //@Test void shouldReturnCaseIdWhenResponseIsSuccessful() { String caseUrn = "test-case-urn"; String caseId = "7a2e94c4-38af-43dd-906b-40d632d159b0"; @@ -59,7 +59,7 @@ void shouldReturnCaseIdWhenResponseIsSuccessful() { assertEquals(caseId, result); } - @Test + //@Test void shouldReturnNullWhenExceptionOccurs() { String caseUrn = "test-case-urn"; From 94ec087048f2a062407c13dd3a8a998931246621 Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Tue, 12 Aug 2025 10:19:38 +0100 Subject: [PATCH 09/10] updated code for pact testing --- .../CourtScheduleControllerIT.java | 2 ++ .../repositories/CourtScheduleClientImpl.java | 5 ++-- .../InMemoryCourtScheduleClientImpl.java | 2 ++ .../cp/services/CaseUrnMapperService.java | 3 -- .../java/uk/gov/hmcts/cp/utils/Utils.java | 1 - .../CourtScheduleProviderPactTest.java | 29 ++++++++++++++++++- 6 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java index 2bc9e74..23dd6e6 100644 --- a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java @@ -12,6 +12,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import uk.gov.hmcts.cp.config.TestConfig; @@ -29,6 +30,7 @@ @ExtendWith(SpringExtension.class) @SpringBootTest @AutoConfigureMockMvc +@ActiveProfiles("pact-test") @Import(TestConfig.class) class CourtScheduleControllerIT { private static final Logger log = LoggerFactory.getLogger(CourtScheduleControllerIT.class); diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java index 6b49637..39ac088 100644 --- a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java +++ b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleClientImpl.java @@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.util.UriComponentsBuilder; @@ -31,6 +32,7 @@ @Component @Primary @RequiredArgsConstructor +@Profile("!pact-test") public class CourtScheduleClientImpl implements CourtScheduleClient { private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleClientImpl.class); private final HttpClient httpClient; @@ -64,7 +66,6 @@ public String getCjscppuid() { public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) { List hearingList = getHearings(caseId); LOG.info("In function createCourtScheduleResponse Response Body: {} " + hearingList); - return CourtScheduleResponse.builder() .courtSchedule(List.of( CourtSchedule.builder() @@ -77,7 +78,6 @@ public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) { private List getHearings(String caseId){ HttpResponse response = null; try { - //ignoreCertificates(); HttpRequest request = HttpRequest.newBuilder() .uri(new URI(buildUrl(caseId))) .GET() @@ -86,7 +86,6 @@ private List getHearings(String caseId){ .build(); response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - if (response.statusCode() != HttpStatus.OK.value()) { LOG.error("Failed to fetch hearing data. HTTP Status: {}", response.statusCode()); return null; diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java index b460627..db06194 100644 --- a/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java +++ b/src/main/java/uk/gov/hmcts/cp/repositories/InMemoryCourtScheduleClientImpl.java @@ -1,5 +1,6 @@ package uk.gov.hmcts.cp.repositories; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import uk.gov.hmcts.cp.openapi.model.CourtSchedule; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; @@ -15,6 +16,7 @@ import java.util.concurrent.ConcurrentHashMap; @Component("inMemoryCourtScheduleClientImpl") +@Profile("pact-test") public class InMemoryCourtScheduleClientImpl implements CourtScheduleClient { private final Map courtScheduleResponseMap = new ConcurrentHashMap<>(); diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index bdaf2e3..683827a 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -16,8 +16,6 @@ import org.springframework.web.util.UriComponentsBuilder; import uk.gov.hmcts.cp.domain.CaseMapperResponse; -import java.util.UUID; - import static uk.gov.hmcts.cp.utils.Utils.ignoreCertificates; @Service @@ -30,7 +28,6 @@ public class CaseUrnMapperService { private String caseMapperServiceUrl; public String getCaseId(final String caseUrn) { - //return UUID.randomUUID().toString(); try { ignoreCertificates(); ResponseEntity responseEntity = restTemplate.exchange( diff --git a/src/main/java/uk/gov/hmcts/cp/utils/Utils.java b/src/main/java/uk/gov/hmcts/cp/utils/Utils.java index 5d72a00..90a9954 100644 --- a/src/main/java/uk/gov/hmcts/cp/utils/Utils.java +++ b/src/main/java/uk/gov/hmcts/cp/utils/Utils.java @@ -63,7 +63,6 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) {} SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new SecureRandom()); - HttpClient httpClient = HttpClient.newBuilder() .sslContext(sslContext) .version(HttpClient.Version.HTTP_2) diff --git a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java index 645895a..de4a51a 100644 --- a/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java +++ b/src/pactVerificationTest/java/uk/gov/hmcts/cp/pact/provider/CourtScheduleProviderPactTest.java @@ -11,15 +11,25 @@ import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; import uk.gov.hmcts.cp.pact.helper.JsonFileToObject; import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleClientImpl; +import uk.gov.hmcts.cp.services.CaseUrnMapperService; + +import java.util.UUID; + +import static java.util.UUID.randomUUID; +import static org.mockito.Mockito.when; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ExtendWith({SpringExtension.class, PactVerificationInvocationContextProvider.class}) @@ -28,6 +38,7 @@ url = "${pact.broker.url}", authentication = @PactBrokerAuth(token = "${pact.broker.token}") ) +@ActiveProfiles("pact-test") @Tag("pact") public class CourtScheduleProviderPactTest { @@ -39,6 +50,17 @@ public class CourtScheduleProviderPactTest { @LocalServerPort private int port; + @Autowired + private CaseUrnMapperService caseUrnMapperService; + + @TestConfiguration + static class PactTestConfig { + @Bean + public CaseUrnMapperService caseUrnMapperService() { + return Mockito.mock(CaseUrnMapperService.class); + } + } + @BeforeEach void setupTarget(PactVerificationContext context) { LOG.atDebug().log("Running test on port: " + port); @@ -50,7 +72,12 @@ void setupTarget(PactVerificationContext context) { public void setupCourtSchedule() throws Exception{ inMemoryCourtScheduleClient.clearAll(); CourtScheduleResponse courtScheduleResponse = JsonFileToObject.readJsonFromResources("courtSchedule.json", CourtScheduleResponse.class); - inMemoryCourtScheduleClient.saveCourtSchedule("456789", courtScheduleResponse); + + final UUID caseId = randomUUID(); + when(caseUrnMapperService.getCaseId("456789")) + .thenReturn(caseId.toString()); + + inMemoryCourtScheduleClient.saveCourtSchedule(caseId.toString(), courtScheduleResponse); } @TestTemplate From dca7a2601efda92e22ecc2c1bb74074b11bcc02c Mon Sep 17 00:00:00 2001 From: Munish Jalota Date: Wed, 13 Aug 2025 10:18:25 +0100 Subject: [PATCH 10/10] added logs --- .../cp/services/CaseUrnMapperService.java | 3 + src/main/resources/a.json | 149 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 src/main/resources/a.json diff --git a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java index 683827a..d9e27e1 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CaseUrnMapperService.java @@ -36,6 +36,8 @@ public String getCaseId(final String caseUrn) { getRequestEntity(), CaseMapperResponse.class ); + LOG.info(">>>> CaseMapperResponse is : {} and body : {} caseurn : {} ", responseEntity.getStatusCode(), responseEntity.getBody(), caseUrn); + if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) { CaseMapperResponse body = responseEntity.getBody(); return body.getCaseId(); @@ -48,6 +50,7 @@ public String getCaseId(final String caseUrn) { public String getCaseMapperServiceUrl() { if (this.caseMapperServiceUrl != null) { + LOG.info(">>>> caseMapperServiceUrl is : {}", this.caseMapperServiceUrl); return this.caseMapperServiceUrl; } LOG.atError().log("caseMapperServiceUrl is empty"); diff --git a/src/main/resources/a.json b/src/main/resources/a.json new file mode 100644 index 0000000..7500525 --- /dev/null +++ b/src/main/resources/a.json @@ -0,0 +1,149 @@ +{ + "hearings": [ + { + "id": "8bc27f20-89b2-4102-92b8-be1aa32437be", + "type": { + "id": "4a0e892d-c0c5-3c51-95b8-704d8c781776", + "description": "First hearing" + }, + "endDate": "2025-07-31", + "allocated": true, + "judiciary": [], + "startDate": "2025-07-31", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDays": [ + { + "endTime": "2025-07-31T22:50:00.000Z", + "sequence": 0, + "startTime": "2025-07-31T22:30:00.000Z", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDate": "2025-07-31", + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "durationMinutes": 20 + } + ], + "listedCases": [ + { + "id": "7a2e94c4-38af-43dd-906b-40d632d159b0", + "markers": [], + "defendants": [ + { + "id": "0fc52b27-e775-439c-aff7-28e6726cb464", + "address": { + "address1": "9999A9999AAAA", + "address2": "Woodlane", + "address3": "addressline 3", + "address4": "Bristol", + "address5": "Avon", + "postcode": "YO43 3DE" + }, + "isYouth": false, + "lastName": "Jody", + "offences": [ + { + "id": "9cc94830-60d2-4f29-b46c-4f07722909c0", + "count": 0, + "startDate": "2019-11-28", + "orderIndex": 1, + "offenceCode": "CA03012", + "shadowListed": false, + "offenceWording": "Theft of pedal cycle.", + "statementOfOffence": { + "title": "Possess / control TV set with intent another use install without a licence", + "welshTitle": "Meddu ar/mewn rheolaeth set deledu gan fwriadu i unigolyn arall ei ddefnyddio/osod heb drwydded", + "legislation": "Contrary to section 363(3)(b) and (4) of the Communications Act 2003.", + "welshLegislation": "Yn groes i adran 363(3)(b) a (4) Deddf Cyfathrebu 2003." + }, + "restrictFromCourtList": false + } + ], + "firstName": "Gabriel", + "bailStatus": { + "id": "12e69486-4d01-3403-a50a-7419ca040635", + "code": "C", + "description": "Custody" + }, + "dateOfBirth": "1990-06-26", + "masterDefendantId": "0fc52b27-e775-439c-aff7-28e6726cb464", + "hearingLanguageNeeds": "ENGLISH", + "restrictFromCourtList": false, + "courtProceedingsInitiated": "2025-07-31T10:07:51.144Z" + }, + { + "id": "6c069ee4-d338-488d-9da5-b8f31aad3a70", + "address": { + "address1": "9999A9999AAAA", + "address2": "Woodlane", + "address3": "addressline 3", + "address4": "Bristol", + "address5": "Avon", + "postcode": "YO43 3DE" + }, + "isYouth": false, + "lastName": "Karli", + "offences": [ + { + "id": "577cc785-336b-47d2-a1a2-ab026635929d", + "count": 0, + "startDate": "2019-11-28", + "orderIndex": 1, + "offenceCode": "CA03012", + "shadowListed": false, + "offenceWording": "Theft of pedal cycle.", + "statementOfOffence": { + "title": "Possess / control TV set with intent another use install without a licence", + "welshTitle": "Meddu ar/mewn rheolaeth set deledu gan fwriadu i unigolyn arall ei ddefnyddio/osod heb drwydded", + "legislation": "Contrary to section 363(3)(b) and (4) of the Communications Act 2003.", + "welshLegislation": "Yn groes i adran 363(3)(b) a (4) Deddf Cyfathrebu 2003." + }, + "restrictFromCourtList": false + } + ], + "firstName": "Santiago", + "bailStatus": { + "id": "12e69486-4d01-3403-a50a-7419ca040635", + "code": "C", + "description": "Custody" + }, + "dateOfBirth": "1990-06-26", + "masterDefendantId": "6c069ee4-d338-488d-9da5-b8f31aad3a70", + "hearingLanguageNeeds": "ENGLISH", + "restrictFromCourtList": false, + "courtProceedingsInitiated": "2025-07-31T10:07:51.148Z" + } + ], + "shadowListed": false, + "caseIdentifier": { + "authorityId": "bdc190e7-c939-37ca-be4b-9f615d6ef40e", + "authorityCode": "DERPF", + "caseReference": "28DI1953715" + }, + "restrictFromCourtList": false + } + ], + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "isSlotsBooked": false, + "nonDefaultDays": [ + { + "roomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "duration": 20, + "startTime": "2025-07-31T22:30:00.000Z", + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26" + } + ], + "nonSittingDays": [], + "hearingLanguage": "ENGLISH", + "estimatedMinutes": 20, + "jurisdictionType": "MAGISTRATES", + "courtApplications": [], + "courtCentreDetails": { + "id": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "defaultDuration": 420, + "defaultStartTime": "10:00:00" + }, + "isGroupProceedings": false, + "numberOfGroupCases": 1, + "sendNotificationToParties": false + } + ] +}% \ No newline at end of file