Skip to content

Commit c5c8858

Browse files
authored
CDPS-1096: Upgrade spring boot to 3.4.1 (#18)
* CDPS-1096: Upgrade spring boot to 3.4.1 * CDPS-1096: Fixing linting issues * CDPS-1096: Updating ktlint version to 1.5.0 * CDPS-1096: Reverting to use Kotlin 2.0.21
1 parent c133203 commit c5c8858

File tree

20 files changed

+128
-107
lines changed

20 files changed

+128
-107
lines changed

.github/workflows/security_owasp.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
jobs:
77
security-kotlin-owasp-check:
88
name: Kotlin security OWASP dependency check
9-
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_owasp.yml@v1 # WORKFLOW_VERSION
9+
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_owasp.yml@v2 # WORKFLOW_VERSION
1010
with:
1111
channel_id: ${{ vars.SECURITY_ALERTS_SLACK_CHANNEL_ID || 'NO_SLACK' }}
1212
secrets: inherit

.github/workflows/security_trivy.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
jobs:
77
security-kotlin-trivy-check:
88
name: Project security trivy dependency check
9-
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_trivy.yml@v1 # WORKFLOW_VERSION
9+
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_trivy.yml@v2 # WORKFLOW_VERSION
1010
with:
1111
channel_id: ${{ vars.SECURITY_ALERTS_SLACK_CHANNEL_ID || 'NO_SLACK' }}
1212
secrets: inherit

.github/workflows/security_veracode_pipeline_scan.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
jobs:
77
security-veracode-pipeline-scan:
88
name: Project security veracode pipeline scan
9-
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_veracode_pipeline_scan.yml@v1 # WORKFLOW_VERSION
9+
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_veracode_pipeline_scan.yml@v2 # WORKFLOW_VERSION
1010
with:
1111
channel_id: ${{ vars.SECURITY_ALERTS_SLACK_CHANNEL_ID || 'NO_SLACK' }}
1212
secrets: inherit

.github/workflows/security_veracode_policy_scan.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
jobs:
77
security-veracode-policy-check:
88
name: Project security veracode policy scan
9-
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_veracode_policy_scan.yml@v1 # WORKFLOW_VERSION
9+
uses: ministryofjustice/hmpps-github-actions/.github/workflows/security_veracode_policy_scan.yml@v2 # WORKFLOW_VERSION
1010
with:
1111
channel_id: ${{ vars.SECURITY_ALERTS_SLACK_CHANNEL_ID || 'NO_SLACK' }}
1212
secrets: inherit

.sdkmanrc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Enable auto-env through the sdkman_auto_env config
2+
# Add key=value pairs of SDKs to use below
3+
java=21.0.5-tem

.trivyignore

+3
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
# Suppression for h2 2.1.214 password on command line vulnerability
1111
# can be suppressed as we only run h2 locally and not on build environments
1212
CVE-2022-45868
13+
# Suppression for tomcat vulnerability affecting jsp compilation in the default servlet
14+
# can be suppressed as we do not use the default servlet and haven't configured it for write either
15+
CVE-2024-50379

build.gradle.kts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
plugins {
2-
id("uk.gov.justice.hmpps.gradle-spring-boot") version "6.0.9"
2+
id("uk.gov.justice.hmpps.gradle-spring-boot") version "6.1.2"
33
kotlin("plugin.spring") version "2.0.21"
44
}
55

@@ -8,12 +8,12 @@ configurations {
88
}
99

1010
dependencies {
11-
implementation("uk.gov.justice.service.hmpps:hmpps-kotlin-spring-boot-starter:1.0.8")
11+
implementation("uk.gov.justice.service.hmpps:hmpps-kotlin-spring-boot-starter:1.1.1")
1212
implementation("org.springframework.boot:spring-boot-starter-webflux")
13-
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0")
13+
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.0")
1414

15-
testImplementation("uk.gov.justice.service.hmpps:hmpps-kotlin-spring-boot-starter-test:1.0.8")
16-
testImplementation("org.wiremock:wiremock-standalone:3.9.1")
15+
testImplementation("uk.gov.justice.service.hmpps:hmpps-kotlin-spring-boot-starter-test:1.1.1")
16+
testImplementation("org.wiremock:wiremock-standalone:3.10.0")
1717
testImplementation("io.swagger.parser.v3:swagger-parser:2.1.24") {
1818
exclude(group = "io.swagger.core.v3")
1919
}

gradle/wrapper/gradle-wrapper.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

helm_deploy/hmpps-person-integration-api/Chart.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ name: hmpps-person-integration-api
55
version: 0.2.0
66
dependencies:
77
- name: generic-service
8-
version: "3.7"
8+
version: "3.8"
99
repository: https://ministryofjustice.github.io/hmpps-helm-charts
1010
- name: generic-prometheus-alerts
1111
version: "1.11"

readme/build_test_run.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
## Building
55

6+
To use the same version of Java locally as is used in CI and production, follow [these notes](sdkman.md).
7+
68
To build the project without tests run:
79

810
```

readme/sdkman.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[< Back](./building_and_running.md)
2+
---
3+
4+
## sdkman
5+
6+
It is recommended to use [sdkman](https://sdkman.io/) to ensure that you are running the same version of Java that is
7+
used in CI and in production.
8+
9+
To do this on a mac:
10+
11+
```shell
12+
curl -s "https://get.sdkman.io" | bash
13+
```
14+
15+
Close the terminal and reopen. Then run **within the repository folder**:
16+
17+
```shell
18+
sdk env
19+
```
20+
21+
This will pick up the `.sdkmanrc` file which contains the java version that should be used.
22+
23+
To enable sdkman to automatically switch you to the correct java version when changing directory in the terminal,
24+
edit `~/.sdkman/etc/config` and set `sdkman_auto_env=true`

src/main/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/common/config/HmppsPersonIntegrationApiExceptionHandler.kt

+50-55
Original file line numberDiff line numberDiff line change
@@ -46,69 +46,64 @@ class HmppsPersonIntegrationApiExceptionHandler {
4646
}
4747

4848
@ExceptionHandler(HttpMessageNotReadableException::class)
49-
fun handleValidationException(ex: HttpMessageNotReadableException): ResponseEntity<ErrorResponse> =
50-
ResponseEntity
51-
.status(BAD_REQUEST)
52-
.body(
53-
ErrorResponse(
54-
status = BAD_REQUEST,
55-
userMessage = "Unable to read the request",
56-
developerMessage = ex.message,
57-
),
58-
).also { log.info(ex.message) }
49+
fun handleValidationException(ex: HttpMessageNotReadableException): ResponseEntity<ErrorResponse> = ResponseEntity
50+
.status(BAD_REQUEST)
51+
.body(
52+
ErrorResponse(
53+
status = BAD_REQUEST,
54+
userMessage = "Unable to read the request",
55+
developerMessage = ex.message,
56+
),
57+
).also { log.info(ex.message) }
5958

6059
@ExceptionHandler(HandlerMethodValidationException::class)
61-
fun handleHandlerMethodValidationException(e: HandlerMethodValidationException): ResponseEntity<ErrorResponse> =
62-
e.allErrors.map { it.toString() }.distinct().sorted().joinToString("\n")
63-
.let { validationErrors ->
64-
ResponseEntity
65-
.status(BAD_REQUEST)
66-
.body(
67-
ErrorResponse(
68-
status = BAD_REQUEST,
69-
userMessage = "Validation failure(s): ${
70-
e.allErrors.map { it.defaultMessage }.distinct().sorted().joinToString("\n")
71-
}",
72-
developerMessage = "${e.message} $validationErrors",
73-
),
74-
).also { log.info("Validation exception: $validationErrors\n {}", e.message) }
75-
}
60+
fun handleHandlerMethodValidationException(e: HandlerMethodValidationException): ResponseEntity<ErrorResponse> = e.allErrors.map { it.toString() }.distinct().sorted().joinToString("\n")
61+
.let { validationErrors ->
62+
ResponseEntity
63+
.status(BAD_REQUEST)
64+
.body(
65+
ErrorResponse(
66+
status = BAD_REQUEST,
67+
userMessage = "Validation failure(s): ${
68+
e.allErrors.map { it.defaultMessage }.distinct().sorted().joinToString("\n")
69+
}",
70+
developerMessage = "${e.message} $validationErrors",
71+
),
72+
).also { log.info("Validation exception: $validationErrors\n {}", e.message) }
73+
}
7674

7775
@ExceptionHandler(ValidationException::class)
78-
fun handleValidationException(e: ValidationException): ResponseEntity<ErrorResponse> =
79-
ResponseEntity
80-
.status(BAD_REQUEST)
81-
.body(
82-
ErrorResponse(
83-
status = BAD_REQUEST,
84-
userMessage = "Validation failure: ${e.message}",
85-
developerMessage = e.message,
86-
),
87-
).also { log.info("Validation exception: {}", e.message) }
76+
fun handleValidationException(e: ValidationException): ResponseEntity<ErrorResponse> = ResponseEntity
77+
.status(BAD_REQUEST)
78+
.body(
79+
ErrorResponse(
80+
status = BAD_REQUEST,
81+
userMessage = "Validation failure: ${e.message}",
82+
developerMessage = e.message,
83+
),
84+
).also { log.info("Validation exception: {}", e.message) }
8885

8986
@ExceptionHandler(NoResourceFoundException::class)
90-
fun handleNoResourceFoundException(e: NoResourceFoundException): ResponseEntity<ErrorResponse> =
91-
ResponseEntity
92-
.status(NOT_FOUND)
93-
.body(
94-
ErrorResponse(
95-
status = NOT_FOUND,
96-
userMessage = "No resource found failure: ${e.message}",
97-
developerMessage = e.message,
98-
),
99-
).also { log.info("No resource found exception: {}", e.message) }
87+
fun handleNoResourceFoundException(e: NoResourceFoundException): ResponseEntity<ErrorResponse> = ResponseEntity
88+
.status(NOT_FOUND)
89+
.body(
90+
ErrorResponse(
91+
status = NOT_FOUND,
92+
userMessage = "No resource found failure: ${e.message}",
93+
developerMessage = e.message,
94+
),
95+
).also { log.info("No resource found exception: {}", e.message) }
10096

10197
@ExceptionHandler(AccessDeniedException::class)
102-
fun handleAccessDeniedException(e: AccessDeniedException): ResponseEntity<ErrorResponse> =
103-
ResponseEntity
104-
.status(FORBIDDEN)
105-
.body(
106-
ErrorResponse(
107-
status = FORBIDDEN,
108-
userMessage = "Forbidden: ${e.message}",
109-
developerMessage = e.message,
110-
),
111-
).also { log.debug("Forbidden (403) returned: {}", e.message) }
98+
fun handleAccessDeniedException(e: AccessDeniedException): ResponseEntity<ErrorResponse> = ResponseEntity
99+
.status(FORBIDDEN)
100+
.body(
101+
ErrorResponse(
102+
status = FORBIDDEN,
103+
userMessage = "Forbidden: ${e.message}",
104+
developerMessage = e.message,
105+
),
106+
).also { log.debug("Forbidden (403) returned: {}", e.message) }
112107

113108
@ExceptionHandler(Exception::class)
114109
fun handleException(e: Exception): ResponseEntity<ErrorResponse> = ResponseEntity

src/main/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/common/config/OpenApiConfiguration.kt

+4-6
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,8 @@ class OpenApiConfiguration(
7272
}
7373

7474
@Bean
75-
fun v1Api(): GroupedOpenApi {
76-
return GroupedOpenApi.builder()
77-
.group("v1")
78-
.pathsToMatch("/v1/**")
79-
.build()
80-
}
75+
fun v1Api(): GroupedOpenApi = GroupedOpenApi.builder()
76+
.group("v1")
77+
.pathsToMatch("/v1/**")
78+
.build()
8179
}

src/main/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/common/config/UserEnhancedOAuth2ClientCredentialGrantRequestConverter.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import org.springframework.util.MultiValueMap
88
import java.util.Objects
99

1010
@Suppress("UNCHECKED_CAST")
11-
class UserEnhancedOAuth2ClientCredentialGrantRequestConverter :
12-
OAuth2ClientCredentialsGrantRequestEntityConverter() {
11+
class UserEnhancedOAuth2ClientCredentialGrantRequestConverter : OAuth2ClientCredentialsGrantRequestEntityConverter() {
1312

1413
fun enhanceWithUsername(
1514
grantRequest: OAuth2ClientCredentialsGrantRequest?,

src/main/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/common/config/WebClientConfiguration.kt

+9-13
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,23 @@ class WebClientConfiguration(
3636
@Value("\${prison-api.timeout:30s}") private val prisonApiTimeout: Duration,
3737
) {
3838
@Bean
39-
fun authHealthWebClient(builder: WebClient.Builder): WebClient =
40-
builder.healthWebClient(authBaseUri, authHealthTimeout)
39+
fun authHealthWebClient(builder: WebClient.Builder): WebClient = builder.healthWebClient(authBaseUri, authHealthTimeout)
4140

4241
@Bean
43-
fun prisonApiHealthWebClient(builder: WebClient.Builder): WebClient =
44-
builder.healthWebClient(prisonApiBaseUri, prisonApiHealthTimeout)
42+
fun prisonApiHealthWebClient(builder: WebClient.Builder): WebClient = builder.healthWebClient(prisonApiBaseUri, prisonApiHealthTimeout)
4543

4644
@Bean
4745
@RequestScope
4846
fun prisonApiWebClient(
4947
clientRegistrationRepository: ClientRegistrationRepository,
5048
builder: WebClient.Builder,
51-
): WebClient {
52-
return getOAuthWebClient(
53-
authorizedClientManagerUserEnhanced(clientRegistrationRepository),
54-
builder,
55-
prisonApiBaseUri,
56-
"hmpps-person-integration-api",
57-
prisonApiTimeout,
58-
)
59-
}
49+
): WebClient = getOAuthWebClient(
50+
authorizedClientManagerUserEnhanced(clientRegistrationRepository),
51+
builder,
52+
prisonApiBaseUri,
53+
"hmpps-person-integration-api",
54+
prisonApiTimeout,
55+
)
6056

6157
@Bean
6258
@DependsOn("prisonApiWebClient")

src/main/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/corepersonrecord/resource/CorePersonRecordV1Resource.kt

+1-3
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,7 @@ class CorePersonRecordV1Resource(
145145
fun putProfileImageByPrisonerNumber(
146146
@RequestParam(required = true) @Valid @ValidPrisonerNumber prisonerNumber: String,
147147
@RequestPart(name = "imageFile", required = true) profileImage: MultipartFile,
148-
): ResponseEntity<Void> {
149-
return noContent().build()
150-
}
148+
): ResponseEntity<Void> = noContent().build()
151149

152150
@GetMapping("reference-data/domain/{domain}/codes")
153151
@ResponseStatus(HttpStatus.OK)

src/main/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/personprotectercharacteristics/resource/PersonProtectedCharacteristicsV1Resource.kt

+6-8
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,12 @@ class PersonProtectedCharacteristicsV1Resource {
8484
fun putReligionByPrisonerNumber(
8585
@RequestParam(required = true) @Valid @ValidPrisonerNumber prisonerNumber: String,
8686
@RequestBody(required = true) @Valid religionV1RequestDto: ReligionV1RequestDto,
87-
): ResponseEntity<PersonReligionInformationV1ResponseDto> {
88-
return ok().body(
89-
PersonReligionInformationV1ResponseDto(
90-
currentReligion = ReligionDto(),
91-
religionHistory = emptySet(),
92-
),
93-
)
94-
}
87+
): ResponseEntity<PersonReligionInformationV1ResponseDto> = ok().body(
88+
PersonReligionInformationV1ResponseDto(
89+
currentReligion = ReligionDto(),
90+
religionHistory = emptySet(),
91+
),
92+
)
9593

9694
@GetMapping("reference-data/domain/{domain}/codes")
9795
@ResponseStatus(HttpStatus.OK)

src/test/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/integration/ResourceSecurityTest.kt

+6-7
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ class ResourceSecurityTest : IntegrationTestBase() {
5252
}
5353
}
5454

55-
private fun RequestMappingInfo.getMappings() =
56-
methodsCondition.methods
57-
.map { it.name }
58-
.ifEmpty { listOf("") } // if no methods defined then match all rather than none
59-
.flatMap { method ->
60-
pathPatternsCondition?.patternValues?.map { "$method $it" } ?: emptyList()
61-
}
55+
private fun RequestMappingInfo.getMappings() = methodsCondition.methods
56+
.map { it.name }
57+
.ifEmpty { listOf("") } // if no methods defined then match all rather than none
58+
.flatMap { method ->
59+
pathPatternsCondition?.patternValues?.map { "$method $it" } ?: emptyList()
60+
}

src/test/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/integration/wiremock/HmppsAuthMockServer.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import org.junit.jupiter.api.extension.ExtensionContext
1414
import java.time.LocalDateTime
1515
import java.time.ZoneOffset
1616

17-
class HmppsAuthApiExtension : BeforeAllCallback, AfterAllCallback, BeforeEachCallback {
17+
class HmppsAuthApiExtension :
18+
BeforeAllCallback,
19+
AfterAllCallback,
20+
BeforeEachCallback {
1821
companion object {
1922
@JvmField
2023
val hmppsAuth = HmppsAuthMockServer()

src/test/kotlin/uk/gov/justice/digital/hmpps/personintegrationapi/integration/wiremock/PrisonApiMockServer.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ class PrisonApiMockServer : WireMockServer(8082) {
110110
}
111111
}
112112

113-
class PrisonApiExtension : BeforeAllCallback, AfterAllCallback, BeforeEachCallback {
113+
class PrisonApiExtension :
114+
BeforeAllCallback,
115+
AfterAllCallback,
116+
BeforeEachCallback {
114117
companion object {
115118
@JvmField
116119
val prisonApi = PrisonApiMockServer()

0 commit comments

Comments
 (0)