Skip to content

Commit e1b6122

Browse files
authored
Merge pull request #539 from hmcts/fix-data-loss-issue
Fix data loss bug in hearing service due to shared mutable field
2 parents 4d36e7a + 719223e commit e1b6122

File tree

3 files changed

+51
-82
lines changed

3 files changed

+51
-82
lines changed

src/main/java/uk/gov/hmcts/reform/hmc/api/services/HearingsServiceImpl.java

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@
33
import com.nimbusds.oauth2.sdk.util.CollectionUtils;
44
import feign.FeignException;
55
import lombok.RequiredArgsConstructor;
6-
import org.slf4j.Logger;
7-
import org.slf4j.LoggerFactory;
8-
import org.springframework.beans.factory.annotation.Autowired;
6+
import lombok.extern.slf4j.Slf4j;
97
import org.springframework.beans.factory.annotation.Value;
108
import org.springframework.stereotype.Service;
119
import org.springframework.web.client.HttpClientErrorException;
1210
import org.springframework.web.client.HttpServerErrorException;
13-
import org.springframework.web.client.RestTemplate;
1411
import uk.gov.hmcts.reform.authorisation.generators.AuthTokenGenerator;
1512
import uk.gov.hmcts.reform.hmc.api.config.IdamTokenGenerator;
1613
import uk.gov.hmcts.reform.hmc.api.mapper.AutomatedHearingTransformer;
@@ -39,31 +36,15 @@
3936

