Skip to content

Commit

Permalink
RWA-2310: Springboot upgrade (#709)
Browse files Browse the repository at this point in the history
* RWA-2310: Springboot upgrade

* Fixed case event message entity issue

* CcdRetryableClient import issue fixed

* Feign issue fixed.

* Junit upgrades

* Feignclient issue fix

* FeignClients config added

* Imports added

* Feign Client config updated

* Fixed test issues

* Removed unused constants

* removed properties-volume-spring-boot-starter deprecated dependancy
  • Loading branch information
adityadwadasi authored Aug 8, 2024
1 parent 8b0ef3c commit 2eed165
Show file tree
Hide file tree
Showing 21 changed files with 297 additions and 115 deletions.
31 changes: 17 additions & 14 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ plugins {
id 'pmd'
id 'jacoco'
id 'io.spring.dependency-management' version '1.1.6'
id 'org.springframework.boot' version '2.7.18'
id 'org.springframework.boot' version '3.3.0'
id 'org.owasp.dependencycheck' version '10.0.2'
id 'com.github.ben-manes.versions' version '0.48.0'
id 'uk.gov.hmcts.java' version '0.12.63'
Expand Down Expand Up @@ -239,7 +239,7 @@ dependencyManagement {
dependency group: 'org.glassfish', name: 'jakarta.el', version: '4.0.2'

//CVE-2021-42550
dependencySet(group: 'ch.qos.logback', version: '1.2.13') {
dependencySet(group: 'ch.qos.logback', version: '1.5.6') {
entry 'logback-classic'
entry 'logback-core'
}
Expand Down Expand Up @@ -277,7 +277,7 @@ dependencyManagement {
entry 'selenium-support'
}

dependencySet(group: 'org.springframework.security', version: '5.8.13') {
dependencySet(group: 'org.springframework.security', version: '6.0.8') {
entry 'spring-security-core'
entry 'spring-security-acl'
entry 'spring-security-aspects'
Expand Down Expand Up @@ -311,16 +311,16 @@ repositories {
def versions = [
junit : '5.10.3',
junitPlatform: '1.10.3',
reformLogging: '6.0.1',
springDoc : '1.7.0',
springBoot : '2.7.18',
serenity : '3.1.20',
reformLogging: '6.1.4',
springDoc : '2.2.0',
springBoot : '3.3.0',
serenity : '3.4.2',
gradlePitest : '1.9.11',
pitest : '1.15.0',
sonarPitest : '0.5',
logbook : '2.16.0',
tomcat : '9.0.83',
log4j : '2.17.2',
logbook : '3.9.0',
tomcat : '10.1.16',
log4j : '2.23.1',
retry : '2.0.7'
]

Expand Down Expand Up @@ -348,16 +348,20 @@ dependencies {
implementation group: 'org.springframework.security', name: 'spring-security-rsa', version: '1.1.5'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: versions.springBoot
implementation group: 'org.springframework.retry', name: 'spring-retry', version: versions.retry
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign', version: '3.1.9'
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign', version: '4.1.1'

implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: versions.springDoc
implementation group: 'org.apache.httpcomponents.client5', name: 'httpclient5', version: '5.3.1'

implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: versions.springDoc

implementation group: 'org.zalando', name: 'logbook-core', version: versions.logbook
implementation group: 'org.zalando', name: 'logbook-spring-boot-starter', version: versions.logbook
implementation group: 'org.zalando', name: 'logbook-httpclient5', version: versions.logbook

implementation group: 'com.github.hmcts.java-logging', name: 'logging', version: versions.reformLogging
implementation group: 'com.github.hmcts.java-logging', name: 'logging-appinsights', version: versions.reformLogging

implementation group: 'com.github.hmcts', name: 'service-auth-provider-java-client', version: '3.1.4'
implementation group: 'com.github.hmcts', name: 'service-auth-provider-java-client', version: '5.1.2'
implementation group: 'com.github.hmcts', name: 'core-case-data-store-client', version: '4.9.2'
implementation group: 'com.azure', name: 'azure-messaging-servicebus', version: '7.15.0'
implementation group: 'io.projectreactor.netty', name: 'reactor-netty-http', version: '1.1.21'
Expand Down Expand Up @@ -410,7 +414,6 @@ dependencies {

implementation group: 'org.flywaydb', name: 'flyway-core', version: '8.5.13'
implementation group: 'com.zaxxer', name: 'HikariCP', version: '5.0.1'
implementation group: 'com.vladmihalcea', name: 'hibernate-types-52', version: '2.21.1'

implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.15.2'
runtimeOnly group: 'org.postgresql', name: 'postgresql', version: '42.7.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

import com.azure.messaging.servicebus.ServiceBusClientBuilder;
import com.azure.messaging.servicebus.ServiceBusSenderClient;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;

@Configuration
@ConditionalOnExpression("${azure.servicebus.enableASB-DLQ:true}")
public class CcdEventPublisherConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -367,37 +365,6 @@ void should_store_parsing_error_unprocessable_message_and_return_200_ok() throws
assertEquals(unprocessableMessage, response.getMessageContent(), "Valid message should be returned");
}

@ParameterizedTest
@MethodSource("uk.gov.hmcts.reform.wacaseeventhandler.controllers.CaseEventHandlerControllerEndpointTest"
+ "#provideInvalidMessages")
void should_store_invalid_unprocessable_message_and_return_200_ok(String invalidMessage) throws Exception {
String messageId = randomMessageId();

MvcResult result = mockMvc.perform(post("/messages/"
+ messageId
+ "?from_dlq=false&session_id="
+ CASE_REFERENCE)
.contentType(MediaType.APPLICATION_JSON)
.content(invalidMessage))
.andExpect(status().isCreated())
.andReturn();

String content = result.getResponse().getContentAsString();
assertEquals(201, result.getResponse().getStatus(), content);
assertNotNull(content, "Content Should not be null");

CaseEventMessage response = OBJECT_MAPPER.readValue(content, CaseEventMessage.class);
assertNotNull(response, "Response should not be null");
assertEquals(messageId, response.getMessageId(), "Valid MessageId should be returned");
assertNotNull(response.getSequence(), "Valid sequence should be returned");
assertEquals(CASE_REFERENCE, response.getCaseId(), "Valid CaseId should be returned");
assertEquals(false, response.getFromDlq(), "Valid FromDlq should be returned");
assertEquals(MessageState.UNPROCESSABLE, response.getState(), "Valid State should be returned");
assertNotNull(response.getReceived(), "Valid Received should be returned");
assertEquals(0, response.getDeliveryCount(), "Valid DeliveryCount should be returned");
assertEquals(invalidMessage, response.getMessageContent(), "Valid message should be returned");
}

@NotNull
private String randomMessageId() {
return UUID.randomUUID().toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package uk.gov.hmcts.reform.wacaseeventhandler.controllers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import uk.gov.hmcts.reform.authorisation.generators.AuthTokenGenerator;
import uk.gov.hmcts.reform.wacaseeventhandler.clients.WorkflowApiClient;
import uk.gov.hmcts.reform.wacaseeventhandler.domain.camunda.request.EvaluateDmnRequest;
import uk.gov.hmcts.reform.wacaseeventhandler.domain.camunda.response.CancellationEvaluateResponse;
import uk.gov.hmcts.reform.wacaseeventhandler.domain.camunda.response.EvaluateDmnResponse;
import uk.gov.hmcts.reform.wacaseeventhandler.domain.model.CaseEventMessage;
import uk.gov.hmcts.reform.wacaseeventhandler.entity.MessageState;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static uk.gov.hmcts.reform.wacaseeventhandler.domain.camunda.DmnValue.dmnStringValue;

@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
@ActiveProfiles(profiles = {"db", "integration"})
class CaseEventHandlerControllerInvalidMessageTest {
protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE)
.registerModule(new JavaTimeModule())
.registerModule(new Jdk8Module());

public static final String S2S_TOKEN = "Bearer s2s token";
public static final String TENANT_ID = "ia";
public static final String CANCELLATION_DMN_TABLE = "wa-task-cancellation-ia-asylum";
public static final String CASE_REFERENCE = "some case reference";
public static final LocalDateTime EVENT_TIME_STAMP = LocalDateTime.now();

@MockBean
private AuthTokenGenerator authTokenGenerator;

@MockBean
private WorkflowApiClient workflowApiClient;

@Autowired
private MockMvc mockMvc;

@BeforeEach
void setUp() {
when(authTokenGenerator.generate()).thenReturn(S2S_TOKEN);
setUpMocks();
}

@Nested
class CaseEventHandlerControllerPostMessageEndpointTest {

@ParameterizedTest
@MethodSource("uk.gov.hmcts.reform.wacaseeventhandler.controllers.CaseEventHandlerControllerEndpointTest"
+ "#provideInvalidMessages")
void should_store_invalid_unprocessable_message_and_return_200_ok(String invalidMessage) throws Exception {
String messageId = randomMessageId();

MvcResult result = mockMvc.perform(post("/messages/"
+ messageId
+ "?from_dlq=false&session_id="
+ CASE_REFERENCE)
.contentType(MediaType.APPLICATION_JSON)
.content(invalidMessage))
.andExpect(status().isCreated())
.andReturn();

String content = result.getResponse().getContentAsString();
assertEquals(201, result.getResponse().getStatus(), content);
assertNotNull(content, "Content Should not be null");

CaseEventMessage response = OBJECT_MAPPER.readValue(content, CaseEventMessage.class);
assertNotNull(response, "Response should not be null");
assertEquals(messageId, response.getMessageId(), "Valid MessageId should be returned");
assertNotNull(response.getSequence(), "Valid sequence should be returned");
assertEquals(CASE_REFERENCE, response.getCaseId(), "Valid CaseId should be returned");
assertEquals(false, response.getFromDlq(), "Valid FromDlq should be returned");
assertEquals(MessageState.UNPROCESSABLE, response.getState(), "Valid State should be returned");
assertNotNull(response.getReceived(), "Valid Received should be returned");
assertEquals(0, response.getDeliveryCount(), "Valid DeliveryCount should be returned");
assertEquals(invalidMessage, response.getMessageContent(), "Valid message should be returned");
}

@NotNull
private String randomMessageId() {
return UUID.randomUUID().toString();
}

}

private void setUpMocks() {
mockCancellationHandler();
mockWarningHandler();
mockWarningHandlerWithMultipleCategories();
}

private void mockCancellationHandler() {
List<CancellationEvaluateResponse> results = List.of(new CancellationEvaluateResponse(
dmnStringValue("Cancel"), null, null,
null,
dmnStringValue("some category")
));

EvaluateDmnResponse<CancellationEvaluateResponse> cancellationResponse = new EvaluateDmnResponse<>(results);

doReturn(cancellationResponse).when(workflowApiClient).evaluateCancellationDmn(
eq(S2S_TOKEN),
eq(CANCELLATION_DMN_TABLE),
eq(TENANT_ID),
any(EvaluateDmnRequest.class));

}

private void mockWarningHandler() {
List<CancellationEvaluateResponse> results = List.of(new CancellationEvaluateResponse(
dmnStringValue("Warn"), null, null,
null,
dmnStringValue("some category")
));

EvaluateDmnResponse<CancellationEvaluateResponse> cancellationResponse = new EvaluateDmnResponse<>(results);

doReturn(cancellationResponse).when(workflowApiClient).evaluateCancellationDmn(
eq(S2S_TOKEN),
eq(CANCELLATION_DMN_TABLE),
eq(TENANT_ID),
any(EvaluateDmnRequest.class));
}

private void mockWarningHandlerWithMultipleCategories() {
List<CancellationEvaluateResponse> results = List.of(new CancellationEvaluateResponse(
dmnStringValue("Warn"), null, null,
null,
dmnStringValue("some category, some other category")
));
EvaluateDmnResponse<CancellationEvaluateResponse> cancellationResponse = new EvaluateDmnResponse<>(results);

doReturn(cancellationResponse).when(workflowApiClient).evaluateCancellationDmn(
eq(S2S_TOKEN),
eq(CANCELLATION_DMN_TABLE),
eq(TENANT_ID),
any(EvaluateDmnRequest.class));
}

public static Stream<String> provideInvalidMessages() {
return Stream.of(
"{\n"
+ " \"EventInstanceId\" : \"some event instance Id\",\n"
+ " \"EventTimeStamp\" : \"" + EVENT_TIME_STAMP + "\",\n"
+ " \"InvalidField\" : \"data\",\n"
+ " \"CaseTypeId\" : \"asylum\",\n"
+ " \"EventId\" : \"some event Id\",\n"
+ " \"NewStateId\" : \"some new state Id\",\n"
+ " \"UserId\" : \"some user Id\",\n"
+ " \"MessageProperties\" : {\n"
+ " \"property1\" : \"test1\"\n"
+ " }\n"
+ "}",
"{\n"
+ " \"EventInstanceId\" : \"some event instance Id\",\n"
+ " \"CaseId\" : " + CASE_REFERENCE + ",\n"
+ " \"InvalidField\" : \"data\",\n"
+ " \"CaseTypeId\" : \"asylum\",\n"
+ " \"EventId\" : \"some event Id\",\n"
+ " \"NewStateId\" : \"some new state Id\",\n"
+ " \"UserId\" : \"some user Id\",\n"
+ " \"MessageProperties\" : {\n"
+ " \"property1\" : \"test1\"\n"
+ " }\n"
+ "}"
);
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@
import org.springframework.retry.annotation.EnableRetry;

@SpringBootApplication
@EnableFeignClients
@EnableRetry
@SuppressWarnings("HideUtilityClassConstructor") // Spring needs a constructor, its not a utility class
@EnableFeignClients(basePackages =
{
"uk.gov.hmcts.reform.ccd.client",
"uk.gov.hmcts.reform.wacaseeventhandler.clients",
"uk.gov.hmcts.reform.wacaseeventhandler.services.holidaydates",
"uk.gov.hmcts.reform.wacaseeventhandler.entities.idam",
"uk.gov.hmcts.reform.wacaseeventhandler.services"
})
public class Application {

public static void main(final String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.zalando.logbook.HeaderFilter;
import org.zalando.logbook.HeaderFilters;
import org.zalando.logbook.core.HeaderFilters;
import org.zalando.logbook.json.JsonHttpLogFormatter;

@Configuration
Expand Down
Loading

0 comments on commit 2eed165

Please sign in to comment.