Skip to content

Commit 82d9ec0

Browse files
committed
Merge branch 'main' into NIAD-3157
2 parents 61786b1 + 36763e4 commit 82d9ec0

File tree

50 files changed

+23510
-185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+23510
-185
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
### Added
1010
* The GP2GP Adaptor now adds the EhrComposition / confidentialityCode field when Encounter.meta.security contains NOPAT security entry
1111
* The GP2GP Adaptor now populates the ObservationStatement / confidentialityCode field when the .meta.security field of an Uncategorised Data Observation contains NOPAT
12+
* When List.meta.security field contains NOPAT, the GP2GP Adaptor will now populate the CompoundStatement.confidentialityCode
13+
1214

1315
## [2.4.0] - 2025-04-02
1416

docker/docker-compose-transform-tool.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
services:
22
mongodb:
3-
image: mongo:3.6.23
3+
image: mongo:4.0.28
44
ports:
55
- "27017:27017"
66

e2e-tests/build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ dependencies {
1616
implementation 'org.apache.qpid:qpid-jms-client:2.7.0'
1717
implementation "org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1.1"
1818
implementation 'org.mongodb:mongo-java-driver:3.12.14'
19-
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.18.3'
20-
testImplementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.3'
21-
testImplementation 'commons-io:commons-io:2.18.0'
19+
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.19.0'
20+
testImplementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.19.0'
21+
testImplementation 'commons-io:commons-io:2.19.0'
2222
testImplementation 'org.awaitility:awaitility:4.3.0'
2323
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.4'
2424
testImplementation "org.assertj:assertj-core:3.27.3"
2525
testImplementation 'ch.qos.logback:logback-classic:1.5.18'
2626
testImplementation 'org.xmlunit:xmlunit-assertj3:2.10.0'
27-
testImplementation 'org.apache.httpcomponents.client5:httpclient5:5.4.3'
27+
testImplementation 'org.apache.httpcomponents.client5:httpclient5:5.4.4'
2828

2929
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.4'
3030
}