4037
@Service
4138
@RequiredArgsConstructor
42-
@SuppressWarnings("unchecked")
39+
@Slf4j
4340
public class HearingsServiceImpl implements HearingsService {
4441

45-
public static final String HEARING_API_CALL_HTTP_CLIENT_ERROR_EXCEPTION = "Hearing api call HttpClientError exception {}";
46-
public static final String HEARING_API_CALL_FEIGN_EXCEPTION = "Hearing api call Feign exception {}";
47-
public static final String HEARING_API_CALL_EXCEPTION_EXCEPTION = "Hearing api call Exception exception {}";
48-
private static Logger log = LoggerFactory.getLogger(HearingsServiceImpl.class);
49-
5042
@Value("${ccd.ui.url}")
5143
private String ccdBaseUrl;
5244

5345
@Value("${hearing.specialCharacters}")
5446
private String specialCharacters;
5547

56-
@Autowired AuthTokenGenerator authTokenGenerator;
57-
58-
@Autowired IdamTokenGenerator idamTokenGenerator;
59-
60-
@Autowired RefDataService refDataService;
61-
62-
@Autowired RefDataJudicialService refDataJudicialService;
63-
64-
@Autowired HearingApiClient hearingApiClient;
65-
RestTemplate restTemplate = new RestTemplate();
66-
6748
@Value("${hearing_component.api.url}")
6849
private String basePath;
6950

@@ -73,7 +54,11 @@ public class HearingsServiceImpl implements HearingsService {
7354
@Value("#{'${hearing_component.futureHearingStatus}'.split(',')}")
7455
private List<String> futureHearingStatusList;
7556

76-
private Hearings hearingDetails;
57+
private final AuthTokenGenerator authTokenGenerator;
58+
private final IdamTokenGenerator idamTokenGenerator;
59+
private final RefDataService refDataService;
60+
private final RefDataJudicialService refDataJudicialService;
61+
private final HearingApiClient hearingApiClient;
7762

7863
/**
7964
* This method will fetch all the hearings which belongs to a particular caseRefNumber.
@@ -198,8 +183,7 @@ public List<Hearings> getHearingsByListOfCaseIds(
198183
ROLE_ASSIGNMENT_ATTRIBUTE_CASE_TYPE);
199184
for (var hearing : hearingDetailsList) {
200185
try {
201-
hearingDetails = hearing;
202-
List<CaseHearing> filteredHearings = hearingDetails.getCaseHearings();
186+
List<CaseHearing> filteredHearings = hearing.getCaseHearings();
203187
log.info("Excluded hearing statuses {}", hearingStatesToBeExcluded);
204188
if (CollectionUtils.isNotEmpty(hearingStatesToBeExcluded)) {
205189
filteredHearings = filteredHearings.stream()
@@ -211,8 +195,8 @@ public List<Hearings> getHearingsByListOfCaseIds(
211195
Hearings filteredCaseHearingsWithCount =
212196
Hearings.hearingsWith()
213197
.caseHearings(filteredHearings)
214-
.caseRef(hearingDetails.getCaseRef())
215-
.hmctsServiceCode(hearingDetails.getHmctsServiceCode())
198+
.caseRef(hearing.getCaseRef())
199+
.hmctsServiceCode(hearing.getHmctsServiceCode())
216200
.build();
217201
casesWithHearings.add(filteredCaseHearingsWithCount);
218202
} catch (HttpClientErrorException | HttpServerErrorException exception) {
@@ -228,7 +212,7 @@ public List<Hearings> getHearingsByListOfCaseIds(
228212
if (!casesWithHearings.isEmpty()) {
229213
List<CourtDetail> allVenues =
230214
refDataService.getCourtDetailsByServiceCode(
231-
hearingDetails.getHmctsServiceCode());
215+
hearingDetailsList.get(0).getHmctsServiceCode());
232216

233217
integrateVenueDetailsForCaseId(allVenues, casesWithHearings, caseIdWithRegionIdMap);
234218
}
@@ -259,9 +243,8 @@ public List<Hearings> getHearingsByListOfCaseIdsWithoutCourtVenueDetails(
259243
log.info("fis processing {}",hearing.getCaseRef());
260244
try {
261245
log.info("try block hit");
262-
hearingDetails = hearing;
263246
List<CaseHearing> filteredHearings =
264-
hearingDetails.getCaseHearings().stream()
247+
hearing.getCaseHearings().stream()
265248
.filter(
266249
eachHearing ->
267250
eachHearing.getHmcStatus().equals(LISTED)
@@ -272,12 +255,12 @@ public List<Hearings> getHearingsByListOfCaseIdsWithoutCourtVenueDetails(
272255
.getHmcStatus()
273256
.equals(COMPLETED))
274257
.toList();
275-
log.info("checking hearings for case id {}", hearingDetails.getCaseRef());
258+
log.info("checking hearings for case id {}", hearing.getCaseRef());
276259
Hearings filteredCaseHearingsWithCount =
277260
Hearings.hearingsWith()
278261
.caseHearings(filteredHearings)
279-
.caseRef(hearingDetails.getCaseRef())
280-
.hmctsServiceCode(hearingDetails.getHmctsServiceCode())
262+
.caseRef(hearing.getCaseRef())
263+
.hmctsServiceCode(hearing.getHmctsServiceCode())
281264
.build();
282265
log.info("adding hearing with case id {}", filteredCaseHearingsWithCount.getCaseRef());
283266
casesWithHearings.add(filteredCaseHearingsWithCount);
@@ -306,15 +289,8 @@ public Map<String, List<String>> getHearingsListedForCurrentDateByListOfCaseIdsW
306289
try {
307290
hearingDetailsList.addAll(hearingApiClient.getListOfHearingDetails(userToken, s2sToken, listOfCaseIds,
308291
ROLE_ASSIGNMENT_ATTRIBUTE_CASE_TYPE));
309-
} catch (HttpClientErrorException | HttpServerErrorException exception) {
310-
log.error(
311-
HEARING_API_CALL_HTTP_CLIENT_ERROR_EXCEPTION,
312-
exception.getMessage()
313-
);
314-
} catch (FeignException exception) {
315-
log.error(HEARING_API_CALL_FEIGN_EXCEPTION, exception.getMessage());
316292
} catch (Exception exception) {
317-
log.error(HEARING_API_CALL_EXCEPTION_EXCEPTION, exception.getMessage());
293+
log.error("Hearing api call Exception exception {}", exception.getMessage());
318294
}
319295
Map<String, List<String>> caseIdHearingIdMap = new HashMap<>();
320296
if (CollectionUtils.isNotEmpty(hearingDetailsList)) {
@@ -461,7 +437,7 @@ public Hearings getFutureHearings(String caseReference) {
461437
final String s2sToken = authTokenGenerator.generate();
462438
Hearings futureHearingsResponse = null;
463439
try {
464-
hearingDetails = hearingApiClient.getHearingDetails(userToken, s2sToken, caseReference);
440+
Hearings hearingDetails = hearingApiClient.getHearingDetails(userToken, s2sToken, caseReference);
465441

466442
final List<String> hearingStatuses =
467443
futureHearingStatusList.stream().map(String::trim).toList();

src/test/java/uk/gov/hmcts/reform/hmc/api/services/AutomateHearingServiceTest.java

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
package uk.gov.hmcts.reform.hmc.api.services;
22

3-
4-
import org.json.simple.parser.ParseException;
53
import org.junit.jupiter.api.BeforeEach;
64
import org.junit.jupiter.api.Test;
7-
import org.junit.jupiter.api.extension.ExtendWith;
8-
import org.mockito.InjectMocks;
9-
import org.mockito.Mock;
10-
import org.mockito.junit.jupiter.MockitoExtension;
5+
import org.springframework.beans.factory.annotation.Autowired;
116
import org.springframework.boot.test.context.SpringBootTest;
7+
import org.springframework.boot.test.mock.mockito.MockBean;
128
import org.springframework.context.annotation.PropertySource;
139
import org.springframework.test.context.ActiveProfiles;
1410
import uk.gov.hmcts.reform.authorisation.generators.AuthTokenGenerator;
@@ -34,7 +30,6 @@
3430
import uk.gov.hmcts.reform.hmc.api.model.common.dynamic.DynamicListElement;
3531
import uk.gov.hmcts.reform.hmc.api.model.response.HearingResponse;
3632

37-
import java.io.IOException;
3833
import java.time.LocalDate;
3934
import java.util.ArrayList;
4035
import java.util.List;
@@ -47,19 +42,21 @@
4742
import static uk.gov.hmcts.reform.hmc.api.utils.Constants.NO;
4843

4944
@SpringBootTest
50-
@ExtendWith({MockitoExtension.class})
5145
@ActiveProfiles("test")
5246
@PropertySource("classpath:application.yaml")
5347
class AutomateHearingServiceTest {
5448

55-
@InjectMocks HearingsServiceImpl hearingsService;
56-
57-
@Mock private AuthTokenGenerator authTokenGenerator;
49+
@Autowired
50+
private HearingsServiceImpl hearingsService;
5851

59-
@Mock private IdamTokenGenerator idamTokenGenerator;
52+
@MockBean
53+
private AuthTokenGenerator authTokenGenerator;
6054

55+
@MockBean
56+
private IdamTokenGenerator idamTokenGenerator;
6157

62-
@Mock private HearingApiClient hearingApiClient;
58+
@MockBean
59+
private HearingApiClient hearingApiClient;
6360

6461
private static final String TEST_UUID = "00000000-0000-0000-0000-000000000000";
6562

@@ -156,7 +153,7 @@ void setup() {
156153
}
157154

158155
@Test
159-
void shouldReturnAutomateHearingTestC100() throws IOException, ParseException {
156+
void shouldReturnAutomateHearingTestC100() {
160157

161158
HearingResponse response = HearingResponse.builder()
162159
.hearingRequestID("123")
@@ -243,7 +240,7 @@ private void getHearingData(HearingData.HearingDataBuilder dynamicList, String y
243240
}
244241

245242
@Test
246-
void shouldReturnAutomateHearingTestC100ForParties() throws IOException, ParseException {
243+
void shouldReturnAutomateHearingTestC100ForParties() {
247244

248245
HearingResponse response = HearingResponse.builder()
249246
.hearingRequestID("123")
@@ -304,7 +301,7 @@ void shouldReturnAutomateHearingTestC100ForParties() throws IOException, ParseEx
304301
}
305302

306303
@Test
307-
void shouldReturnAutomateHearingTestF401() throws IOException, ParseException {
304+
void shouldReturnAutomateHearingTestF401() {
308305

309306
HearingResponse response = HearingResponse.builder()
310307
.hearingRequestID("123")
@@ -363,7 +360,7 @@ void shouldReturnAutomateHearingTestF401() throws IOException, ParseException {
363360

364361

365362
@Test
366-
void shouldReturnAutomateHearingTestF401ForParties() throws IOException, ParseException {
363+
void shouldReturnAutomateHearingTestF401ForParties() {
367364

368365
HearingResponse response = HearingResponse.builder()
369366
.hearingRequestID("123")
@@ -429,7 +426,7 @@ public static <T> Element<T> element(T element) {
429426

430427

431428
@Test
432-
void shouldReturnAutomateHearingsByExceptionTest() throws IOException, ParseException {
429+
void shouldReturnAutomateHearingsByExceptionTest() {
433430
when(authTokenGenerator.generate()).thenReturn(SERVICE_AUTH_TOKEN);
434431
when(idamTokenGenerator.generateIdamTokenForHearingCftData()).thenReturn(AUTHORIZATION_TOKEN);
435432

@@ -475,6 +472,4 @@ void shouldReturnAutomateHearingsByExceptionTest() throws IOException, ParseExce
475472
assertThrows(NullPointerException.class, () -> hearingsService.createAutomatedHearings(caseData));
476473
}
477474

478-
479-
480475
}

src/test/java/uk/gov/hmcts/reform/hmc/api/services/HearingsServiceTest.java

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,17 @@
1414
import feign.FeignException;
1515
import feign.Request;
1616
import feign.Response;
17-
import java.io.IOException;
1817
import java.time.LocalDateTime;
1918
import java.util.ArrayList;
2019
import java.util.HashMap;
2120
import java.util.List;
2221
import java.util.Map;
23-
import org.json.simple.parser.ParseException;
2422
import org.junit.jupiter.api.Assertions;
2523
import org.junit.jupiter.api.Test;
26-
import org.junit.jupiter.api.extension.ExtendWith;
27-
import org.mockito.InjectMocks;
28-
import org.mockito.Mock;
29-
import org.mockito.junit.jupiter.MockitoExtension;
24+
import org.springframework.beans.factory.annotation.Autowired;
3025
import org.springframework.beans.factory.annotation.Value;
3126
import org.springframework.boot.test.context.SpringBootTest;
27+
import org.springframework.boot.test.mock.mockito.MockBean;
3228
import org.springframework.context.annotation.PropertySource;
3329
import org.springframework.http.HttpStatus;
3430
import org.springframework.test.context.ActiveProfiles;
@@ -44,28 +40,33 @@
4440
import uk.gov.hmcts.reform.hmc.api.model.response.JudgeDetail;
4541

4642
@SpringBootTest
47-
@ExtendWith({MockitoExtension.class})
4843
@ActiveProfiles("test")
4944
@PropertySource("classpath:application.yaml")
5045
class HearingsServiceTest {
5146

5247
@Value("#{'${hearing_component.futureHearingStatus}'.split(',')}")
5348
private List<String> futureHearingStatusList;
5449

55-
@InjectMocks HearingsServiceImpl hearingsService;
50+
@Autowired
51+
private HearingsServiceImpl hearingsService;
5652

57-
@Mock private RefDataServiceImpl refDataService;
53+
@MockBean
54+
private HearingApiClient hearingApiClient;
5855

59-
@Mock private AuthTokenGenerator authTokenGenerator;
56+
@MockBean
57+
private IdamTokenGenerator idamTokenGenerator;
6058

61-
@Mock private IdamTokenGenerator idamTokenGenerator;
59+
@MockBean
60+
private AuthTokenGenerator authTokenGenerator;
6261

63-
@Mock private HearingApiClient hearingApiClient;
62+
@MockBean
63+
private RefDataServiceImpl refDataService;
6464

65-
@Mock RefDataJudicialService refDataJudicialService;
65+
@MockBean
66+
private RefDataJudicialService refDataJudicialService;
6667

6768
@Test
68-
void shouldReturnCtfHearingsAuthExceptionTest() throws IOException, ParseException {
69+
void shouldReturnCtfHearingsAuthExceptionTest() {
6970
Hearings caseHearings =
7071
Hearings.hearingsWith()
7172
.caseRef("123")
@@ -85,7 +86,7 @@ void shouldReturnCtfHearingsAuthExceptionTest() throws IOException, ParseExcepti
8586
}
8687

8788
@Test
88-
void shouldReturnHearingsByCaseRefNoTest() throws IOException, ParseException {
89+
void shouldReturnHearingsByCaseRefNoTest() {
8990

9091
when(idamTokenGenerator.generateIdamTokenForHearingCftData()).thenReturn("MOCK_AUTH_TOKEN");
9192
when(authTokenGenerator.generate()).thenReturn("MOCK_S2S_TOKEN");
@@ -452,8 +453,7 @@ void shouldReturnAllFutureHearingsByCaseRefNoTest() {
452453
}
453454

454455
@Test
455-
void shouldReturnAllFutureHearingsByCaseRefNoFeignExceptionTest()
456-
throws IOException, ParseException {
456+
void shouldReturnAllFutureHearingsByCaseRefNoFeignExceptionTest() {
457457
when(authTokenGenerator.generate()).thenReturn("MOCK_S2S_TOKEN");
458458
when(idamTokenGenerator.generateIdamTokenForHearingCftData()).thenReturn("MOCK_AUTH_TOKEN");
459459
when(hearingApiClient.getHearingDetails(anyString(), any(), any()))
@@ -463,8 +463,7 @@ void shouldReturnAllFutureHearingsByCaseRefNoFeignExceptionTest()
463463
}
464464

465465
@Test
466-
void shouldReturnAllFutureHearingsByCaseRefNoAuthExceptionTest()
467-
throws IOException, ParseException {
466+
void shouldReturnAllFutureHearingsByCaseRefNoAuthExceptionTest() {
468467
when(authTokenGenerator.generate()).thenReturn("MOCK_S2S_TOKEN");
469468
when(idamTokenGenerator.generateIdamTokenForHearingCftData()).thenReturn("MOCK_AUTH_TOKEN");
470469
when(hearingApiClient.getHearingDetails(any(), any(), any()))
@@ -473,8 +472,7 @@ void shouldReturnAllFutureHearingsByCaseRefNoAuthExceptionTest()
473472
}
474473

475474
@Test
476-
void shouldReturnAllFutureHearingsByCaseRefNoExceptionTest()
477-
throws IOException, ParseException {
475+
void shouldReturnAllFutureHearingsByCaseRefNoExceptionTest() {
478476
when(authTokenGenerator.generate()).thenReturn("MOCK_S2S_TOKEN");
479477
when(idamTokenGenerator.generateIdamTokenForHearingCftData()).thenReturn("MOCK_AUTH_TOKEN");
480478
when(hearingApiClient.getHearingDetails(any(), any(), any()))

0 commit comments

Comments
 (0)