diff --git a/.github/workflows/base-java-service-jobs.yml b/.github/workflows/base-java-service-jobs.yml index 794e4053..6781b464 100644 --- a/.github/workflows/base-java-service-jobs.yml +++ b/.github/workflows/base-java-service-jobs.yml @@ -19,8 +19,7 @@ on: default: false java_version: type: string -# TODO PRM-711: Update to Java 25 once all services are compatible - default: "21" + default: "25" required: false image_prefix: type: string diff --git a/.github/workflows/full-deployment.yml b/.github/workflows/full-deployment.yml index 4f8b679a..9f2841d7 100644 --- a/.github/workflows/full-deployment.yml +++ b/.github/workflows/full-deployment.yml @@ -101,8 +101,6 @@ jobs: service: pds-adaptor environment: ${{ inputs.environment }} is_deployment: ${{ inputs.is_deployment }} - # TODO PRM-713 REMOVE THIS LINE SO IT TAKES THE DEFAULT - java_version: "11" ecr_alias: deductions/pds-adaptor secrets: inherit diff --git a/.github/workflows/service-ci.yml b/.github/workflows/service-ci.yml index 003b4b97..2c854f99 100644 --- a/.github/workflows/service-ci.yml +++ b/.github/workflows/service-ci.yml @@ -109,8 +109,6 @@ jobs: environment: dev is_deployment: ${{ github.ref == 'refs/heads/main' }} requires_localstack: true - # PRM-711: Remove the hardcoded java_versions once all services are compatible with Java 25 - java_version: "25" ecr_alias: deductions/nems-event-processor secrets: inherit @@ -124,7 +122,6 @@ jobs: environment: dev is_deployment: ${{ github.ref == 'refs/heads/main' }} requires_localstack: true - java_version: "25" ecr_alias: deductions/ehr-transfer-service secrets: inherit @@ -137,7 +134,6 @@ jobs: service: pds-adaptor environment: dev is_deployment: ${{ github.ref == 'refs/heads/main' }} - java_version: "25" ecr_alias: deductions/pds-adaptor secrets: inherit @@ -152,7 +148,6 @@ jobs: is_deployment: ${{ github.ref == 'refs/heads/main' }} requires_localstack: true image_prefix: repo/ - java_version: "25" ecr_alias: repo/re-registration-service secrets: inherit diff --git a/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsClientSpringConfiguration.java b/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsClientSpringConfiguration.java index 312dbb45..2144e47b 100644 --- a/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsClientSpringConfiguration.java +++ b/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsClientSpringConfiguration.java @@ -6,9 +6,6 @@ @Configuration public class SqsClientSpringConfiguration { - - - @Bean public SqsClient sqsClient() { return SqsClient.create(); diff --git a/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsListenerSpringConfiguration.java b/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsListenerSpringConfiguration.java index b79e2d5b..88a0ac3c 100644 --- a/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsListenerSpringConfiguration.java +++ b/services/ehr-transfer-service/src/main/java/uk/nhs/prm/repo/ehrtransferservice/config/SqsListenerSpringConfiguration.java @@ -57,11 +57,6 @@ public class SqsListenerSpringConfiguration { @Value("${aws.nackQueueName}") private String negativeAckQueueName; - @Bean - public SqsClient sqsClient() { - return SqsClient.create(); - } - @Bean public SQSConnection createConnection(SqsClient sqsClient) throws JMSException { SQSConnectionFactory connectionFactory = new SQSConnectionFactory(new ProviderConfiguration(), sqsClient); diff --git a/services/suspension-service/Dockerfile b/services/suspension-service/Dockerfile index ded9919c..748d52e9 100644 --- a/services/suspension-service/Dockerfile +++ b/services/suspension-service/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:21-jre-alpine-3.23 +FROM eclipse-temurin:25-jre-alpine-3.23 RUN apk update && \ apk -u list && \ diff --git a/services/suspension-service/build.gradle b/services/suspension-service/build.gradle index d903ae04..7e2c0680 100644 --- a/services/suspension-service/build.gradle +++ b/services/suspension-service/build.gradle @@ -1,15 +1,13 @@ plugins { - id 'org.springframework.boot' version '3.2.2' - id 'io.spring.dependency-management' version '1.1.4' + id 'org.springframework.boot' version '4.0.3' + id 'io.spring.dependency-management' version '1.1.7' id 'java' id 'jacoco' - id 'com.github.spotbugs' version '6.0.6' - id 'org.sonarqube' version '4.3.1.3277' + id 'org.sonarqube' version '7.2.2.6593' } group = 'uk.nhs.prm.repo' version = '0.0.1-SNAPSHOT' -sourceCompatibility = '21' configurations { compileOnly { @@ -21,61 +19,54 @@ repositories { mavenCentral() } -//Without this task two jars are built, the additional "-plain.jar" is not needed -// for more details refer to: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#packaging-executable.and-plain-archives -jar { - enabled = false +java { + toolchain { + languageVersion = JavaLanguageVersion.of(25) + } } dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-json' - - implementation 'org.yaml:snakeyaml:2.2' - implementation('io.netty:netty-buffer') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-codec') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-codec-http') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-codec-http2') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-common') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-handler') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-resolver') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-transport') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-transport-classes-epoll') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-transport-native-epoll') { version { strictly '4.1.104.Final' } } - implementation('io.netty:netty-transport-native-unix-common') { version { strictly '4.1.104.Final' } } - - implementation platform('software.amazon.awssdk:bom:2.18.41') + implementation 'org.springframework:spring-jms' + + implementation 'org.yaml:snakeyaml:2.5' + implementation('io.netty:netty-buffer') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-codec') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-codec-http') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-codec-http2') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-common') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-handler') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-resolver') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-transport') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-transport-classes-epoll') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-transport-native-epoll') { version { strictly '4.2.9.Final' } } + implementation('io.netty:netty-transport-native-unix-common') { version { strictly '4.2.9.Final' } } + + implementation platform('software.amazon.awssdk:bom:2.41.14') implementation 'software.amazon.awssdk:cloudwatch' implementation 'software.amazon.awssdk:sns' implementation 'software.amazon.awssdk:sqs' implementation 'software.amazon.awssdk:dynamodb' - // TODO: Once we upgrade amazon-sqs-java-messaging-lib to v2 we can remove aws-java-sdk-core and sqs. - implementation 'com.amazonaws:amazon-sqs-java-messaging-lib:1.1.2' - implementation 'com.amazonaws:aws-java-sdk-core:1.12.368' - implementation 'com.amazonaws:aws-java-sdk-sqs:1.12.368' - implementation 'com.google.code.gson:gson:2.10.1' - implementation 'com.google.guava:guava:33.0.0-jre' - implementation 'io.github.resilience4j:resilience4j-retry:1.7.1' - implementation 'org.springframework:spring-jms:5.3.19' - implementation 'com.github.spotbugs:spotbugs-annotations:4.8.3' - implementation 'org.apache.bcel:bcel:6.6.1' - // Explicit declaration to override outdated dependency on httpclient - outdated as of Spring Boot >3.0.0 - // TODO We plan to replace the HTTP calls on this service with Lambda calls soon, this can be removed at this point - implementation 'org.apache.httpcomponents.client5:httpclient5:5.3' - implementation 'commons-fileupload:commons-fileupload:1.5' - implementation 'net.logstash.logback:logstash-logback-encoder:7.0.1' - - compileOnly 'org.projectlombok:lombok:1.18.30' + implementation 'com.amazonaws:amazon-sqs-java-messaging-lib:2.1.4' + implementation 'com.google.code.gson:gson:2.13.2' + implementation 'com.google.guava:guava:33.5.0-jre' + implementation 'io.github.resilience4j:resilience4j-retry:2.3.0' + implementation 'org.apache.bcel:bcel:6.12.0' + implementation 'org.apache.httpcomponents.client5:httpclient5' + implementation 'commons-fileupload:commons-fileupload:1.6.0' + implementation 'net.logstash.logback:logstash-logback-encoder:9.0' + + compileOnly 'org.projectlombok:lombok:1.18.42' annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.awaitility:awaitility:4.2.0' + testImplementation 'org.awaitility:awaitility:4.3.0' testImplementation 'org.springframework.boot:spring-boot-test' testImplementation 'org.springframework.boot:spring-boot-test-autoconfigure' testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.boot:spring-boot-starter-aop' - testImplementation 'org.mockito:mockito-core:3.+' - testImplementation 'org.wiremock:wiremock-standalone:3.3.1' + testImplementation 'org.wiremock:wiremock-standalone:3.13.2' } test { @@ -132,39 +123,6 @@ jacocoTestCoverageVerification { } } -spotbugsMain { - ignoreFailures = true - reports { - html { - enabled = true - destination = file("$buildDir/reports/spotbugs/main/spotbugs.html") - stylesheet = 'fancy-hist.xsl' - } - } -} - -spotbugsTest { - ignoreFailures = true - reports { - html { - enabled = true - destination = file("$buildDir/reports/spotbugs/test/spotbugs.html") - stylesheet = 'fancy-hist.xsl' - } - } -} - -spotbugsIntegration { - ignoreFailures = true - reports { - html { - enabled = true - destination = file("$buildDir/reports/spotbugs/integration/spotbugs.html") - stylesheet = 'fancy-hist.xsl' - } - } -} - sonar { properties { property "sonar.projectKey", "NHSDigital_orphaned-record-continuity" diff --git a/services/suspension-service/docker-compose.localstack-local.yaml b/services/suspension-service/docker-compose.localstack-local.yaml index da1f35ea..1d11e6e6 100644 --- a/services/suspension-service/docker-compose.localstack-local.yaml +++ b/services/suspension-service/docker-compose.localstack-local.yaml @@ -1,7 +1,7 @@ services: localstack: container_name: "localstack-suspension-service" - image: localstack/localstack + image: localstack/localstack:4.14.0 ports: - "4566:4566" network_mode: bridge diff --git a/services/suspension-service/gradle/wrapper/gradle-wrapper.properties b/services/suspension-service/gradle/wrapper/gradle-wrapper.properties index a5952066..5dc98dbc 100644 --- a/services/suspension-service/gradle/wrapper/gradle-wrapper.properties +++ b/services/suspension-service/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/http/HttpClientTest.java b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/http/HttpClientTest.java index 57e1eb38..57fbe61f 100644 --- a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/http/HttpClientTest.java +++ b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/http/HttpClientTest.java @@ -31,6 +31,8 @@ public class HttpClientTest { @BeforeEach public void setUp() { wireMockServer = initializeWebServer(); + configureFor("localhost", wireMockServer.port()); + } @Test @@ -51,7 +53,7 @@ void shouldPerformPutWithAuthAndReturnBodyAndResponseCode() { "some request payload"); assertThat(responsePayload.getBody()).isEqualTo("some body"); - assertThat(responsePayload.getStatusCodeValue()).isEqualTo(203); + assertThat(responsePayload.getStatusCode().value()).isEqualTo(203); } @Test @@ -69,8 +71,7 @@ void shouldReturnResponseWithStatusCode() { "bob", "banana"); - assertThat(response.getStatusCodeValue()).isEqualTo(202); - } + assertThat(response.getStatusCode().value()).isEqualTo(202); } @Test diff --git a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/infra/LocalStackAwsConfig.java b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/infra/LocalStackAwsConfig.java index 3d33c7fc..7c6851d9 100644 --- a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/infra/LocalStackAwsConfig.java +++ b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/infra/LocalStackAwsConfig.java @@ -1,18 +1,11 @@ package uk.nhs.prm.repo.suspension.service.infra; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder; -import com.amazonaws.services.sqs.model.GetQueueAttributesResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; -import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; @@ -23,6 +16,10 @@ import software.amazon.awssdk.services.sns.model.CreateTopicRequest; import software.amazon.awssdk.services.sns.model.CreateTopicResponse; import software.amazon.awssdk.services.sns.model.SubscribeRequest; +import software.amazon.awssdk.services.sqs.SqsClient; +import software.amazon.awssdk.services.sqs.model.CreateQueueResponse; +import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; +import software.amazon.awssdk.services.sqs.model.QueueAttributeName; import jakarta.annotation.PostConstruct; import java.net.URI; @@ -31,12 +28,16 @@ import java.util.List; import java.util.Map; - @TestConfiguration public class LocalStackAwsConfig { + private static final Region LOCALSTACK_REGION = Region.EU_WEST_2; + + private static final StaticCredentialsProvider LOCALSTACK_CREDENTIALS = + StaticCredentialsProvider.create(AwsBasicCredentials.create("LSIA5678901234567890", "LSIA5678901234567890")); + @Autowired - private AmazonSQSAsync amazonSQSAsync; + private SqsClient sqsClient; @Autowired private SnsClient snsClient; @@ -75,10 +76,11 @@ public class LocalStackAwsConfig { private String activeSuspensionsQueueName; @Bean - public static AmazonSQSAsync amazonSQSAsync(@Value("${localstack.url}") String localstackUrl) { - return AmazonSQSAsyncClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("LSIA5678901234567890", "LSIA5678901234567890"))) - .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(localstackUrl, "eu-west-2")) + public static SqsClient sqsClient(@Value("${localstack.url}") String localstackUrl) { + return SqsClient.builder() + .endpointOverride(URI.create(localstackUrl)) + .region(LOCALSTACK_REGION) + .credentialsProvider(LOCALSTACK_CREDENTIALS) .build(); } @@ -86,18 +88,8 @@ public static AmazonSQSAsync amazonSQSAsync(@Value("${localstack.url}") String l public static SnsClient snsClient(@Value("${localstack.url}") String localstackUrl) { return SnsClient.builder() .endpointOverride(URI.create(localstackUrl)) - .region(Region.EU_WEST_2) - .credentialsProvider(StaticCredentialsProvider.create(new AwsCredentials() { - @Override - public String accessKeyId() { - return "LSIA5678901234567890"; - } - - @Override - public String secretAccessKey() { - return "LSIA5678901234567890"; - } - })) + .region(LOCALSTACK_REGION) + .credentialsProvider(LOCALSTACK_CREDENTIALS) .build(); } @@ -105,19 +97,8 @@ public String secretAccessKey() { public static DynamoDbClient dynamoDbClient(@Value("${localstack.url}") String localstackUrl) { return DynamoDbClient.builder() .endpointOverride(URI.create(localstackUrl)) - .region(Region.EU_WEST_2) - .credentialsProvider( - StaticCredentialsProvider.create(new AwsCredentials() { - @Override - public String accessKeyId() { - return "LSIA5678901234567890"; - } - - @Override - public String secretAccessKey() { - return "LSIA5678901234567890"; - } - })) + .region(LOCALSTACK_REGION) + .credentialsProvider(LOCALSTACK_CREDENTIALS) .build(); } @@ -126,23 +107,23 @@ public String secretAccessKey() { public static CloudWatchClient cloudwatchClient(@Value("${localstack.url}") String localstackUrl) { return CloudWatchClient.builder() .endpointOverride(URI.create(localstackUrl)) - .region(Region.EU_WEST_2) - .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("LSIAQAAAAAAVNCBMPNSG", "LSIAQAAAAAAVNCBMPNSG"))) + .region(LOCALSTACK_REGION) + .credentialsProvider(LOCALSTACK_CREDENTIALS) .build(); } @PostConstruct public void setupTestQueuesAndTopics() { - amazonSQSAsync.createQueue(suspensionsQueueName); - amazonSQSAsync.createQueue(ackQueueName); - var notSuspendedQueue = amazonSQSAsync.createQueue(notSuspendedQueueName); - var mofUpdatedQueue = amazonSQSAsync.createQueue(mofUpdatedQueueName); - var eventOutOfOrderQueue = amazonSQSAsync.createQueue(eventOutOfOrderQueueName); - var invalidSuspensionQueue = amazonSQSAsync.createQueue(invalidSuspensionQueueName); - var invalidSuspensionAuditQueue = amazonSQSAsync.createQueue(invalidSuspensionAuditQueueName); - var incomingQueue = amazonSQSAsync.createQueue(repoIncomingQueueName); - //Queue created in re-registration service, only used here for checking that message is received on active-suspensions topic - var activeSuspensionsQueue = amazonSQSAsync.createQueue(activeSuspensionsQueueName); + sqsClient.createQueue(builder -> builder.queueName(suspensionsQueueName)); + sqsClient.createQueue(builder -> builder.queueName(ackQueueName)); + CreateQueueResponse notSuspendedQueue = sqsClient.createQueue(builder -> builder.queueName(notSuspendedQueueName)); + CreateQueueResponse mofUpdatedQueue = sqsClient.createQueue(builder -> builder.queueName(mofUpdatedQueueName)); + CreateQueueResponse eventOutOfOrderQueue = sqsClient.createQueue(builder -> builder.queueName(eventOutOfOrderQueueName)); + CreateQueueResponse invalidSuspensionQueue = sqsClient.createQueue(builder -> builder.queueName(invalidSuspensionQueueName)); + CreateQueueResponse invalidSuspensionAuditQueue = sqsClient.createQueue(builder -> builder.queueName(invalidSuspensionAuditQueueName)); + CreateQueueResponse incomingQueue = sqsClient.createQueue(builder -> builder.queueName(repoIncomingQueueName)); + // Queue created in re-registration service, only used here for checking that message is received on active-suspensions topic + CreateQueueResponse activeSuspensionsQueue = sqsClient.createQueue(builder -> builder.queueName(activeSuspensionsQueueName)); var topic = snsClient.createTopic(CreateTopicRequest.builder().name("test_not_suspended_topic").build()); var mofUpdatedTopic = snsClient.createTopic(CreateTopicRequest.builder().name("mof_updated_sns_topic").build()); @@ -152,19 +133,18 @@ public void setupTestQueuesAndTopics() { var repoIncomingTopic = snsClient.createTopic(CreateTopicRequest.builder().name("repo_incoming_sns_topic").build()); var activeSuspensionsTopic = snsClient.createTopic(CreateTopicRequest.builder().name("active_suspensions_sns_topic").build()); - createSnsTestReceiverSubscription(topic, getQueueArn(notSuspendedQueue.getQueueUrl())); - createSnsTestReceiverSubscription(mofUpdatedTopic, getQueueArn(mofUpdatedQueue.getQueueUrl())); - createSnsTestReceiverSubscription(eventOutOfOrderTopic, getQueueArn(eventOutOfOrderQueue.getQueueUrl())); - createSnsTestReceiverSubscription(invalidSuspensionTopic, getQueueArn(invalidSuspensionQueue.getQueueUrl())); - createSnsTestReceiverSubscription(nonSensitiveInvalidSuspensionTopic, getQueueArn(invalidSuspensionAuditQueue.getQueueUrl())); - createSnsTestReceiverSubscription(repoIncomingTopic, getQueueArn(incomingQueue.getQueueUrl())); - createSnsTestReceiverSubscription(activeSuspensionsTopic, getQueueArn(activeSuspensionsQueue.getQueueUrl())); + createSnsTestReceiverSubscription(topic, getQueueArn(notSuspendedQueue.queueUrl())); + createSnsTestReceiverSubscription(mofUpdatedTopic, getQueueArn(mofUpdatedQueue.queueUrl())); + createSnsTestReceiverSubscription(eventOutOfOrderTopic, getQueueArn(eventOutOfOrderQueue.queueUrl())); + createSnsTestReceiverSubscription(invalidSuspensionTopic, getQueueArn(invalidSuspensionQueue.queueUrl())); + createSnsTestReceiverSubscription(nonSensitiveInvalidSuspensionTopic, getQueueArn(invalidSuspensionAuditQueue.queueUrl())); + createSnsTestReceiverSubscription(repoIncomingTopic, getQueueArn(incomingQueue.queueUrl())); + createSnsTestReceiverSubscription(activeSuspensionsTopic, getQueueArn(activeSuspensionsQueue.queueUrl())); setupDbAndTable(); } private void setupDbAndTable() { - var waiter = dynamoDbClient.waiter(); var tableRequest = DescribeTableRequest.builder() .tableName(suspensionDynamoDbTableName) @@ -174,7 +154,6 @@ private void setupDbAndTable() { resetTableForLocalEnvironment(waiter, tableRequest); } - List keySchema = new ArrayList<>(); keySchema.add(KeySchemaElement.builder() .keyType(KeyType.HASH) @@ -221,7 +200,10 @@ private void createSnsTestReceiverSubscription(CreateTopicResponse topic, String } private String getQueueArn(String queueUrl) { - GetQueueAttributesResult queueAttributes = amazonSQSAsync.getQueueAttributes(queueUrl, List.of("QueueArn")); - return queueAttributes.getAttributes().get("QueueArn"); + var queueAttributes = sqsClient.getQueueAttributes(GetQueueAttributesRequest.builder() + .queueUrl(queueUrl) + .attributeNames(QueueAttributeName.QUEUE_ARN) + .build()); + return queueAttributes.attributes().get(QueueAttributeName.QUEUE_ARN); } } diff --git a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateBasedOnOdsCodeToggle.java b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateBasedOnOdsCodeToggle.java index e1a5c3a1..e4e31ab9 100644 --- a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateBasedOnOdsCodeToggle.java +++ b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateBasedOnOdsCodeToggle.java @@ -1,9 +1,5 @@ package uk.nhs.prm.repo.suspension.service.repo.in; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.model.Message; -import com.amazonaws.services.sqs.model.PurgeQueueRequest; -import com.amazonaws.services.sqs.model.ReceiveMessageRequest; import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -16,6 +12,10 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import software.amazon.awssdk.services.sqs.SqsClient; +import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.PurgeQueueRequest; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; import uk.nhs.prm.repo.suspension.service.infra.LocalStackAwsConfig; import uk.nhs.prm.repo.suspension.service.suspensionsevents.SuspensionEventBuilder; @@ -36,7 +36,7 @@ public class MOFUpdateBasedOnOdsCodeToggle { @Autowired - private AmazonSQSAsync sqs; + private SqsClient sqs; @Value("${aws.incomingQueueName}") private String suspensionsQueueName; @@ -54,7 +54,8 @@ public class MOFUpdateBasedOnOdsCodeToggle { @BeforeEach public void setUp() { stubPdsAdaptor = initializeWebServer(); - suspensionQueueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); + configureFor("localhost", stubPdsAdaptor.port()); + suspensionQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); } @AfterEach @@ -75,16 +76,16 @@ void shouldUpdateMofToPreviousGpAndSendMessageToMofUpdatedSNSTopicWhenOdsCodeNot var nhsNumber = Long.toString(System.currentTimeMillis()); stubForPdsAdaptor(nhsNumber, getSuspendedResponseWith(nhsNumber)); - var mofUpdatedQueueUrl = sqs.getQueueUrl(mofUpdatedQueueName).getQueueUrl(); - sqs.sendMessage(suspensionQueueUrl, getSuspensionEventWith(nhsNumber, "B85612")); + var mofUpdatedQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(mofUpdatedQueueName)).queueUrl(); + sqs.sendMessage(builder -> builder.queueUrl(suspensionQueueUrl).messageBody(getSuspensionEventWith(nhsNumber, "B85612"))); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { List receivedMessageHolder = checkMessageInRelatedQueue(mofUpdatedQueueUrl); - assertTrue(receivedMessageHolder.get(0).getBody().contains("ACTION:UPDATED_MANAGING_ORGANISATION")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("TEST-NEMS-ID")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("B85612")); - assertTrue(receivedMessageHolder.get(0).getMessageAttributes().containsKey("traceId")); + assertTrue(receivedMessageHolder.get(0).body().contains("ACTION:UPDATED_MANAGING_ORGANISATION")); + assertTrue(receivedMessageHolder.get(0).body().contains("TEST-NEMS-ID")); + assertTrue(receivedMessageHolder.get(0).body().contains("B85612")); + assertTrue(receivedMessageHolder.get(0).messageAttributes().containsKey("traceId")); }); } @@ -94,27 +95,27 @@ void shouldSetMOFAsRepoOdsCodeWhenOdsCodeIsInSafeList(){ stubForPdsAdaptor(nhsNumber, getSuspendedResponseWithRepoOdsCode(nhsNumber)); - var repoIncomingQueueUrl = sqs.getQueueUrl(repoIncomingQueueName).getQueueUrl(); + var repoIncomingQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(repoIncomingQueueName)).queueUrl(); purgeQueue(repoIncomingQueueUrl); - sqs.sendMessage(suspensionQueueUrl, getSuspensionEventWith(nhsNumber, "tEsT21")); + sqs.sendMessage(builder -> builder.queueUrl(suspensionQueueUrl).messageBody(getSuspensionEventWith(nhsNumber, "tEsT21"))); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { List receivedMessageHolder = checkMessageInRelatedQueue(repoIncomingQueueUrl); - assertTrue(receivedMessageHolder.get(0).getBody().contains("TEST-NEMS-ID")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("A1234")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("nemsEventLastUpdated")); - assertTrue(receivedMessageHolder.get(0).getMessageAttributes().containsKey("traceId")); + assertTrue(receivedMessageHolder.get(0).body().contains("TEST-NEMS-ID")); + assertTrue(receivedMessageHolder.get(0).body().contains("A1234")); + assertTrue(receivedMessageHolder.get(0).body().contains("nemsEventLastUpdated")); + assertTrue(receivedMessageHolder.get(0).messageAttributes().containsKey("traceId")); }); } private void stubForPdsAdaptor(String nhsNumber, String suspendedResponse) { - stubFor(get(urlMatching("/suspended-patient-status/" + nhsNumber)) + stubPdsAdaptor.stubFor(get(urlMatching("/suspended-patient-status/" + nhsNumber)) .withHeader("Authorization", matching("Basic c3VzcGVuc2lvbi1zZXJ2aWNlOiJ0ZXN0Ig==")) .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(getSuspendedResponseWith(nhsNumber)))); - stubFor(put(urlMatching("/suspended-patient-status/" + nhsNumber)) + stubPdsAdaptor.stubFor(put(urlMatching("/suspended-patient-status/" + nhsNumber)) .withHeader("Authorization", matching("Basic c3VzcGVuc2lvbi1zZXJ2aWNlOiJ0ZXN0Ig==")) .willReturn(aResponse() .withHeader("Content-Type", "application/json") @@ -124,10 +125,11 @@ private void stubForPdsAdaptor(String nhsNumber, String suspendedResponse) { private List checkMessageInRelatedQueue(String queueUrl) { System.out.println("checking sqs queue: " + queueUrl); - var requestForMessagesWithAttributes - = new ReceiveMessageRequest().withQueueUrl(queueUrl) - .withMessageAttributeNames("traceId"); - List messages = sqs.receiveMessage(requestForMessagesWithAttributes).getMessages(); + var requestForMessagesWithAttributes = ReceiveMessageRequest.builder() + .queueUrl(queueUrl) + .messageAttributeNames("traceId") + .build(); + List messages = sqs.receiveMessage(requestForMessagesWithAttributes).messages(); System.out.printf("Found %s messages on queue: %s%n", messages.size(), queueUrl); assertThat(messages).hasSize(1); return messages; @@ -171,6 +173,6 @@ private String getSuspendedResponseWithRepoOdsCode(String nhsNumber) { private void purgeQueue(String queueUrl) { System.out.println("Purging queue url: " + queueUrl); - sqs.purgeQueue(new PurgeQueueRequest(queueUrl)); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(queueUrl).build()); } } diff --git a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateToRepoIntegrationTest.java b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateToRepoIntegrationTest.java index 941396c7..932b8052 100644 --- a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateToRepoIntegrationTest.java +++ b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/repo/in/MOFUpdateToRepoIntegrationTest.java @@ -1,9 +1,5 @@ package uk.nhs.prm.repo.suspension.service.repo.in; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.model.Message; -import com.amazonaws.services.sqs.model.PurgeQueueRequest; -import com.amazonaws.services.sqs.model.ReceiveMessageRequest; import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -16,6 +12,10 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import software.amazon.awssdk.services.sqs.SqsClient; +import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.PurgeQueueRequest; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; import uk.nhs.prm.repo.suspension.service.infra.LocalStackAwsConfig; import uk.nhs.prm.repo.suspension.service.suspensionsevents.SuspensionEventBuilder; @@ -25,7 +25,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest(properties = "toggle.canUpdateManagingOrganisationToRepo=true") @@ -36,7 +35,7 @@ public class MOFUpdateToRepoIntegrationTest { @Autowired - private AmazonSQSAsync sqs; + private SqsClient sqs; @Value("${aws.incomingQueueName}") private String suspensionsQueueName; @@ -51,7 +50,8 @@ public class MOFUpdateToRepoIntegrationTest { @BeforeEach public void setUp() { stubPdsAdaptor = initializeWebServer(); - suspensionQueueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); + configureFor("localhost", stubPdsAdaptor.port()); + suspensionQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); purgeQueue(suspensionQueueUrl); } @@ -59,7 +59,7 @@ public void setUp() { public void tearDown() { stubPdsAdaptor.resetAll(); stubPdsAdaptor.stop(); - suspensionQueueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); + suspensionQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); purgeQueue(suspensionQueueUrl); } @@ -70,7 +70,7 @@ private WireMockServer initializeWebServer() { } @Test - void shouldSetMOFAsRepoOdsCodeWhenToggleOn(){ + void shouldSetMOFAsRepoOdsCodeWhenToggleOn() { var nhsNumber = Long.toString(System.currentTimeMillis()); stubFor(get(urlMatching("/suspended-patient-status/" + nhsNumber)) .withHeader("Authorization", matching("Basic c3VzcGVuc2lvbi1zZXJ2aWNlOiJ0ZXN0Ig==")) @@ -83,31 +83,30 @@ void shouldSetMOFAsRepoOdsCodeWhenToggleOn(){ .withHeader("Content-Type", "application/json") .withBody(getSuspendedResponseWithRepoOdsCode(nhsNumber)))); - - var queueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); - var repoIncomingQueueUrl = sqs.getQueueUrl(repoIncomingQueueName).getQueueUrl(); + var queueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); + var repoIncomingQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(repoIncomingQueueName)).queueUrl(); purgeQueue(repoIncomingQueueUrl); - sqs.sendMessage(queueUrl, getSuspensionEventWith(nhsNumber)); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(getSuspensionEventWith(nhsNumber))); System.out.println("Sent message to queue url " + queueUrl); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { List receivedMessageHolder = checkMessageInRelatedQueue(repoIncomingQueueUrl); - assertTrue(receivedMessageHolder.get(0).getBody().contains("TEST-NEMS-ID")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("A1234")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("nemsEventLastUpdated")); - assertTrue(receivedMessageHolder.get(0).getMessageAttributes().containsKey("traceId")); - + assertTrue(receivedMessageHolder.get(0).body().contains("TEST-NEMS-ID")); + assertTrue(receivedMessageHolder.get(0).body().contains("A1234")); + assertTrue(receivedMessageHolder.get(0).body().contains("nemsEventLastUpdated")); + assertTrue(receivedMessageHolder.get(0).messageAttributes().containsKey("traceId")); }); } private List checkMessageInRelatedQueue(String queueUrl) { System.out.println("checking sqs queue: " + queueUrl); - var requestForMessagesWithAttributes - = new ReceiveMessageRequest().withQueueUrl(queueUrl) - .withMessageAttributeNames("traceId"); - List messages = sqs.receiveMessage(requestForMessagesWithAttributes).getMessages(); + var requestForMessagesWithAttributes = ReceiveMessageRequest.builder() + .queueUrl(queueUrl) + .messageAttributeNames("traceId") + .build(); + List messages = sqs.receiveMessage(requestForMessagesWithAttributes).messages(); System.out.printf("Found %s messages on queue: %s%n", messages.size(), queueUrl); assertThat(messages).hasSize(1); return messages; @@ -151,6 +150,6 @@ private String getSuspendedResponseWithRepoOdsCode(String nhsNumber) { private void purgeQueue(String queueUrl) { System.out.println("Purging queue url: " + queueUrl); - sqs.purgeQueue(new PurgeQueueRequest(queueUrl)); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(queueUrl).build()); } } diff --git a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventBuilder.java b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventBuilder.java index f243fe66..f15fb137 100644 --- a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventBuilder.java +++ b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventBuilder.java @@ -1,7 +1,7 @@ package uk.nhs.prm.repo.suspension.service.suspensionsevents; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; public class SuspensionEventBuilder { @@ -39,7 +39,7 @@ private SuspensionEventBuilder add(String fieldName, String value) { private String toJson(ImmutableMap messageData) { try { return new ObjectMapper().writeValueAsString(messageData); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { throw new RuntimeException(e); } } diff --git a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionThrottlingTest.java b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionThrottlingTest.java index 573c4539..ae96b5e7 100644 --- a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionThrottlingTest.java +++ b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionThrottlingTest.java @@ -1,12 +1,10 @@ package uk.nhs.prm.repo.suspension.service.suspensionsevents; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.model.GetQueueAttributesResult; -import com.amazonaws.services.sqs.model.PurgeQueueRequest; -import com.amazonaws.services.sqs.model.SendMessageBatchRequest; -import com.amazonaws.services.sqs.model.SendMessageBatchRequestEntry; import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -17,6 +15,12 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import software.amazon.awssdk.services.sqs.SqsClient; +import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; +import software.amazon.awssdk.services.sqs.model.PurgeQueueRequest; +import software.amazon.awssdk.services.sqs.model.QueueAttributeName; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; import uk.nhs.prm.repo.suspension.service.infra.LocalStackAwsConfig; import java.time.Duration; @@ -32,15 +36,15 @@ import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertTrue; -@SpringBootTest() +@SpringBootTest @ActiveProfiles("test") @ExtendWith(SpringExtension.class) -@ContextConfiguration( classes = LocalStackAwsConfig.class) +@ContextConfiguration(classes = LocalStackAwsConfig.class) @DirtiesContext public class SuspensionThrottlingTest { @Autowired - private AmazonSQSAsync sqs; + private SqsClient sqs; @Value("${aws.incomingQueueName}") private String suspensionsQueueName; @@ -51,13 +55,15 @@ public class SuspensionThrottlingTest { private WireMockServer stubPdsAdaptor; private String mofUpdatedQueueUrl; + private String suspensionQueueUrl; @BeforeEach public void setUp() { stubPdsAdaptor = initializeWebServer(); - mofUpdatedQueueUrl = sqs.getQueueUrl(mofUpdatedQueueName).getQueueUrl(); - suspensionQueueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); + configureFor("localhost", stubPdsAdaptor.port()); + mofUpdatedQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(mofUpdatedQueueName)).queueUrl(); + suspensionQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); purgeQueues(suspensionQueueUrl, mofUpdatedQueueUrl); } @@ -115,10 +121,10 @@ void shouldApplyBackOffDelay() { var nhsNumber = randomNhsNumber(); setPdsRetryMessage(nhsNumber); - stubbinForGenericPdsResponses(0,0); + stubbinForGenericPdsResponses(0, 0); var startingTime = Instant.now(); - sqs.sendMessage(suspensionQueueUrl, getSuspensionEvent(nhsNumber)); + sqs.sendMessage(builder -> builder.queueUrl(suspensionQueueUrl).messageBody(getSuspensionEvent(nhsNumber))); await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> assertTrue(isQueueEmpty(suspensionQueueUrl))); @@ -140,7 +146,7 @@ void shouldRetry3TimesWithExponentialBackOffPeriod() { var startingTime = Instant.now(); sendMultipleBatchesOf10Messages(suspensionQueueUrl, 2); - sqs.sendMessage(suspensionQueueUrl, getSuspensionEvent(nhsNumber)); + sqs.sendMessage(builder -> builder.queueUrl(suspensionQueueUrl).messageBody(getSuspensionEvent(nhsNumber))); await().atMost(120, TimeUnit.SECONDS).untilAsserted(() -> assertTrue(isQueueEmpty(suspensionQueueUrl))); @@ -173,7 +179,7 @@ private void setPdsErrorState(String startingState, String finishedState, int pr .inScenario("Retry Scenario") .whenScenarioStateIs(startingState) .willReturn(aResponse() - .withStatus(500) // request unsuccessful with status code 500 + .withStatus(500) .withHeader("Content-Type", "text/xml") .withBody("Some content")) .willSetStateTo(finishedState)); @@ -204,29 +210,35 @@ private void stubbinForGenericPdsResponses(int getRequestDelay, int putRequestDe } private boolean isQueueEmpty(String queueUrl) { - List attributeList = new ArrayList<>(); - attributeList.add("ApproximateNumberOfMessagesNotVisible"); - attributeList.add("ApproximateNumberOfMessages"); - GetQueueAttributesResult getQueueAttributesResult = sqs.getQueueAttributes(queueUrl, attributeList); - - var numberOfMessageNotVisible = Integer.valueOf(getQueueAttributesResult.getAttributes().get("ApproximateNumberOfMessagesNotVisible")); - var numberOfMessageVisible = Integer.valueOf(getQueueAttributesResult.getAttributes().get("ApproximateNumberOfMessages")); + var getQueueAttributesResult = sqs.getQueueAttributes(GetQueueAttributesRequest.builder() + .queueUrl(queueUrl) + .attributeNames( + QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE, + QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES) + .build()); + + var numberOfMessageNotVisible = Integer.parseInt( + getQueueAttributesResult.attributes().get(QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE)); + var numberOfMessageVisible = Integer.parseInt( + getQueueAttributesResult.attributes().get(QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES)); return (numberOfMessageVisible == 0 && numberOfMessageNotVisible == 0); } private SendMessageBatchRequest createBatchOfTenRequest(String queueUrl) { - SendMessageBatchRequest sendMessageBatchRequest = new SendMessageBatchRequest(); - sendMessageBatchRequest.setEntries(generateSendMessageBatchRequestEntryList()); - sendMessageBatchRequest.setQueueUrl(queueUrl); - - return sendMessageBatchRequest; + return SendMessageBatchRequest.builder() + .queueUrl(queueUrl) + .entries(generateSendMessageBatchRequestEntryList()) + .build(); } private List generateSendMessageBatchRequestEntryList() { List requestEntries = new ArrayList<>(); for (int i = 0; i < 10; i++) { - requestEntries.add(new SendMessageBatchRequestEntry(UUID.randomUUID().toString(), getSuspensionEvent())); + requestEntries.add(SendMessageBatchRequestEntry.builder() + .id(UUID.randomUUID().toString()) + .messageBody(getSuspensionEvent()) + .build()); } return requestEntries; } @@ -268,7 +280,7 @@ private String randomNhsNumber() { } private void purgeQueues(String queueUrl, String mofUpdatedQueueUrl) { - sqs.purgeQueue(new PurgeQueueRequest(queueUrl)); - sqs.purgeQueue(new PurgeQueueRequest(mofUpdatedQueueUrl)); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(queueUrl).build()); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(mofUpdatedQueueUrl).build()); } } diff --git a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsIntegrationTest.java b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsIntegrationTest.java index 86822adf..7b14a5e3 100644 --- a/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsIntegrationTest.java +++ b/services/suspension-service/src/integration/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsIntegrationTest.java @@ -1,9 +1,5 @@ package uk.nhs.prm.repo.suspension.service.suspensionsevents; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.model.Message; -import com.amazonaws.services.sqs.model.PurgeQueueRequest; -import com.amazonaws.services.sqs.model.ReceiveMessageRequest; import com.github.tomakehurst.wiremock.WireMockServer; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -16,6 +12,10 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import software.amazon.awssdk.services.sqs.SqsClient; +import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.PurgeQueueRequest; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; import uk.nhs.prm.repo.suspension.service.infra.LocalStackAwsConfig; import java.util.List; @@ -34,7 +34,7 @@ public class SuspensionsIntegrationTest { @Autowired - private AmazonSQSAsync sqs; + private SqsClient sqs; @Value("${aws.incomingQueueName}") private String suspensionsQueueName; @@ -64,15 +64,16 @@ public class SuspensionsIntegrationTest { @BeforeEach public void setUp() { stubPdsAdaptor = initializeWebServer(); - suspensionQueueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); + configureFor("localhost", stubPdsAdaptor.port()); + suspensionQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); purgeQueue(suspensionQueueUrl); } + @AfterEach public void tearDown() { stubPdsAdaptor.resetAll(); stubPdsAdaptor.stop(); - suspensionQueueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); purgeQueue(suspensionQueueUrl); } @@ -91,59 +92,59 @@ void shouldSendSuspensionMessageToNotSuspendedSNSTopicIfNoLongerSuspendedInPDS() .withHeader("Content-Type", "application/json") .withBody(getNotSuspendedResponseWith(nhsNumber)))); - var queueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); - var notSuspendedQueueUrl = sqs.getQueueUrl(notSuspendedQueueName).getQueueUrl(); - sqs.sendMessage(queueUrl, getSuspensionEventWith(nhsNumber)); + var queueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); + var notSuspendedQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(notSuspendedQueueName)).queueUrl(); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(getSuspensionEventWith(nhsNumber))); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { List receivedMessageHolder = checkMessageInRelatedQueue(notSuspendedQueueUrl); - assertTrue(receivedMessageHolder.get(0).getBody().contains("NO_ACTION:NO_LONGER_SUSPENDED_ON_PDS")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("nemsMessageId")); - assertTrue(receivedMessageHolder.get(0).getMessageAttributes().containsKey("traceId")); + assertTrue(receivedMessageHolder.get(0).body().contains("NO_ACTION:NO_LONGER_SUSPENDED_ON_PDS")); + assertTrue(receivedMessageHolder.get(0).body().contains("nemsMessageId")); + assertTrue(receivedMessageHolder.get(0).messageAttributes().containsKey("traceId")); }); purgeQueue(notSuspendedQueueUrl); } - @Test - void shouldUpdateManagingOrganisationAndSendMessageToMofUpdatedSNSTopicForSuspendedPatient() { - var nhsNumber = Long.toString(System.currentTimeMillis()); - stubFor(get(urlMatching("/suspended-patient-status/" + nhsNumber)) - .withHeader("Authorization", matching("Basic c3VzcGVuc2lvbi1zZXJ2aWNlOiJ0ZXN0Ig==")) - .willReturn(aResponse() - .withHeader("Content-Type", "application/json") - .withBody(getSuspendedResponseWith(nhsNumber)))); - stubFor(put(urlMatching("/suspended-patient-status/" + nhsNumber)) - .withHeader("Authorization", matching("Basic c3VzcGVuc2lvbi1zZXJ2aWNlOiJ0ZXN0Ig==")) - .willReturn(aResponse() - .withHeader("Content-Type", "application/json") - .withBody(getSuspendedResponseWith(nhsNumber)))); - - var queueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); - var mofUpdatedQueueUrl = sqs.getQueueUrl(mofUpdatedQueueName).getQueueUrl(); - var activeSuspensionsQueueUrl = sqs.getQueueUrl(activeSuspensionsQueueName).getQueueUrl(); - sqs.sendMessage(queueUrl, getSuspensionEventWith(nhsNumber)); - - await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { - List receivedMessageHolder = checkMessageInRelatedQueue(mofUpdatedQueueUrl); - - assertTrue(receivedMessageHolder.get(0).getBody().contains("ACTION:UPDATED_MANAGING_ORGANISATION")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("TEST-NEMS-ID")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("B85612")); - assertTrue(receivedMessageHolder.get(0).getMessageAttributes().containsKey("traceId")); - }); - - await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { - List receivedMessageHolder = checkMessageInRelatedQueue(activeSuspensionsQueueUrl); - - assertTrue(receivedMessageHolder.get(0).getBody().contains("nhsNumber")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("B85612")); - assertTrue(receivedMessageHolder.get(0).getBody().contains("2017-11-01T15:00:33+00:00")); - assertTrue(receivedMessageHolder.get(0).getMessageAttributes().containsKey("traceId")); - }); - - purgeQueue(mofUpdatedQueueUrl); - purgeQueue(activeSuspensionsQueueUrl); - } + @Test + void shouldUpdateManagingOrganisationAndSendMessageToMofUpdatedSNSTopicForSuspendedPatient() { + var nhsNumber = Long.toString(System.currentTimeMillis()); + stubFor(get(urlMatching("/suspended-patient-status/" + nhsNumber)) + .withHeader("Authorization", matching("Basic c3VzcGVuc2lvbi1zZXJ2aWNlOiJ0ZXN0Ig==")) + .willReturn(aResponse() + .withHeader("Content-Type", "application/json") + .withBody(getSuspendedResponseWith(nhsNumber)))); + stubFor(put(urlMatching("/suspended-patient-status/" + nhsNumber)) + .withHeader("Authorization", matching("Basic c3VzcGVuc2lvbi1zZXJ2aWNlOiJ0ZXN0Ig==")) + .willReturn(aResponse() + .withHeader("Content-Type", "application/json") + .withBody(getSuspendedResponseWith(nhsNumber)))); + + var queueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); + var mofUpdatedQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(mofUpdatedQueueName)).queueUrl(); + var activeSuspensionsQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(activeSuspensionsQueueName)).queueUrl(); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(getSuspensionEventWith(nhsNumber))); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + List receivedMessageHolder = checkMessageInRelatedQueue(mofUpdatedQueueUrl); + + assertTrue(receivedMessageHolder.get(0).body().contains("ACTION:UPDATED_MANAGING_ORGANISATION")); + assertTrue(receivedMessageHolder.get(0).body().contains("TEST-NEMS-ID")); + assertTrue(receivedMessageHolder.get(0).body().contains("B85612")); + assertTrue(receivedMessageHolder.get(0).messageAttributes().containsKey("traceId")); + }); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + List receivedMessageHolder = checkMessageInRelatedQueue(activeSuspensionsQueueUrl); + + assertTrue(receivedMessageHolder.get(0).body().contains("nhsNumber")); + assertTrue(receivedMessageHolder.get(0).body().contains("B85612")); + assertTrue(receivedMessageHolder.get(0).body().contains("2017-11-01T15:00:33+00:00")); + assertTrue(receivedMessageHolder.get(0).messageAttributes().containsKey("traceId")); + }); + + purgeQueue(mofUpdatedQueueUrl); + purgeQueue(activeSuspensionsQueueUrl); + } @Test void shouldPutEventOutOfOrderInRelevantQueues() { @@ -160,26 +161,26 @@ void shouldPutEventOutOfOrderInRelevantQueues() { .withHeader("Content-Type", "application/json") .withBody(getSuspendedResponseWith(nhsNumber)))); - var queueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); - var mofUpdatedQueueUrl = sqs.getQueueUrl(mofUpdatedQueueName).getQueueUrl(); - var eventOutOfOrderQueue = sqs.getQueueUrl(eventOutOfOrderQueueName).getQueueUrl(); + var queueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); + var mofUpdatedQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(mofUpdatedQueueName)).queueUrl(); + var eventOutOfOrderQueue = sqs.getQueueUrl(builder -> builder.queueName(eventOutOfOrderQueueName)).queueUrl(); var suspensionEvent = getSuspensionEventWith(nhsNumber); - sqs.sendMessage(queueUrl, suspensionEvent); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(suspensionEvent)); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { var receivedMessageHolder = checkMessageInRelatedQueue(mofUpdatedQueueUrl); - assertTrue(receivedMessageHolder.get(0).getBody().contains("B85612")); + assertTrue(receivedMessageHolder.get(0).body().contains("B85612")); }); var nemsMessageId = "OUT-OF-ORDER-ID"; var secondSuspensionEvent = getSuspensionEventWith(nhsNumber, nemsMessageId); - sqs.sendMessage(queueUrl, secondSuspensionEvent); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(secondSuspensionEvent)); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { var receivedMessageInObservabilityQueue = checkMessageInRelatedQueue(eventOutOfOrderQueue); - assertTrue(receivedMessageInObservabilityQueue.get(0).getBody().contains(nemsMessageId)); + assertTrue(receivedMessageInObservabilityQueue.get(0).body().contains(nemsMessageId)); }); purgeQueue(mofUpdatedQueueUrl); @@ -200,27 +201,27 @@ void shouldPutDLQsWhenPdsAdaptorReturn400() { .withStatus(400) .withHeader("Content-Type", "application/json"))); - var queueUrl = sqs.getQueueUrl(suspensionsQueueName).getQueueUrl(); - var invalidSuspensionQueueUrl = sqs.getQueueUrl(invalidSuspensionQueueName).getQueueUrl(); - var nonSensitiveInvalidSuspensionQueueUrl = sqs.getQueueUrl(invalidSuspensionAuditQueueName).getQueueUrl(); - sqs.sendMessage(queueUrl, getSuspensionEventWith(nhsNumber)); + var queueUrl = sqs.getQueueUrl(builder -> builder.queueName(suspensionsQueueName)).queueUrl(); + var invalidSuspensionQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(invalidSuspensionQueueName)).queueUrl(); + var nonSensitiveInvalidSuspensionQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(invalidSuspensionAuditQueueName)).queueUrl(); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(getSuspensionEventWith(nhsNumber))); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { List receivedMessageHolderForInvalidSuspensions = checkMessageInRelatedQueue(invalidSuspensionQueueUrl); - assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).getBody().contains("nhsNumber")); - assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).getBody().contains(nhsNumber)); - assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).getBody().contains("B85612")); - assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).getBody().contains("TEST-NEMS-ID")); - assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).getMessageAttributes().containsKey("traceId")); + assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).body().contains("nhsNumber")); + assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).body().contains(nhsNumber)); + assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).body().contains("B85612")); + assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).body().contains("TEST-NEMS-ID")); + assertTrue(receivedMessageHolderForInvalidSuspensions.get(0).messageAttributes().containsKey("traceId")); }); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { List receivedMessageHolderForNonSensitiveInvalidSuspensions = checkMessageInRelatedQueue(nonSensitiveInvalidSuspensionQueueUrl); - assertTrue(receivedMessageHolderForNonSensitiveInvalidSuspensions.get(0).getBody().contains("NO_ACTION:INVALID_SUSPENSION")); - assertTrue(receivedMessageHolderForNonSensitiveInvalidSuspensions.get(0).getBody().contains("TEST-NEMS-ID")); + assertTrue(receivedMessageHolderForNonSensitiveInvalidSuspensions.get(0).body().contains("NO_ACTION:INVALID_SUSPENSION")); + assertTrue(receivedMessageHolderForNonSensitiveInvalidSuspensions.get(0).body().contains("TEST-NEMS-ID")); }); purgeQueue(invalidSuspensionQueueUrl); @@ -231,10 +232,11 @@ void shouldPutDLQsWhenPdsAdaptorReturn400() { private List checkMessageInRelatedQueue(String queueUrl) { System.out.println("checking sqs queue: " + queueUrl); - var requestForMessagesWithAttributes - = new ReceiveMessageRequest().withQueueUrl(queueUrl) - .withMessageAttributeNames("traceId"); - List messages = sqs.receiveMessage(requestForMessagesWithAttributes).getMessages(); + var requestForMessagesWithAttributes = ReceiveMessageRequest.builder() + .queueUrl(queueUrl) + .messageAttributeNames("traceId") + .build(); + List messages = sqs.receiveMessage(requestForMessagesWithAttributes).messages(); System.out.printf("Found %s messages on queue: %s%n", messages.size(), queueUrl); assertThat(messages).hasSize(1); return messages; @@ -276,6 +278,6 @@ private String getSuspendedResponseWith(String nhsNumber) { private void purgeQueue(String queueUrl) { System.out.println("Purging queue url: " + queueUrl); - sqs.purgeQueue(new PurgeQueueRequest(queueUrl)); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(queueUrl).build()); } } diff --git a/services/suspension-service/src/integration/resources/logback-test.xml b/services/suspension-service/src/integration/resources/logback-test.xml new file mode 100644 index 00000000..11a07a7d --- /dev/null +++ b/services/suspension-service/src/integration/resources/logback-test.xml @@ -0,0 +1,17 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/HttpClientConfig.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/HttpClientConfig.java index 8798513c..870ce2b8 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/HttpClientConfig.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/HttpClientConfig.java @@ -16,7 +16,7 @@ import org.apache.hc.core5.ssl.SSLContextBuilder; import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; -import org.apache.http.protocol.HTTP; +import org.apache.hc.core5.http.HttpHeaders; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; @@ -77,7 +77,9 @@ public PoolingHttpClientConnectionManager poolingConnectionManager() { @Bean public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() { return (response, context) -> { - BasicHeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); + BasicHeaderElementIterator it = + new BasicHeaderElementIterator(response.headerIterator(HttpHeaders.KEEP_ALIVE)); + while (it.hasNext()) { HeaderElement headerElement = it.next(); diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/SqsListenerSpringConfiguration.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/SqsListenerSpringConfiguration.java index 2d80295f..518a7b63 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/SqsListenerSpringConfiguration.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/SqsListenerSpringConfiguration.java @@ -3,8 +3,6 @@ import com.amazon.sqs.javamessaging.ProviderConfiguration; import com.amazon.sqs.javamessaging.SQSConnectionFactory; import com.amazon.sqs.javamessaging.SQSSession; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -15,6 +13,7 @@ import org.springframework.jms.config.SimpleJmsListenerEndpoint; import org.springframework.jms.listener.DefaultMessageListenerContainer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import software.amazon.awssdk.services.sqs.SqsClient; import uk.nhs.prm.repo.suspension.service.suspensionsevents.SuspensionMessageProcessor; import uk.nhs.prm.repo.suspension.service.suspensionsevents.SuspensionsEventListener; @@ -41,11 +40,6 @@ public class SqsListenerSpringConfiguration { private final SuspensionMessageProcessor suspensionsEventProcessor; private final Tracer tracer; - @Bean - public AmazonSQSAsync amazonSQSAsync() { - return AmazonSQSAsyncClientBuilder.defaultClient(); - } - @Bean public DefaultMessageListenerContainer jmsListener(DefaultJmsListenerContainerFactory jmsListenerContainerFactory) { SimpleJmsListenerEndpoint simpleJmsListenerEndpoint = new SimpleJmsListenerEndpoint(); @@ -55,9 +49,9 @@ public DefaultMessageListenerContainer jmsListener(DefaultJmsListenerContainerFa } @Bean - public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(AmazonSQSAsync amazonSQS) { + public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(SqsClient sqsClient) { ProviderConfiguration providerConfiguration = new ProviderConfiguration().withNumberOfMessagesToPrefetch(0); - SQSConnectionFactory connectionFactory = new SQSConnectionFactory(providerConfiguration, amazonSQS); + SQSConnectionFactory connectionFactory = new SQSConnectionFactory(providerConfiguration, sqsClient); DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConcurrency(concurrencyMinMax); factory.setSessionAcknowledgeMode(SQSSession.UNORDERED_ACKNOWLEDGE); diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/Tracer.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/Tracer.java index 3a225e0a..84116c66 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/Tracer.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/config/Tracer.java @@ -5,8 +5,8 @@ import org.slf4j.MDC; import org.springframework.context.annotation.Configuration; -import javax.jms.JMSException; -import javax.jms.Message; +import jakarta.jms.JMSException; +import jakarta.jms.Message; import java.util.UUID; @Slf4j diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/http/HttpServiceClient.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/http/HttpServiceClient.java index 7c7dce0b..3772bfb1 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/http/HttpServiceClient.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/http/HttpServiceClient.java @@ -2,7 +2,11 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import uk.nhs.prm.repo.suspension.service.config.Tracer; diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/pds/PdsAdaptorSuspensionStatusResponseParser.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/pds/PdsAdaptorSuspensionStatusResponseParser.java index fd787bff..55fcadce 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/pds/PdsAdaptorSuspensionStatusResponseParser.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/pds/PdsAdaptorSuspensionStatusResponseParser.java @@ -1,10 +1,10 @@ package uk.nhs.prm.repo.suspension.service.pds; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.ObjectMapper; import uk.nhs.prm.repo.suspension.service.model.PdsAdaptorSuspensionStatusResponse; @Component @@ -19,7 +19,7 @@ public PdsAdaptorSuspensionStatusResponse parse(String responseBody) { ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(responseBody, PdsAdaptorSuspensionStatusResponse.class); } - catch (JsonProcessingException e) { + catch (JacksonException e) { log.error("Got an exception while parsing PDS lookup response."); throw new UnexpectedPdsAdaptorResponseException("JSON parsing error attempting to parse PDS status response"); } diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/MessageProcessExecution.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/MessageProcessExecution.java index 9fca830c..a5356f67 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/MessageProcessExecution.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/MessageProcessExecution.java @@ -1,9 +1,9 @@ package uk.nhs.prm.repo.suspension.service.suspensionsevents; -import com.fasterxml.jackson.core.JsonProcessingException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import tools.jackson.core.JacksonException; import uk.nhs.prm.repo.suspension.service.config.MessageProcessProperties; import uk.nhs.prm.repo.suspension.service.data.LastUpdatedEventService; import uk.nhs.prm.repo.suspension.service.model.PdsAdaptorSuspensionStatusResponse; @@ -85,7 +85,7 @@ private PdsAdaptorSuspensionStatusResponse getPdsAdaptorSuspensionStatusResponse private SuspensionEvent getSuspensionEvent(String suspensionMessage) { try { return parser.parse(suspensionMessage); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { log.error("Got an exception while parsing suspensions message"); messagePublisherBroker.invalidMessage(suspensionMessage, null); throw new InvalidSuspensionMessageException("Encountered an invalid message", e); @@ -98,11 +98,6 @@ private boolean patientIsNonSynthetic(SuspensionEvent suspensionEvent) { return isNonSynthetic; } - -// private boolean patientIsSafeListed(SuspensionEvent suspensionEvent) { -// return this.config.getAllowedPatientsNhsNumbers() != null && this.config.getAllowedPatientsNhsNumbers().contains(suspensionEvent.nhsNumber()); -// } - private boolean processingOnlySyntheticPatients() { log.info("Process only synthetic patients: " + this.config.getProcessOnlySyntheticPatients()); return Boolean.parseBoolean(this.config.getProcessOnlySyntheticPatients()); diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParser.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParser.java index 813069eb..eb32bc72 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParser.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParser.java @@ -1,19 +1,16 @@ package uk.nhs.prm.repo.suspension.service.suspensionsevents; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; - -import java.util.HashMap; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.ObjectMapper; @Component @Slf4j public class SuspensionEventParser { private final ObjectMapper mapper = new ObjectMapper(); - public SuspensionEvent parse(String suspensionMessage) throws JsonProcessingException { + public SuspensionEvent parse(String suspensionMessage) throws JacksonException { return mapper.readValue(suspensionMessage, SuspensionEvent.class); } } \ No newline at end of file diff --git a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListener.java b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListener.java index db14fe48..17f21964 100644 --- a/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListener.java +++ b/services/suspension-service/src/main/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListener.java @@ -5,10 +5,10 @@ import uk.nhs.prm.repo.suspension.service.config.Tracer; import uk.nhs.prm.repo.suspension.service.pds.InvalidPdsRequestException; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.TextMessage; +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.MessageListener; +import jakarta.jms.TextMessage; @Slf4j @RequiredArgsConstructor diff --git a/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/config/TracerTest.java b/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/config/TracerTest.java index 81c9546b..9f47da7a 100644 --- a/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/config/TracerTest.java +++ b/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/config/TracerTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.Test; import org.slf4j.MDC; -import javax.jms.JMSException; +import jakarta.jms.JMSException; import java.util.UUID; diff --git a/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParserTest.java b/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParserTest.java index a3f4e8c8..49514220 100644 --- a/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParserTest.java +++ b/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionEventParserTest.java @@ -1,7 +1,7 @@ package uk.nhs.prm.repo.suspension.service.suspensionsevents; -import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.jupiter.api.Test; +import tools.jackson.core.JacksonException; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -10,6 +10,6 @@ class SuspensionEventParserTest { @Test void parseShouldThrowAnExceptionWhenMessageIsInvalid() { var parser = new SuspensionEventParser(); - assertThrows(JsonProcessingException.class, () -> parser.parse("invalid message")); + assertThrows(JacksonException.class, () -> parser.parse("invalid message")); } } \ No newline at end of file diff --git a/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListenerTest.java b/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListenerTest.java index 86f6c237..3ed8265e 100644 --- a/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListenerTest.java +++ b/services/suspension-service/src/test/java/uk/nhs/prm/repo/suspension/service/suspensionsevents/SuspensionsEventListenerTest.java @@ -9,7 +9,7 @@ import uk.nhs.prm.repo.suspension.service.config.Tracer; import uk.nhs.prm.repo.suspension.service.pds.InvalidPdsRequestException; -import javax.jms.JMSException; +import jakarta.jms.JMSException; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; diff --git a/services/suspension-service/tasks b/services/suspension-service/tasks index afbf1c23..beb719df 100755 --- a/services/suspension-service/tasks +++ b/services/suspension-service/tasks @@ -8,50 +8,11 @@ set -Eeo pipefail AWS_DEFAULT_REGION=eu-west-2 IMAGE_REPO_NAME=repo/suspension-service -AWS_HELPERS_VERSION=0.2.27 -echo "AWS helper scripts version: $AWS_HELPERS_VERSION" - -########################### -# Shared utils # -########################### - -AWS_HELPERS_FILE="utils/$AWS_HELPERS_VERSION/aws-helpers" - -mkdir -p "utils/$AWS_HELPERS_VERSION" -if [[ ! -f $AWS_HELPERS_FILE ]];then - wget --quiet -O $AWS_HELPERS_FILE https://github.com/nhsconnect/prm-deductions-support-infra/releases/download/${AWS_HELPERS_VERSION}/aws-helpers -fi -chmod +x $AWS_HELPERS_FILE -source $AWS_HELPERS_FILE #################################### # Instance (Environment) Variables # #################################### -function check_env { - if [[ -z "${NHS_ENVIRONMENT}" ]]; then - echo "Must set NHS_ENVIRONMENT" - exit 1 - fi - - if [[ -z "${NHS_SERVICE}" ]]; then - echo "Must set NHS_SERVICE" - exit 1 - fi -} - -function set_image_tag() { - if [[ -z "${GO_DEPENDENCY_LABEL_APP}" ]]; then - export IMAGE_TAG=${GO_PIPELINE_LABEL:-$(git rev-parse HEAD | cut -c 1-8)} - else - export IMAGE_TAG=${GO_DEPENDENCY_LABEL_APP} - fi -} - -function get_aws_account_id { - AWS_ACCOUNT_ID=$(aws sts get-caller-identity | jq -r .Account) -} - function configure_envs { export LOCALSTACK_URL="http://localhost:4566" export AWS_REGION="eu-west-2" @@ -72,44 +33,6 @@ function configure_sonar_environment_variable { # Terraform Functions # ####################### -function tf_init { - check_env - cd terraform - - terraform init -reconfigure \ - -backend-config key="${NHS_SERVICE}-${NHS_ENVIRONMENT}/terraform.tfstate" \ - -backend-config bucket="prm-deductions-${NHS_ENVIRONMENT}-terraform-state" \ - -backend-config dynamodb_table="prm-deductions-${NHS_ENVIRONMENT}-terraform-table" \ - -backend-config region=${AWS_DEFAULT_REGION} -} - -function tf_plan { - operation=$1 - - if [[ -z "${IMAGE_TAG}" ]]; then - set_image_tag - fi - - tf_init - - terraform get # modules - if [[ "${operation}" == "create" ]]; then - terraform plan -var task_image_tag=$IMAGE_TAG -var-file="configs/${NHS_SERVICE}/${NHS_SERVICE}.tfvars" -var-file="configs/${NHS_SERVICE}/$NHS_ENVIRONMENT.tfvars" -out="${NHS_SERVICE}.tfplan" - elif [[ "${operation}" == "destroy" ]]; then - terraform plan -var task_image_tag=$IMAGE_TAG -var-file="configs/${NHS_SERVICE}/${NHS_SERVICE}.tfvars" -var-file="configs/${NHS_SERVICE}/$NHS_ENVIRONMENT.tfvars" -out="${NHS_SERVICE}.tfplan" -destroy - else - echo "Unknown operation (should be create or destroy), got: ${operation}" - exit 1 - fi -} - -function tf_apply { - tf_init - terraform get # modules - terraform apply ${NHS_SERVICE}.tfplan - terraform output -json > tf-out.json -} - function configure_local_envs { export LOCALSTACK_URL="http://localhost:4566" export AWS_REGION="eu-west-2" @@ -122,23 +45,22 @@ function configure_local_envs { export NHS_ENVIRONMENT="local" } +############# +# Functions # +############# + function start_localstack { + echo "################################" + echo "##### Starting Localstack ######" + echo "################################" docker compose -f docker-compose.localstack-local.yaml up -d } -function destroy_localstack { - echo docker processes running: $(docker ps) - - DOCKER_CONTAINERS_ON_PORT=$(docker ps --filter publish=4566 -q) - - echo docker processes running on expected localstack port: $DOCKER_CONTAINERS_ON_PORT - - if [ -z "$DOCKER_CONTAINERS_ON_PORT" ]; then - echo no localstack nonsense going on, cool - else - echo trying to kill localstack... - docker stop $DOCKER_CONTAINERS_ON_PORT - fi +function stop_localstack { + echo "################################" + echo "##### Stopping Localstack ######" + echo "################################" + docker compose -f docker-compose.localstack-local.yaml down } ########### @@ -147,8 +69,11 @@ function destroy_localstack { command="$1" case "${command}" in - destroy_localstack) - destroy_localstack + start_localstack) + start_localstack + ;; + stop_localstack) + stop_localstack ;; build_docker) configure_envs @@ -168,66 +93,33 @@ case "${command}" in ;; test_integration) configure_envs + start_localstack ./gradlew --info integration + stop_localstack ;; test_coverage) configure_envs - destroy_localstack + start_localstack ./gradlew jacocoTestCoverageVerification + stop_localstack ;; code_quality) - destroy_localstack + start_localstack ./gradlew check -x test -x integration + stop_localstack ;; test_all) configure_envs + start_localstack ./gradlew clean test integration jacocoTestCoverageVerification check + stop_localstack ;; run_local) configure_envs ./gradlew bootRun ;; - start_localstack) - start_localstack - ;; - tf) - check_env - _assume_environment_role $NHS_ENVIRONMENT - tf_init - bash - ;; - tf_plan_suspension) - export NHS_SERVICE=suspension-service - check_env - export NHS_SERVICE=suspension-service - _assume_environment_role $NHS_ENVIRONMENT - tf_plan $2 - ;; - tf_plan) - check_env - _assume_environment_role $NHS_ENVIRONMENT - tf_plan $2 - ;; - tf_apply) - check_env - _assume_environment_role $NHS_ENVIRONMENT - tf_apply - ;; - promote_docker_image) - check_env - set_image_tag - promote_docker_image "$IMAGE_REPO_NAME:$IMAGE_TAG" "$NHS_ENVIRONMENT" - ;; - wait_ecs) - check_env - _assume_environment_role $NHS_ENVIRONMENT - aws ecs wait services-stable \ - --region $AWS_DEFAULT_REGION \ - --cluster $NHS_ENVIRONMENT-${NHS_SERVICE}-ecs-cluster \ - --service $NHS_ENVIRONMENT-${NHS_SERVICE} - ;; run_sonar) - destroy_localstack + stop_localstack _assume_environment_role $NHS_ENVIRONMENT configure_envs configure_sonar_environment_variable