e2e-tests/src/test/java/uk/nhs/adaptors/gp2gp/e2e/EhrExtractTest.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,12 @@ public class EhrExtractTest {
100100
private static final String ACK_TO_REQUESTER = "ackToRequester";
101101
private static final String ACK_TO_PENDING = "ackPending";
102102
private static final String NACK_CODE_FAILED_TO_GENERATE_EHR = "10";
103-
private final static String NACK_CODE_REQUEST_NOT_WELL_FORMED = "18";
104-
private final static String NACK_CODE_PATIENT_NOT_FOUND = "06";
105-
private final static String NACK_CODE_INVALID = "19";
106-
private final static String NACK_CODE_GP_CONNECT_ERROR = "20";
107-
private final static String NACK_CODE_NO_RELATIONSHIP = "19";
108-
private final static String NACK_MESSAGE_REQUEST_NOT_WELL_FORMED = "An error occurred processing the initial EHR request";
109-
private final static String NACK_MESSAGE_NOT_FOUND = "Patient not at surgery.";
103+
private static final String NACK_CODE_REQUEST_NOT_WELL_FORMED = "18";
104+
private static final String NACK_CODE_PATIENT_NOT_FOUND = "06";
105+
private static final String NACK_CODE_INVALID = "19";
106+
private static final String NACK_CODE_GP_CONNECT_ERROR = "20";
107+
private static final String NACK_CODE_NO_RELATIONSHIP = "19";
108+
private static final String NACK_MESSAGE_NOT_FOUND = "Patient not at surgery.";
110109

111110
private static final CharSequence XML_NAMESPACE = "/urn:hl7-org:v3:";
112111
private static final String DOCUMENT_REFERENCE_XPATH_TEMPLATE = "/RCMR_IN030000UK06/ControlActEvent/subject/EhrExtract/component/ehrFolder/component/ehrComposition/component/NarrativeStatement/reference/referredToExternalDocument/text/reference[@value='cid:%s']";
@@ -311,7 +310,7 @@ public void When_ExtractRequestReceivedForPatientWithNoDocs_Expect_DatabaseToBeU
311310

312311
var documentList = ehrExtractStatus.get(GPC_ACCESS_DOCUMENT, Document.class).get("documents", Collections.emptyList());
313312

314-
assertThat(documentList.size()).isEqualTo(1); // large ehr as a document
313+
assertThat(documentList).hasSize(1); // large ehr as a document
315314

316315
var ackToPending = ehrExtractStatus.get(ACK_TO_PENDING, Document.class);
317316
assertThatAcknowledgementPending(ackToPending, ACCEPTED_ACKNOWLEDGEMENT_TYPE_CODE);
@@ -321,7 +320,7 @@ public void When_ExtractRequestReceivedForPatientWithNoDocs_Expect_DatabaseToBeU
321320
assertThat(mhsMockRequests).hasSize(3);
322321
var ehrExtractMhsRequest = mhsMockRequests.get(0);
323322

324-
assertThat(ehrExtractMhsRequest.getAttachments()).hasSize(0);
323+
assertThat(ehrExtractMhsRequest.getAttachments()).isEmpty();
325324
assertThat(ehrExtractMhsRequest.getExternalAttachments()).hasSize(1);
326325

327326
var externalAttachment = ehrExtractMhsRequest.getExternalAttachments().get(0);
@@ -670,15 +669,8 @@ private void assertEhrStatusHasPlaceholders(EhrStatus ehrStatus) {
670669
.filter(status -> status.getFileStatus().equals(PLACEHOLDER))
671670
.collect(Collectors.toList());
672671

673-
boolean hasAbsentAttachmentInFilename = placeholders.stream()
674-
.allMatch(status -> status.getFileName().startsWith("AbsentAttachment"));
675-
676-
boolean hasPlainTextSuffix = placeholders.stream()
677-
.allMatch(status -> status.getFileName().endsWith(".txt"));
678-
679-
assertThat(placeholders.isEmpty())
680-
.as("Migration should have placeholders")
681-
.isFalse();
672+
assertThat(placeholders).isNotEmpty()
673+
.as("Migration should have placeholders");
682674

683675
// TODO: NIAD-2394 - These assertions can be used to ensure AbsentAttachment is appended to a placeholders filename and there is a plain text suffix
684676

mock-mhs-adaptor/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
plugins {
2-
id 'org.springframework.boot' version '3.4.4'
2+
id 'org.springframework.boot' version '3.4.5'
33
id 'io.spring.dependency-management' version '1.1.7'
44
id 'java'
55
id "io.freefair.lombok" version "8.13.1"

service/build.gradle

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
plugins {
2-
id 'org.springframework.boot' version '3.4.3'
2+
id 'org.springframework.boot' version '3.4.5'
33
id 'io.spring.dependency-management' version '1.1.7'
44
id 'java'
55
id "checkstyle"
6-
id "com.github.spotbugs" version "6.1.6"
6+
id "com.github.spotbugs" version "6.1.7"
77
id "io.freefair.lombok" version "8.13.1"
88
id 'jacoco'
99
id 'org.sonarqube' version '6.1.0.5360'
@@ -50,7 +50,7 @@ dependencies {
5050
implementation 'org.springframework.boot:spring-boot-starter-logging'
5151

5252
// Infrastructure
53-
implementation 'software.amazon.awssdk:s3:2.31.16'
53+
implementation 'software.amazon.awssdk:s3:2.31.40'
5454
implementation ('com.azure:azure-storage-blob:12.30.0')
5555
implementation 'org.apache.qpid:qpid-jms-client:2.7.0'
5656

@@ -67,8 +67,8 @@ dependencies {
6767
testImplementation 'org.springframework.boot:spring-boot-starter-test'
6868
testImplementation "org.assertj:assertj-core:3.27.3"
6969
testImplementation 'org.testcontainers:testcontainers:1.20.6'
70-
testImplementation 'org.awaitility:awaitility:4.2.2'
71-
testImplementation 'org.wiremock:wiremock-standalone:3.12.1'
70+
testImplementation 'org.awaitility:awaitility:4.3.0'
71+
testImplementation 'org.wiremock:wiremock-standalone:3.13.0'
7272
testImplementation 'com.squareup.okhttp3:okhttp:4.12.0'
7373
testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'
7474
testImplementation 'io.findify:s3mock_2.13:0.2.6'

service/src/intTest/java/uk/nhs/adaptors/gp2gp/ehr/EhrExtractStatusServiceIT.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import uk.nhs.adaptors.gp2gp.ehr.exception.EhrExtractException;
4040
import uk.nhs.adaptors.gp2gp.ehr.model.EhrExtractStatus;
4141
import uk.nhs.adaptors.gp2gp.ehr.scheduling.EhrExtractTimeoutScheduler;
42-
import uk.nhs.adaptors.gp2gp.ehr.utils.ErrorDetail;
4342
import uk.nhs.adaptors.gp2gp.gpc.GetGpcDocumentTaskDefinition;
4443
import uk.nhs.adaptors.gp2gp.testcontainers.MongoDBExtension;
4544

@@ -54,7 +53,6 @@ public class EhrExtractStatusServiceIT {
5453
private static final int DEFAULT_CONTENT_LENGTH = 244;
5554
private static final String CONTENT_TYPE_MSWORD = "application/msword";
5655
public static final String JSON_SUFFIX = ".json";
57-
private static final ErrorDetail ACK_TIMEOUT_ERROR = ErrorDetail.ACK_TIMEOUT;
5856

5957
@Autowired
6058
private EhrExtractStatusService ehrExtractStatusService;

service/src/intTest/java/uk/nhs/adaptors/gp2gp/ehr/SendEhrExtractCoreComponentTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ public void When_ExtractCoreWithLargeMessage_Expect_MhsRequestBuilderCalledWithA
244244
.description(
245245
OutboundMessage.AttachmentDescription.builder()
246246
.fileName(GpcFilenameUtils.generateLargeExrExtractFilename(COMPRESSED_EHR_EXTRACT_DOCUMENT_ID))
247-
.contentType("text/xml")
247+
.contentType(TEXT_XML_CONTENT_TYPE)
248248
.length(COMPRESSED_LARGE_PAYLOAD.length())
249249
.compressed(true)
250250
.largeAttachment(true)
@@ -280,7 +280,7 @@ public void When_ExtractCoreWithLargeMessage_Expect_CompressedEhrExtractUploaded
280280
OutboundMessage.builder()
281281
.payload("<COPC />")
282282
.attachments(List.of(OutboundMessage.Attachment.builder()
283-
.contentType("text/xml")
283+
.contentType(TEXT_XML_CONTENT_TYPE)
284284
.isBase64(true)
285285
.description(COMPRESSED_EHR_EXTRACT_DOCUMENT_ID)
286286
.payload(COMPRESSED_LARGE_PAYLOAD)

service/src/intTest/java/uk/nhs/adaptors/gp2gp/gpc/GetGpcDocumentComponentTest.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@
77
import static org.mockito.Mockito.atMostOnce;
88
import static org.mockito.Mockito.times;
99
import static org.mockito.Mockito.verify;
10-
1110
import static uk.nhs.adaptors.gp2gp.ehr.EhrStatusConstants.CONVERSATION_ID;
1211
import static uk.nhs.adaptors.gp2gp.ehr.EhrStatusConstants.DOCUMENT_ID;
13-
1412
import java.io.IOException;
1513
import java.io.InputStreamReader;
1614
import java.util.List;
1715
import java.util.UUID;
1816

19-
import org.hl7.fhir.dstu3.model.OperationOutcome;
2017
import org.junit.jupiter.api.Test;
2118
import org.junit.jupiter.api.extension.ExtendWith;
2219
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,12 +38,10 @@
4138
@ExtendWith({SpringExtension.class, MongoDBExtension.class, ActiveMQExtension.class})
4239
@SpringBootTest
4340
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
44-
public class GetGpcDocumentComponentTest extends BaseTaskTest {
45-
private static final String NO_RECORD_FOUND = "NO_RECORD_FOUND";
41+
class GetGpcDocumentComponentTest extends BaseTaskTest {
4642
private static final String NO_RECORD_FOUND_STRING = "No Record Found";
4743
private static final String ODS_CODE_PLACEHOLDER = "@ODS_CODE@";
48-
private static final String EXPECTED_DOCUMENT_JSON_FILENAME =
49-
CONVERSATION_ID.concat("/").concat(DOCUMENT_ID).concat(".json");
44+
private static final String EXPECTED_DOCUMENT_JSON_FILENAME = CONVERSATION_ID.concat("/").concat(DOCUMENT_ID).concat(".json");
5045
private static final String DOCUMENT_BINARY_ENDPOINT = "/documents/fhir/Binary/";
5146

5247
@Autowired
@@ -158,7 +153,7 @@ public void When_AccessDocumentNotFoundError_Expect_EhrStatusUpdatedAndAbsentAtt
158153
assertThat(gpcDocuments.get(0).getAccessedAt()).isNotNull();
159154
assertThat(gpcDocuments.get(0).getObjectName()).isEqualTo(absentAttachmentFilename);
160155
assertThat(gpcDocuments.get(0).getMessageId()).isEqualTo(documentId);
161-
assertThat(gpcDocuments.get(0).getGpConnectErrorMessage()).isEqualTo("No Record Found");
156+
assertThat(gpcDocuments.get(0).getGpConnectErrorMessage()).isEqualTo(NO_RECORD_FOUND_STRING);
162157

163158
assertDoesNotThrow(() -> storageConnector.downloadFromStorage(absentAttachmentFilename));
164159

@@ -209,14 +204,6 @@ private List<EhrExtractStatus.GpcDocument> prepareDocuments() {
209204
.build());
210205
}
211206

212-
private void assertOperationOutcome(Exception exception) {
213-
var operationOutcomeString = exception.getMessage().replace("The following error occurred during GPC request: ", "");
214-
var operationOutcome = FHIR_PARSE_SERVICE.parseResource(operationOutcomeString, OperationOutcome.class).getIssueFirstRep();
215-
var coding = operationOutcome.getDetails().getCodingFirstRep();
216-
assertThat(coding.getCode()).isEqualTo(NO_RECORD_FOUND);
217-
assertThat(coding.getDisplay()).isEqualTo(NO_RECORD_FOUND_STRING);
218-
}
219-
220207
private String buildDocumentUrl(String documentId, String odsCode) {
221208
return configuration.getUrl().replace(ODS_CODE_PLACEHOLDER, odsCode) + DOCUMENT_BINARY_ENDPOINT + documentId;
222209
}

service/src/intTest/java/uk/nhs/adaptors/gp2gp/gpc/GpcWebClientTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class GpcWebClientTest {
5151
private static final String TASK_ID = "testTaskId";
5252
private static final String TEST_BODY = "Test Body";
5353
private static final int FOUR = 4;
54+
public static final String RETRIES_EXHAUSTED_3_3 = "Retries exhausted: 3/3";
5455

5556
private static MockWebServer mockWebServer;
5657

@@ -131,7 +132,7 @@ public void When_GetDocumentRecord_With_HttpStatus5xx_Expect_RetryExceptionWithG
131132

132133
assertThatThrownBy(() -> gpcWebClient.getDocumentRecord(taskDefinition))
133134
.isInstanceOf(RetryLimitReachedException.class)
134-
.hasMessage("Retries exhausted: 3/3")
135+
.hasMessage(RETRIES_EXHAUSTED_3_3)
135136
.hasRootCauseInstanceOf(GpcServerErrorException.class)
136137
.hasRootCauseMessage("The following error occurred during GPC request: " + TEST_BODY);
137138

@@ -150,7 +151,7 @@ public void When_GetDocumentRecord_With_HttpStatus5xxAndNoBody_Expect_Alternativ
150151

151152
assertThatThrownBy(() -> gpcWebClient.getDocumentRecord(taskDefinition))
152153
.isInstanceOf(RetryLimitReachedException.class)
153-
.hasMessage("Retries exhausted: 3/3")
154+
.hasMessage(RETRIES_EXHAUSTED_3_3)
154155
.hasRootCauseInstanceOf(GpcServerErrorException.class)
155156
.hasRootCauseMessage("The following error occurred during GPC request: 500 INTERNAL_SERVER_ERROR");
156157

@@ -170,7 +171,7 @@ public void When_GetDocumentRecord_With_NoResponse_Expect_RetryExceptionWithTime
170171
assertThatThrownBy(() -> gpcWebClient.getDocumentRecord(taskDefinition))
171172
.isInstanceOf(RetryLimitReachedException.class)
172173
.hasRootCauseInstanceOf(TimeoutException.class)
173-
.hasMessage("Retries exhausted: 3/3");
174+
.hasMessage(RETRIES_EXHAUSTED_3_3);
174175

175176
assertThat(mockWebServer.getRequestCount()).isEqualTo(FOUR);
176177
verify(gpcTokenBuilder, times(FOUR)).buildToken(taskDefinition.getFromOdsCode());
@@ -211,7 +212,7 @@ public void When_GetStructuredRecord_With_NoResponse_Expect_RetryExceptionWithTi
211212
assertThatThrownBy(() -> gpcWebClient.getStructuredRecord(taskDefinition))
212213
.isInstanceOf(RetryLimitReachedException.class)
213214
.hasRootCauseInstanceOf(TimeoutException.class)
214-
.hasMessage("Retries exhausted: 3/3");
215+
.hasMessage(RETRIES_EXHAUSTED_3_3);
215216

216217
assertThat(mockWebServer.getRequestCount()).isEqualTo(FOUR);
217218
verify(gpcTokenBuilder, times(FOUR)).buildToken(taskDefinition.getFromOdsCode());
@@ -227,7 +228,7 @@ public void When_GetStructuredRecord_With_HttpStatus5xx_Expect_RetryWithGpcServe
227228

228229
assertThatThrownBy(() -> gpcWebClient.getStructuredRecord(taskDefinition))
229230
.isInstanceOf(RetryLimitReachedException.class)
230-
.hasMessage("Retries exhausted: 3/3")
231+
.hasMessage(RETRIES_EXHAUSTED_3_3)
231232
.hasRootCauseInstanceOf(GpcServerErrorException.class)
232233
.hasRootCauseMessage("The following error occurred during GPC request: " + TEST_BODY);
233234

0 commit comments

Comments
 (0)