diff --git a/.github/workflows/service-ci.yml b/.github/workflows/service-ci.yml index 10decfa0..003b4b97 100644 --- a/.github/workflows/service-ci.yml +++ b/.github/workflows/service-ci.yml @@ -152,6 +152,7 @@ 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/re-registration-service/Dockerfile b/services/re-registration-service/Dockerfile index ded9919c..748d52e9 100644 --- a/services/re-registration-service/Dockerfile +++ b/services/re-registration-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/re-registration-service/build.gradle b/services/re-registration-service/build.gradle index 5ea12bcf..1e9d9de4 100644 --- a/services/re-registration-service/build.gradle +++ b/services/re-registration-service/build.gradle @@ -1,15 +1,13 @@ plugins { - id 'org.springframework.boot' version '3.2.1' - 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.4.1.3373" } group = 'uk.nhs.prm.repo' version = '0.0.1-SNAPSHOT' -sourceCompatibility = '21' configurations { compileOnly { @@ -21,6 +19,12 @@ repositories { mavenCentral() } +java { + toolchain { + languageVersion = JavaLanguageVersion.of(25) + } +} + //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 { @@ -28,50 +32,45 @@ jar { } dependencies { - implementation('com.google.guava:guava') { version { strictly '32.1.3-jre' } } - - implementation('org.yaml:snakeyaml') { version { strictly '2.2' } } - implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-web' - 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-unix-common') { version { strictly '4.1.104.Final' } } + 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-unix-common') { version { strictly '4.2.9.Final' } } - implementation 'com.amazonaws:amazon-sqs-java-messaging-lib:1.1.2' + implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation platform('software.amazon.awssdk:bom:2.18.41') + implementation 'com.amazonaws:amazon-sqs-java-messaging-lib:2.1.4' + + implementation platform('software.amazon.awssdk:bom:2.41.14') implementation 'software.amazon.awssdk:cloudwatch' implementation 'software.amazon.awssdk:sqs' implementation 'software.amazon.awssdk:sns' implementation 'software.amazon.awssdk:dynamodb' - implementation group: 'javax.inject', name: 'javax.inject', version: '1' - implementation 'org.springframework:spring-jms:5.3.19' - implementation 'com.google.code.gson:gson:2.10.1' - implementation 'io.github.resilience4j:resilience4j-retry:1.7.1' + implementation 'com.google.code.gson:gson:2.13.2' + implementation 'io.github.resilience4j:resilience4j-retry:2.3.0' - implementation 'net.logstash.logback:logstash-logback-encoder:7.2' + implementation 'net.logstash.logback:logstash-logback-encoder:9.0' - compileOnly 'org.projectlombok:lombok:1.18.24' + compileOnly 'org.projectlombok:lombok:1.18.42' annotationProcessor 'org.projectlombok:lombok' - implementation 'com.github.spotbugs:spotbugs-annotations:4.8.3' - testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-test' - testImplementation "org.mockito:mockito-core:3.+" - testImplementation 'org.wiremock:wiremock-standalone:3.3.1' - testImplementation 'org.awaitility:awaitility:4.2.0' + testImplementation 'org.wiremock:wiremock-standalone:3.13.2' + testImplementation 'org.awaitility:awaitility:4.3.0' } test { @@ -129,43 +128,6 @@ jacocoTestCoverageVerification { } } -spotbugs { - toolVersion = '4.8.3' -} - -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/re-registration-service/docker-compose.localstack-local.yaml b/services/re-registration-service/docker-compose.localstack-local.yaml index 1009e50f..055caf48 100644 --- a/services/re-registration-service/docker-compose.localstack-local.yaml +++ b/services/re-registration-service/docker-compose.localstack-local.yaml @@ -1,7 +1,7 @@ services: localstack: container_name: "localstack-re-registration-service" - image: localstack/localstack + image: localstack/localstack:4.14.0 ports: - "4566:4566" network_mode: bridge diff --git a/services/re-registration-service/docker-compose.yaml b/services/re-registration-service/docker-compose.yaml index fc572eca..77393130 100644 --- a/services/re-registration-service/docker-compose.yaml +++ b/services/re-registration-service/docker-compose.yaml @@ -1,10 +1,9 @@ -version: "2.2" services: default: links: - localstack:localstack localstack: - image: localstack/localstack + image: localstack/localstack:4.14.0 ports: - "4566:4566" environment: diff --git a/services/re-registration-service/gradle/wrapper/gradle-wrapper.properties b/services/re-registration-service/gradle/wrapper/gradle-wrapper.properties index a5952066..5dc98dbc 100644 --- a/services/re-registration-service/gradle/wrapper/gradle-wrapper.properties +++ b/services/re-registration-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/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ActiveSuspensionsIntegrationTest.java b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ActiveSuspensionsIntegrationTest.java index 3576e4f3..4008bf77 100644 --- a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ActiveSuspensionsIntegrationTest.java +++ b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ActiveSuspensionsIntegrationTest.java @@ -1,6 +1,5 @@ package uk.nhs.prm.repo.re_registration; -import com.amazonaws.services.sqs.AmazonSQSAsync; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -9,6 +8,7 @@ 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 uk.nhs.prm.repo.re_registration.data.ActiveSuspensionsDb; import uk.nhs.prm.repo.re_registration.infra.LocalStackAwsConfig; import uk.nhs.prm.repo.re_registration.model.ActiveSuspensionsMessage; @@ -27,7 +27,7 @@ @ContextConfiguration(classes = LocalStackAwsConfig.class) public class ActiveSuspensionsIntegrationTest { @Autowired - private AmazonSQSAsync amazonSQSAsync; + private SqsClient sqs; @Autowired ActiveSuspensionsDb activeSuspensionsDb; @@ -38,9 +38,6 @@ public class ActiveSuspensionsIntegrationTest { @Value("${aws.reRegistrationsQueueName}") private String reRegistrationsQueueName; - @Autowired - private AmazonSQSAsync sqs; - private static final String NHS_NUMBER = "0987654321"; private static final String PREVIOUS_ODS_CODE = "OLD001"; private static final String NEWLY_REGISTERED_ODS_CODE = "NEW001"; @@ -77,8 +74,8 @@ void shouldDeleteRecordFromActiveSuspensionsDbWhenRecordFoundByNhsNumber() { } private void sendMessage(String queueName, String messageBody) { - var queueUrl = amazonSQSAsync.getQueueUrl(queueName).getQueueUrl(); - amazonSQSAsync.sendMessage(queueUrl, messageBody); + var queueUrl = sqs.getQueueUrl(builder -> builder.queueName(queueName)).queueUrl(); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(messageBody)); } private String getActiveSuspensionsMessage() { diff --git a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ReRegistrationsIntegrationTest.java b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ReRegistrationsIntegrationTest.java index c6b372dc..8d4de98d 100644 --- a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ReRegistrationsIntegrationTest.java +++ b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/ReRegistrationsIntegrationTest.java @@ -1,9 +1,5 @@ package uk.nhs.prm.repo.re_registration; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.model.CreateQueueRequest; -import com.amazonaws.services.sqs.model.Message; -import com.amazonaws.services.sqs.model.ReceiveMessageRequest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -12,6 +8,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.CreateQueueRequest; +import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; import uk.nhs.prm.repo.re_registration.infra.LocalStackAwsConfig; import uk.nhs.prm.repo.re_registration.logging.TestLogAppender; import uk.nhs.prm.repo.re_registration.message_publishers.ReRegistrationAuditPublisher; @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -32,7 +33,7 @@ public class ReRegistrationsIntegrationTest { @Autowired - private AmazonSQSAsync amazonSQSAsync; + private SqsClient sqs; @Autowired ReRegistrationAuditPublisher publisher; @@ -40,18 +41,14 @@ public class ReRegistrationsIntegrationTest { @Value("${aws.reRegistrationsQueueName}") private String reRegistrationsQueueName; - private String getReRegistrationsEvent() { return new ReRegistrationEvent("1234567890", "ABC123", UUID.randomUUID().toString(), "2017-11-01T15:00:33+00:00").toJsonString(); } private void createQueue(String queueName) { - CreateQueueRequest createQueueRequest = new CreateQueueRequest(); - createQueueRequest.setQueueName(queueName); - HashMap attributes = new HashMap<>(); - createQueueRequest.withAttributes(attributes); - amazonSQSAsync.createQueue(reRegistrationsQueueName); - + sqs.createQueue(CreateQueueRequest.builder() + .queueName(queueName) + .build()); } @Test @@ -68,29 +65,24 @@ void shouldReceiveAndLogAndAcknowledgeReRegistrationsEvent() { assertThat(receiveLog).isNotNull(); }); - var messages = receiveMessages(reRegistrationsQueueName); - assertThat(messages).isEmpty(); } - private void sendMessage(String queueName, String messageBody) { var queueUrl = getQueueUrl(queueName); - amazonSQSAsync.sendMessage(queueUrl, messageBody); + sqs.sendMessage(builder -> builder.queueUrl(queueUrl).messageBody(messageBody)); } private String getQueueUrl(String queueName) { - return amazonSQSAsync.getQueueUrl(queueName).getQueueUrl(); + return sqs.getQueueUrl(builder -> builder.queueName(queueName)).queueUrl(); } - @Test private List receiveMessages(String queueName) { - String queueUrl = amazonSQSAsync.getQueueUrl(queueName).getQueueUrl(); - - var receiveMessageRequest = new ReceiveMessageRequest().withQueueUrl(queueUrl); - return amazonSQSAsync.receiveMessage(receiveMessageRequest).getMessages(); + String queueUrl = getQueueUrl(queueName); + var receiveMessageRequest = ReceiveMessageRequest.builder() + .queueUrl(queueUrl) + .build(); + return sqs.receiveMessage(receiveMessageRequest).messages(); } - } - diff --git a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/delete_ehr/DeleteEhrIntegrationTest.java b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/delete_ehr/DeleteEhrIntegrationTest.java index 1d9afe75..68982e30 100644 --- a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/delete_ehr/DeleteEhrIntegrationTest.java +++ b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/delete_ehr/DeleteEhrIntegrationTest.java @@ -1,9 +1,5 @@ package uk.nhs.prm.repo.re_registration.delete_ehr; -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.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -20,6 +16,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.re_registration.data.ActiveSuspensionsDb; import uk.nhs.prm.repo.re_registration.infra.LocalStackAwsConfig; import uk.nhs.prm.repo.re_registration.model.ActiveSuspensionsMessage; @@ -30,17 +30,17 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.delete; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.matching; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @SpringBootTest() @ActiveProfiles("test") @ExtendWith(SpringExtension.class) -@ContextConfiguration( classes = LocalStackAwsConfig.class) +@ContextConfiguration(classes = LocalStackAwsConfig.class) @DirtiesContext public class DeleteEhrIntegrationTest { @@ -48,7 +48,7 @@ public class DeleteEhrIntegrationTest { public static final String NHS_NUMBER = "9999567890"; @Autowired - private AmazonSQSAsync sqs; + private SqsClient sqs; @Autowired ActiveSuspensionsDb activeSuspensionsDb; @@ -66,12 +66,11 @@ public class DeleteEhrIntegrationTest { private String reRegistrationsQueueUrl; private String reRegistrationsAuditUrl; - @BeforeEach public void setUp() { stubPdsAdaptor = initializeWebServer(); - reRegistrationsQueueUrl = sqs.getQueueUrl(reRegistrationsQueueName).getQueueUrl(); - reRegistrationsAuditUrl = sqs.getQueueUrl(reRegistrationsAuditQueueName).getQueueUrl(); + reRegistrationsQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(reRegistrationsQueueName)).queueUrl(); + reRegistrationsAuditUrl = sqs.getQueueUrl(builder -> builder.queueName(reRegistrationsAuditQueueName)).queueUrl(); stubResponses(); } @@ -79,7 +78,7 @@ public void setUp() { public void tearDown() { stubPdsAdaptor.resetAll(); stubPdsAdaptor.stop(); - sqs.purgeQueue(new PurgeQueueRequest(reRegistrationsAuditUrl)); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(reRegistrationsAuditUrl).build()); } private WireMockServer initializeWebServer() { @@ -91,10 +90,10 @@ private WireMockServer initializeWebServer() { @Test void shouldPutTheEHRDeleteAuditMessageOntoTheAuditQueueWhenActiveSuspensionExistsInDBAndPDSReturnsAStatusCode200() { activeSuspensionsDb.save(getActiveSuspensionsMessage()); - sqs.sendMessage(reRegistrationsQueueUrl, getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> { - String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).getBody(); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> { + String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).body(); System.out.println("Found message - " + messageBody); assertThat(messageBody).contains("\"status\":\"ACTION:RE_REGISTRATION_EHR_DELETED\""); @@ -103,13 +102,12 @@ void shouldPutTheEHRDeleteAuditMessageOntoTheAuditQueueWhenActiveSuspensionExist }); } - @Test void shouldPutTheUnknownReRegistrationsAuditMessageOntoTheAuditQueueWhenActiveSuspensionDoesNotExistInDBAndPDSReturnsAStatusCode200() { - sqs.sendMessage(reRegistrationsQueueUrl,getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> { - String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).getBody(); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> { + String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).body(); System.out.println("Found message - " + messageBody); assertThat(messageBody).contains("\"status\":\"NO_ACTION:UNKNOWN_REGISTRATION_EVENT_RECEIVED\""); }); @@ -121,17 +119,16 @@ private void stubResponses() { } private void setPds200SuccessState() { - stubFor(get(urlMatching("/suspended-patient-status/" + NHS_NUMBER)) - .withHeader("Authorization", matching("Basic cmUtcmVnaXN0cmF0aW9uLXNlcnZpY2U6ZGVmYXVsdA==")) - .inScenario("Retry Scenario") + stubPdsAdaptor.stubFor(get(urlEqualTo("/suspended-patient-status/" + NHS_NUMBER)) + .withHeader("Authorization", equalTo("Basic cmUtcmVnaXN0cmF0aW9uLXNlcnZpY2U6ZGVmYXVsdA==")) .willReturn(aResponse() .withStatus(200) - .withHeader("Content-Type", "text/xml") + .withHeader("Content-Type", "application/json") .withBody(getPdsResponseString().getBody()))); } private void ehrRepository200Response() { - stubFor(delete(urlMatching("/patients/" + NHS_NUMBER)) + stubPdsAdaptor.stubFor(delete(urlEqualTo("/patients/" + NHS_NUMBER)) .withHeader("Authorization", matching(authKey)) .willReturn(aResponse() .withStatus(200) @@ -151,13 +148,14 @@ private ReRegistrationEvent getReRegistrationEvent() { private List checkMessageInRelatedQueue(String queueUrl) { LOGGER.info("Checking SQS Queue: {}", queueUrl); - ReceiveMessageRequest requestForMessagesWithAttributes = new ReceiveMessageRequest() - .withQueueUrl(queueUrl) - .withMessageAttributeNames("traceId"); + ReceiveMessageRequest requestForMessagesWithAttributes = ReceiveMessageRequest.builder() + .queueUrl(queueUrl) + .messageAttributeNames("traceId") + .build(); final List messages = sqs .receiveMessage(requestForMessagesWithAttributes) - .getMessages(); + .messages(); LOGGER.info("Found {} messages on queue: {}", messages.size(), queueUrl); assertThat(messages).hasSize(1); diff --git a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/infra/LocalStackAwsConfig.java b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/infra/LocalStackAwsConfig.java index 4c1fb570..2b3c0357 100644 --- a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/infra/LocalStackAwsConfig.java +++ b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/infra/LocalStackAwsConfig.java @@ -1,13 +1,5 @@ package uk.nhs.prm.repo.re_registration.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.CreateQueueRequest; -import com.amazonaws.services.sqs.model.GetQueueAttributesResult; -import com.amazonaws.services.sqs.model.QueueDoesNotExistException; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -32,9 +24,12 @@ 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.CreateQueueRequest; +import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; +import software.amazon.awssdk.services.sqs.model.QueueAttributeName; +import software.amazon.awssdk.services.sqs.model.QueueDoesNotExistException; import java.net.URI; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -60,7 +55,7 @@ public class LocalStackAwsConfig { private String awsRegion; @Autowired - private AmazonSQSAsync amazonSQSAsync; + private SqsClient sqsClient; @Autowired private DynamoDbClient dynamoDbClient; @@ -69,18 +64,11 @@ public class LocalStackAwsConfig { private String activeSuspensionsDynamoDbTableName; @Bean - public static SqsClient sqsClient(@Value("${localstack.url}") String localstackUrl) throws URISyntaxException { + public static SqsClient sqsClient(@Value("${localstack.url}") String localstackUrl) { return SqsClient.builder() - .credentialsProvider((() -> AwsBasicCredentials.create("FAKE", "FAKE"))) - .endpointOverride(new URI(localstackUrl)) - .build(); - } - - @Bean - public static AmazonSQSAsync amazonSQSAsync(@Value("${localstack.url}") String localstackUrl) { - return AmazonSQSAsyncClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("FAKE", "FAKE"))) - .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(localstackUrl, "eu-west-2")) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("FAKE", "FAKE"))) + .endpointOverride(URI.create(localstackUrl)) + .region(Region.EU_WEST_2) .build(); } @@ -126,10 +114,12 @@ public String secretAccessKey() { @PostConstruct public void setupTestQueuesTopicsAndDb() { recreateReRegistrationsQueue(); - var reRegistrationsAuditQueue = amazonSQSAsync.createQueue(reRegistrationsAuditQueueName); + var reRegistrationsAuditQueue = sqsClient.createQueue( + CreateQueueRequest.builder().queueName(reRegistrationsAuditQueueName).build() + ); var topic = snsClient.createTopic(CreateTopicRequest.builder().name("re_registration_audit_sns_topic").build()); - createSnsTestReceiverSubscription(topic, getQueueArn(reRegistrationsAuditQueue.getQueueUrl())); + createSnsTestReceiverSubscription(topic, getQueueArn(reRegistrationsAuditQueue.queueUrl())); setupDbAndTable(); } @@ -186,11 +176,7 @@ private void recreateReRegistrationsQueue() { } private void createQueue(String queueName) { - CreateQueueRequest createQueueRequest = new CreateQueueRequest(); - createQueueRequest.setQueueName(queueName); - HashMap attributes = new HashMap<>(); - createQueueRequest.withAttributes(attributes); - amazonSQSAsync.createQueue(queueName); + sqsClient.createQueue(CreateQueueRequest.builder().queueName(queueName).build()); } private void createSnsTestReceiverSubscription(CreateTopicResponse topic, String queueArn) { @@ -215,12 +201,18 @@ private void ensureQueueDeleted(String queueName) { } private void deleteQueue(String queueName) { - amazonSQSAsync.deleteQueue(amazonSQSAsync.getQueueUrl(queueName).getQueueUrl()); + var queueUrl = sqsClient.getQueueUrl(builder -> builder.queueName(queueName)).queueUrl(); + sqsClient.deleteQueue(builder -> builder.queueUrl(queueUrl)); } 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/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/PdsAdaptorServiceIntegrationTest.java b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/PdsAdaptorServiceIntegrationTest.java index 0f3f07df..6084cb77 100644 --- a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/PdsAdaptorServiceIntegrationTest.java +++ b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/PdsAdaptorServiceIntegrationTest.java @@ -1,10 +1,5 @@ package uk.nhs.prm.repo.re_registration.pds; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.model.GetQueueAttributesResult; -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; @@ -19,16 +14,27 @@ 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.Message; +import software.amazon.awssdk.services.sqs.model.PurgeQueueRequest; +import software.amazon.awssdk.services.sqs.model.QueueAttributeName; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; import uk.nhs.prm.repo.re_registration.data.ActiveSuspensionsDb; import uk.nhs.prm.repo.re_registration.infra.LocalStackAwsConfig; import uk.nhs.prm.repo.re_registration.model.ActiveSuspensionsMessage; import uk.nhs.prm.repo.re_registration.model.ReRegistrationEvent; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @@ -36,15 +42,16 @@ @SpringBootTest() @ActiveProfiles("test") @ExtendWith(SpringExtension.class) -@ContextConfiguration( classes = LocalStackAwsConfig.class) +@ContextConfiguration(classes = LocalStackAwsConfig.class) @DirtiesContext public class PdsAdaptorServiceIntegrationTest { public static final String NHS_NUMBER = "1234567890"; public static final String STATUS_MESSAGE_FOR_WHEN_PATIENT_IS_STILL_SUSPENDED = "NO_ACTION:RE_REGISTRATION_FAILED_STILL_SUSPENDED"; public static final String STATUS_MESSAGE_FOR_WHEN_PDS_RETURNS_4XX_ERROR = "NO_ACTION:RE_REGISTRATION_FAILED_PDS_ERROR"; + @Autowired - private AmazonSQSAsync sqs; + private SqsClient sqs; @Value("${aws.reRegistrationsQueueName}") private String reRegistrationsQueueName; @@ -52,7 +59,7 @@ public class PdsAdaptorServiceIntegrationTest { @Value("${aws.reRegistrationsAuditQueueName}") private String reRegistrationsAuditQueueName; - WireMockServer stubPdsAdaptor; + private WireMockServer stubPdsAdaptor; private String reRegistrationsQueueUrl; private String reRegistrationsAuditUrl; private String nemsMessageId = "nemsMessageId"; @@ -63,8 +70,8 @@ public class PdsAdaptorServiceIntegrationTest { @BeforeEach public void setUp() { stubPdsAdaptor = initializeWebServer(); - reRegistrationsQueueUrl = sqs.getQueueUrl(reRegistrationsQueueName).getQueueUrl(); - reRegistrationsAuditUrl = sqs.getQueueUrl(reRegistrationsAuditQueueName).getQueueUrl(); + reRegistrationsQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(reRegistrationsQueueName)).queueUrl(); + reRegistrationsAuditUrl = sqs.getQueueUrl(builder -> builder.queueName(reRegistrationsAuditQueueName)).queueUrl(); activeSuspensionsDb.save(getActiveSuspensionsMessage()); } @@ -72,8 +79,8 @@ public void setUp() { public void tearDown() { stubPdsAdaptor.resetAll(); stubPdsAdaptor.stop(); - sqs.purgeQueue(new PurgeQueueRequest(reRegistrationsAuditUrl)); - sqs.purgeQueue(new PurgeQueueRequest(reRegistrationsQueueUrl)); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(reRegistrationsAuditUrl).build()); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(reRegistrationsQueueUrl).build()); } private WireMockServer initializeWebServer() { @@ -85,31 +92,31 @@ private WireMockServer initializeWebServer() { @Test void shouldRetryUpTo3TimesAndNotPutAnythingOnReRegistrationAuditTopicWhenPdsReturnsResponseWithStatusCode500() { setPdsRetryMessage(NHS_NUMBER); - sqs.sendMessage(reRegistrationsQueueUrl,getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> assertThat(isQueueEmpty(reRegistrationsAuditUrl)).isTrue()); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> verify(3, getRequestedFor(urlMatching("/suspended-patient-status/" + NHS_NUMBER)))); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> assertThat(isQueueEmpty(reRegistrationsAuditUrl)).isTrue()); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> verify(3, getRequestedFor(urlMatching("/suspended-patient-status/" + NHS_NUMBER)))); } @Test void shouldRetryWhenPdsReturnsResponseWithStatusCode500AndPublishOnReRegistrationAuditTopicOnce200IsReturned() { setPdsRetryMessageAndSucceed(NHS_NUMBER); - sqs.sendMessage(reRegistrationsQueueUrl,getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> { - String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).getBody(); - assertThat(messageBody).contains(STATUS_MESSAGE_FOR_WHEN_PATIENT_IS_STILL_SUSPENDED); - assertThat(messageBody).contains(nemsMessageId); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> { + String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).body(); + assertThat(messageBody).contains(STATUS_MESSAGE_FOR_WHEN_PATIENT_IS_STILL_SUSPENDED); + assertThat(messageBody).contains(nemsMessageId); }); } @Test void shouldPutTheAuditStatusMessageOnAuditTopicWhenPdsReturnsResponseWithStatusCode200() { setPds200SuccessState(null, 1, NHS_NUMBER); - sqs.sendMessage(reRegistrationsQueueUrl,getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> { - String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).getBody(); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> { + String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).body(); assertThat(messageBody).contains(STATUS_MESSAGE_FOR_WHEN_PATIENT_IS_STILL_SUSPENDED); assertThat(messageBody).contains(nemsMessageId); }); @@ -118,34 +125,34 @@ void shouldPutTheAuditStatusMessageOnAuditTopicWhenPdsReturnsResponseWithStatusC @Test void shouldPutTheAuditStatusMessageOnAuditTopicWhenPdsReturnsResponseWithStatusCode400() { setPdsErrorState(null, null, 1, NHS_NUMBER, 400); - sqs.sendMessage(reRegistrationsQueueUrl,getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> { - String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).getBody(); - assertThat(messageBody).contains(STATUS_MESSAGE_FOR_WHEN_PDS_RETURNS_4XX_ERROR); - assertThat(messageBody).contains(nemsMessageId); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> { + String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).body(); + assertThat(messageBody).contains(STATUS_MESSAGE_FOR_WHEN_PDS_RETURNS_4XX_ERROR); + assertThat(messageBody).contains(nemsMessageId); }); } private void setPds200SuccessState(String startingState, int priority, String nhsNumber) { - stubFor(get(urlMatching("/suspended-patient-status/" + nhsNumber)).atPriority(priority) - .withHeader("Authorization", matching("Basic cmUtcmVnaXN0cmF0aW9uLXNlcnZpY2U6ZGVmYXVsdA==")) + stubPdsAdaptor.stubFor(get(urlEqualTo("/suspended-patient-status/" + nhsNumber)).atPriority(priority) + .withHeader("Authorization", equalTo("Basic cmUtcmVnaXN0cmF0aW9uLXNlcnZpY2U6ZGVmYXVsdA==")) .inScenario("Retry Scenario") .whenScenarioStateIs(startingState) .willReturn(aResponse() .withStatus(200) - .withHeader("Content-Type", "text/xml") + .withHeader("Content-Type", "application/json") .withBody(getPdsResponseString().getBody()))); } private void setPdsErrorState(String startingState, String finishedState, int priority, String nhsNumber, int statusCode) { - stubFor(get(urlMatching("/suspended-patient-status/" + nhsNumber)).atPriority(priority) - .withHeader("Authorization", matching("Basic cmUtcmVnaXN0cmF0aW9uLXNlcnZpY2U6ZGVmYXVsdA==")) + stubPdsAdaptor.stubFor(get(urlEqualTo("/suspended-patient-status/" + nhsNumber)).atPriority(priority) + .withHeader("Authorization", equalTo("Basic cmUtcmVnaXN0cmF0aW9uLXNlcnZpY2U6ZGVmYXVsdA==")) .inScenario("Retry Scenario") .whenScenarioStateIs(startingState) .willReturn(aResponse() .withStatus(statusCode) - .withHeader("Content-Type", "text/xml") + .withHeader("Content-Type", "application/json") .withBody("Some content")) .willSetStateTo(finishedState)); } @@ -167,24 +174,33 @@ private ReRegistrationEvent getReRegistrationEvent() { } private boolean isQueueEmpty(String queueUrl) { - List attributeList = new ArrayList<>(); - attributeList.add("ApproximateNumberOfMessagesNotVisible"); - attributeList.add("ApproximateNumberOfMessages"); - GetQueueAttributesResult getQueueAttributesResult = sqs.getQueueAttributes(queueUrl, attributeList); + var getQueueAttributesResponse = sqs.getQueueAttributes(GetQueueAttributesRequest.builder() + .queueUrl(queueUrl) + .attributeNames( + QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE, + QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES + ) + .build()); - var numberOfMessageNotVisible = Integer.valueOf(getQueueAttributesResult.getAttributes().get("ApproximateNumberOfMessagesNotVisible")); - var numberOfMessageVisible = Integer.valueOf(getQueueAttributesResult.getAttributes().get("ApproximateNumberOfMessages")); + int numberOfMessageNotVisible = Integer.parseInt( + getQueueAttributesResponse.attributes().get(QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE) + ); + int numberOfMessageVisible = Integer.parseInt( + getQueueAttributesResponse.attributes().get(QueueAttributeName.APPROXIMATE_NUMBER_OF_MESSAGES) + ); - return (numberOfMessageVisible == 0 && numberOfMessageNotVisible == 0); + return numberOfMessageVisible == 0 && numberOfMessageNotVisible == 0; } 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(); + ReceiveMessageRequest 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; diff --git a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/ToggleCanNotSendEhrDeleteRequestTest.java b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/ToggleCanNotSendEhrDeleteRequestTest.java index 933b3071..8acb1451 100644 --- a/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/ToggleCanNotSendEhrDeleteRequestTest.java +++ b/services/re-registration-service/src/integration/java/uk/nhs/prm/repo/re_registration/pds/ToggleCanNotSendEhrDeleteRequestTest.java @@ -1,9 +1,5 @@ package uk.nhs.prm.repo.re_registration.pds; -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 org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -15,6 +11,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.re_registration.data.ActiveSuspensionsDb; import uk.nhs.prm.repo.re_registration.infra.LocalStackAwsConfig; import uk.nhs.prm.repo.re_registration.model.ActiveSuspensionsMessage; @@ -29,7 +29,7 @@ @SpringBootTest(properties = "toggle.canSendDeleteEhrRequest=false") @ActiveProfiles("test") @ExtendWith(SpringExtension.class) -@ContextConfiguration( classes = LocalStackAwsConfig.class) +@ContextConfiguration(classes = LocalStackAwsConfig.class) @DirtiesContext public class ToggleCanNotSendEhrDeleteRequestTest { @@ -37,7 +37,7 @@ public class ToggleCanNotSendEhrDeleteRequestTest { public static final String STATUS_FOR_RECEIVED_REGISTRATION_EVENT = "NO_ACTION:RE_REGISTRATION_EVENT_RECEIVED"; @Autowired - private AmazonSQSAsync sqs; + private SqsClient sqs; @Autowired private ActiveSuspensionsDb activeSuspensionsDb; @@ -52,26 +52,25 @@ public class ToggleCanNotSendEhrDeleteRequestTest { private String reRegistrationsAuditUrl; private String nemsMessageId = "nemsMessageId"; - @BeforeEach public void setUp() { - reRegistrationsQueueUrl = sqs.getQueueUrl(reRegistrationsQueueName).getQueueUrl(); - reRegistrationsAuditUrl = sqs.getQueueUrl(reRegistrationsAuditQueueName).getQueueUrl(); + reRegistrationsQueueUrl = sqs.getQueueUrl(builder -> builder.queueName(reRegistrationsQueueName)).queueUrl(); + reRegistrationsAuditUrl = sqs.getQueueUrl(builder -> builder.queueName(reRegistrationsAuditQueueName)).queueUrl(); } @AfterEach public void tearDown() { - sqs.purgeQueue(new PurgeQueueRequest(reRegistrationsAuditUrl)); + sqs.purgeQueue(PurgeQueueRequest.builder().queueUrl(reRegistrationsAuditUrl).build()); } @Test void shouldSendToAuditQueueAndNotProcessMessageWhenToggleIsFalseAndActiveSuspensionIsFound() { var activeSuspensionsMessage = new ActiveSuspensionsMessage(NHS_NUMBER, "previous-ods-code", "2017-11-01T15:00:33+00:00"); activeSuspensionsDb.save(activeSuspensionsMessage); - sqs.sendMessage(reRegistrationsQueueUrl,getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> { - String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).getBody(); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> { + String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).body(); assertThat(messageBody).contains(STATUS_FOR_RECEIVED_REGISTRATION_EVENT); assertThat(messageBody).contains(nemsMessageId); }); @@ -79,10 +78,10 @@ void shouldSendToAuditQueueAndNotProcessMessageWhenToggleIsFalseAndActiveSuspens @Test void shouldSendUnknownMessageToAuditQueueAndNotProcessMessageWhenToggleIsFalseAndActiveSuspensionNotIsFound() { - sqs.sendMessage(reRegistrationsQueueUrl,getReRegistrationEvent().toJsonString()); + sqs.sendMessage(builder -> builder.queueUrl(reRegistrationsQueueUrl).messageBody(getReRegistrationEvent().toJsonString())); - await().atMost(20, TimeUnit.SECONDS).untilAsserted(()-> { - String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).getBody(); + await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> { + String messageBody = checkMessageInRelatedQueue(reRegistrationsAuditUrl).get(0).body(); assertThat(messageBody).contains("NO_ACTION:UNKNOWN_REGISTRATION_EVENT_RECEIVED"); }); } @@ -94,13 +93,14 @@ private ReRegistrationEvent getReRegistrationEvent() { 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(); + ReceiveMessageRequest 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; } - } diff --git a/services/re-registration-service/src/integration/resources/logback-test.xml b/services/re-registration-service/src/integration/resources/logback-test.xml new file mode 100644 index 00000000..cc10d4a7 --- /dev/null +++ b/services/re-registration-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/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/config/SqsListenerSpringConfiguration.java b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/config/SqsListenerSpringConfiguration.java index a6da5a35..4787c556 100644 --- a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/config/SqsListenerSpringConfiguration.java +++ b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/config/SqsListenerSpringConfiguration.java @@ -4,8 +4,7 @@ import com.amazon.sqs.javamessaging.SQSConnection; 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 software.amazon.awssdk.services.sqs.SqsClient; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -17,9 +16,9 @@ import uk.nhs.prm.repo.re_registration.listener.ReRegistrationsEventListener; import uk.nhs.prm.repo.re_registration.parser.ActiveSuspensionsParser; -import javax.jms.JMSException; -import javax.jms.MessageConsumer; -import javax.jms.Session; +import jakarta.jms.JMSException; +import jakarta.jms.MessageConsumer; +import jakarta.jms.Session; @Configuration @RequiredArgsConstructor @@ -38,13 +37,13 @@ public class SqsListenerSpringConfiguration { private final ActiveSuspensionsParser activeSuspensionsParser; @Bean - public AmazonSQSAsync amazonSQSAsync() { - return AmazonSQSAsyncClientBuilder.defaultClient(); + public SqsClient sqsClient() { + return SqsClient.create(); } @Bean - public SQSConnection createConnection(AmazonSQSAsync amazonSQSAsync) throws JMSException { - SQSConnectionFactory connectionFactory = new SQSConnectionFactory(new ProviderConfiguration(), amazonSQSAsync); + public SQSConnection createConnection(SqsClient sqsClient) throws JMSException { + SQSConnectionFactory connectionFactory = new SQSConnectionFactory(new ProviderConfiguration(), sqsClient); return connectionFactory.createConnection(); } diff --git a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/config/Tracer.java b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/config/Tracer.java index 244472ba..7a7555e3 100644 --- a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/config/Tracer.java +++ b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/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/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponse.java b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponse.java index 4c3a5ecc..5d8ff482 100644 --- a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponse.java +++ b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponse.java @@ -1,7 +1,6 @@ package uk.nhs.prm.repo.re_registration.ehr_repo; import com.fasterxml.jackson.annotation.JsonProperty; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -10,9 +9,6 @@ @NoArgsConstructor @AllArgsConstructor public class EhrDeleteResponse { - @JsonProperty("data") - @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") public EhrDeleteResponseContent ehrDeleteResponseContent; - } diff --git a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponseContent.java b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponseContent.java index a3385cf6..d1acd142 100644 --- a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponseContent.java +++ b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/ehr_repo/EhrDeleteResponseContent.java @@ -1,6 +1,5 @@ package uk.nhs.prm.repo.re_registration.ehr_repo; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -11,10 +10,7 @@ @NoArgsConstructor @AllArgsConstructor public class EhrDeleteResponseContent { - @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") public String type; - @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") public String id; - @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") public List conversationIds; } diff --git a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListener.java b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListener.java index f8d30ec1..34824fd5 100644 --- a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListener.java +++ b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListener.java @@ -6,9 +6,9 @@ import uk.nhs.prm.repo.re_registration.handlers.ActiveSuspensionsHandler; import uk.nhs.prm.repo.re_registration.parser.ActiveSuspensionsParser; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.TextMessage; +import jakarta.jms.Message; +import jakarta.jms.MessageListener; +import jakarta.jms.TextMessage; @Slf4j @RequiredArgsConstructor diff --git a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListener.java b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListener.java index 82bd707f..283495f8 100644 --- a/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListener.java +++ b/services/re-registration-service/src/main/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListener.java @@ -5,9 +5,9 @@ import uk.nhs.prm.repo.re_registration.config.Tracer; import uk.nhs.prm.repo.re_registration.handlers.ReRegistrationsRetryHandler; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.TextMessage; +import jakarta.jms.Message; +import jakarta.jms.MessageListener; +import jakarta.jms.TextMessage; @Slf4j @RequiredArgsConstructor diff --git a/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/config/TracerTest.java b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/config/TracerTest.java index beac6955..a9496e76 100644 --- a/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/config/TracerTest.java +++ b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/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; import static org.assertj.core.api.Assertions.assertThat; diff --git a/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListenerTest.java b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListenerTest.java index 2a4bdfd2..99eb9243 100644 --- a/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListenerTest.java +++ b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ActiveSuspensionsMessageListenerTest.java @@ -11,7 +11,7 @@ import uk.nhs.prm.repo.re_registration.model.ActiveSuspensionsMessage; import uk.nhs.prm.repo.re_registration.parser.ActiveSuspensionsParser; -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/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListenerTest.java b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListenerTest.java index ecb274db..5ff84d3f 100644 --- a/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListenerTest.java +++ b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/listener/ReRegistrationsEventListenerTest.java @@ -9,7 +9,7 @@ import uk.nhs.prm.repo.re_registration.config.Tracer; import uk.nhs.prm.repo.re_registration.handlers.ReRegistrationsRetryHandler; -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/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/utility/TestDataUtility.java b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/utility/TestDataUtility.java index 27551aae..0a5b6d5d 100644 --- a/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/utility/TestDataUtility.java +++ b/services/re-registration-service/src/test/java/uk/nhs/prm/repo/re_registration/utility/TestDataUtility.java @@ -1,8 +1,7 @@ package uk.nhs.prm.repo.re_registration.utility; - -import org.joda.time.DateTime; -import wiremock.org.apache.commons.lang3.RandomStringUtils; +import java.time.Instant; +import java.util.UUID; public final class TestDataUtility { public static String UNESCAPED_HTML = ""; @@ -10,11 +9,11 @@ public final class TestDataUtility { public static String NHS_NUMBER = "9745812541"; public static String getRandomTimestamp() { - return DateTime.now().toDateTimeISO().toString(); + return Instant.now().toString(); } public static String getRandomOdsCode() { - return RandomStringUtils.randomAlphanumeric(6); + return UUID.randomUUID().toString().replace("-", "").substring(0, 6); } private TestDataUtility() { } diff --git a/services/re-registration-service/tasks b/services/re-registration-service/tasks index 0c211a5d..f74ad657 100755 --- a/services/re-registration-service/tasks +++ b/services/re-registration-service/tasks @@ -9,30 +9,6 @@ set -Eeo pipefail AWS_DEFAULT_REGION=eu-west-2 export NHS_SERVICE=re-registration-service IMAGE_REPO_NAME=repo/$NHS_SERVICE -AWS_HELPERS_VERSION=0.2.27 -echo "AWS helper scripts version: $AWS_HELPERS_VERSION" - -########################### -# Shared utils # -########################### - -function download_util() { - local UTIL_VERSION=$1 - local UTIL_FILENAME=$2 - - local UTIL_FILEPATH="utils/$UTIL_VERSION/$UTIL_FILENAME" - - mkdir -p "utils/$UTIL_VERSION" - if [[ ! -f $UTIL_FILEPATH ]];then - wget --quiet -O $UTIL_FILEPATH https://github.com/nhsconnect/prm-deductions-support-infra/releases/download/${UTIL_VERSION}/${UTIL_FILENAME} - fi - chmod +x $UTIL_FILEPATH - - echo "$UTIL_FILEPATH" -} - -AWS_HELPERS_FILE=$(download_util $AWS_HELPERS_VERSION aws-helpers) -source $AWS_HELPERS_FILE #################################### # Instance (Environment) Variables # @@ -45,19 +21,11 @@ function check_env { 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 { +function configure_local_envs { export LOCALSTACK_URL="http://localhost:4566" export AWS_REGION="eu-west-2" export AWS_DEFAULT_REGION="eu-west-2" @@ -73,21 +41,22 @@ function configure_sonar_environment_variable { export SONAR_TOKEN=$(_get_aws_ssm_secret "/repo/dev/output/re-registration-service/sonar_token") } -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 +############# +# FUNCTIONS # +############# +function start_localstack { + echo "################################" + echo "##### Starting Localstack ######" + echo "################################" + docker compose -f docker-compose.localstack-local.yaml up -d } +function stop_localstack { + echo "################################" + echo "##### Stopping Localstack ######" + echo "################################" + docker compose -f docker-compose.localstack-local.yaml down +} ########### ## TASKS ## @@ -95,17 +64,12 @@ function destroy_localstack { command="$1" case "${command}" in - destroy_localstack) - destroy_localstack + start_localstack) + configure_local_envs + start_localstack ;; - build_docker) - configure_envs - ./tasks build - configure_docker_repository_uri - fetch_redaction_utils - build_docker_image - echo "Pushing the Docker image... $REPOSITORY_URI:$IMAGE_TAG" - docker push $REPOSITORY_URI:$IMAGE_TAG + stop_localstack) + stop_localstack ;; build) rm -rf build/ @@ -115,69 +79,39 @@ case "${command}" in ./gradlew test ;; test_integration) - configure_envs - destroy_localstack + configure_local_envs + start_localstack ./gradlew --info integration + stop_localstack ;; test_coverage) - configure_envs - destroy_localstack + configure_local_envs + start_localstack ./gradlew jacocoTestCoverageVerification + stop_localstack ;; code_quality) - destroy_localstack + start_localstack ./gradlew check -x test -x integration + stop_localstack ;; test_all) - configure_envs + configure_local_envs + start_localstack ./gradlew test integration jacocoTestCoverageVerification check + stop_localstack ;; run_sonar) - configure_envs + configure_local_envs _assume_environment_role $NHS_ENVIRONMENT configure_sonar_environment_variable - destroy_localstack + start_localstack ./gradlew build sonar --info + stop_localstack ;; run_local) - configure_envs + configure_local_envs ./gradlew bootRun ;; - start_localstack) - docker-compose -f docker-compose.localstack-local.yaml up -d - ;; - tf) - check_env - _assume_environment_role $NHS_ENVIRONMENT - tf_init - bash - ;; - 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} - ;; - *) - echo "Invalid command: '${command}'" - exit 1 - ;; esac set +e