diff --git a/build.gradle b/build.gradle index 7e8f3a094..2183a985a 100644 --- a/build.gradle +++ b/build.gradle @@ -203,8 +203,9 @@ configure(subprojects.findAll { !javaPlatformModules.contains(it.name) }) { configuration.resolutionStrategy.activateDependencyLocking() } - sourceCompatibility = JavaVersion.VERSION_17 - + java { + sourceCompatibility = JavaVersion.VERSION_17 + } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } diff --git a/sda-commons-app-example/openapi.yaml b/sda-commons-app-example/openapi.yaml index e7628923b..5846ec0fc 100644 --- a/sda-commons-app-example/openapi.yaml +++ b/sda-commons-app-example/openapi.yaml @@ -14,13 +14,13 @@ paths: content: '*/*': schema: - $ref: '#/components/schemas/Cars' + $ref: "#/components/schemas/Cars" "404": description: Resource not found content: '*/*': schema: - $ref: '#/components/schemas/ApiError' + $ref: "#/components/schemas/ApiError" /trees: get: tags: @@ -32,13 +32,13 @@ paths: content: '*/*': schema: - $ref: '#/components/schemas/Trees' + $ref: "#/components/schemas/Trees" "404": description: Resource not found content: '*/*': schema: - $ref: '#/components/schemas/ApiError' + $ref: "#/components/schemas/ApiError" components: schemas: ApiError: @@ -51,7 +51,7 @@ components: the request body or query params. example: [] items: - $ref: '#/components/schemas/ApiInvalidParam' + $ref: "#/components/schemas/ApiInvalidParam" title: type: string description: The human readable description of the error. @@ -92,7 +92,7 @@ components: type: array description: The cars items: - $ref: '#/components/schemas/Car' + $ref: "#/components/schemas/Car" description: A list of cars Tree: type: object @@ -108,5 +108,5 @@ components: type: array description: The trees items: - $ref: '#/components/schemas/Tree' + $ref: "#/components/schemas/Tree" description: A list of trees diff --git a/sda-commons-app-example/src/test/java/org/sdase/commons/spring/boot/web/app/example/OpenApiGeneratorTest.java b/sda-commons-app-example/src/test/java/org/sdase/commons/spring/boot/web/app/example/OpenApiGeneratorTest.java index f89153b26..2fb297b23 100644 --- a/sda-commons-app-example/src/test/java/org/sdase/commons/spring/boot/web/app/example/OpenApiGeneratorTest.java +++ b/sda-commons-app-example/src/test/java/org/sdase/commons/spring/boot/web/app/example/OpenApiGeneratorTest.java @@ -89,7 +89,7 @@ void shouldSortResponsesByCode() throws JsonProcessingException { .asInstanceOf(InstanceOfAssertFactories.MAP) .extracting(Map::keySet) .extracting(ArrayList::new) - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .containsExactly("200", "404"); } diff --git a/sda-commons-dependencies/build.gradle b/sda-commons-dependencies/build.gradle index 45559a7f6..414da9ad9 100644 --- a/sda-commons-dependencies/build.gradle +++ b/sda-commons-dependencies/build.gradle @@ -10,7 +10,7 @@ ext { awaitalityVersion = '4.2.0' bouncycastleVersion = '1.78.1' logbackContribVersion = '0.1.5' - springBootVersion = '3.3.0' + springBootVersion = '3.3.1' springCloudVersion = '2023.0.2' scalaVersion = '2.13.14' swaggerCoreVersion = '2.2.22' @@ -21,10 +21,6 @@ dependencies { api enforcedPlatform("org.springframework.boot:spring-boot-dependencies:${springBootVersion}") api enforcedPlatform("org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}") - // Mitigate CVE-2024-22262 - // TODO: Remove once spring-boot updates their dependencies - api enforcedPlatform("org.springframework:spring-framework-bom:6.1.10") - // asyncapi generation api enforcedPlatform("com.github.victools:jsonschema-generator-bom:${victoolsVersion}") @@ -53,6 +49,9 @@ dependencies { api "ch.qos.logback.contrib:logback-json-classic:${logbackContribVersion}" api "ch.qos.logback.contrib:logback-jackson:${logbackContribVersion}" api 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.5.0' + api "io.opentelemetry:opentelemetry-api-incubator:1.38.0-alpha", { + because "conflict within transitive dependencies of Spring Boot Dependencies" + } // should align with transitive dependency of org.springdoc:springdoc-openapi-webmvc-core: api "io.swagger.core.v3:swagger-core-jakarta:${swaggerCoreVersion}" diff --git a/sda-commons-starter-web/src/main/java/org/sdase/commons/spring/boot/web/auth/SdaSecurityConfiguration.java b/sda-commons-starter-web/src/main/java/org/sdase/commons/spring/boot/web/auth/SdaSecurityConfiguration.java index d5f59a544..185966190 100644 --- a/sda-commons-starter-web/src/main/java/org/sdase/commons/spring/boot/web/auth/SdaSecurityConfiguration.java +++ b/sda-commons-starter-web/src/main/java/org/sdase/commons/spring/boot/web/auth/SdaSecurityConfiguration.java @@ -105,7 +105,7 @@ private AuthenticationManagerResolver createAuthenticationMa LOG.warn("No trusted issuers configured, anonymous requests allowed."); return onlyAnonymousAuthenticationManagerResolver(); } else { - return new JwtIssuerAuthenticationManagerResolver(trustedIssuers); + return JwtIssuerAuthenticationManagerResolver.fromTrustedIssuers(trustedIssuers); } } diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/async/ContextCopyTaskDecoratorTest.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/async/ContextCopyTaskDecoratorTest.java index 9c418731c..9fae76c64 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/async/ContextCopyTaskDecoratorTest.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/async/ContextCopyTaskDecoratorTest.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.assertj.core.api.InstanceOfAssertFactories; @@ -27,7 +28,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; @@ -78,8 +78,9 @@ void shouldRunInNewThreadAndKeepMDC() throws Exception { var actual = callAsyncAndVerify(asyncProcessor::process); - assertThat(actual.get("mdcCopyOfContextMap")).isInstanceOf(Map.class); - assertThat((Map) actual.get("mdcCopyOfContextMap")) + assertThat(actual.get("mdcCopyOfContextMap")) + .isInstanceOf(Map.class) + .asInstanceOf(InstanceOfAssertFactories.MAP) .containsEntry("test-key", "test-value"); } @@ -118,7 +119,7 @@ public Future> process() { Map mdcCopyOfContextMap = MDC.getCopyOfContextMap() == null ? Map.of() : MDC.getCopyOfContextMap(); try { - return new AsyncResult<>( + return CompletableFuture.completedFuture( Map.of( "thread-id", threadId, @@ -129,7 +130,7 @@ public Future> process() { "mdcCopyOfContextMap", mdcCopyOfContextMap)); } catch (IllegalStateException ignored) { - return new AsyncResult<>( + return CompletableFuture.completedFuture( Map.of("thread-id", threadId, "metadata-context", metadataContext)); } } diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/FeignClientIT.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/FeignClientIT.java index 398a654fb..56d7960f5 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/FeignClientIT.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/FeignClientIT.java @@ -14,6 +14,7 @@ import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.common.Json; import java.util.Map; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.sdase.commons.spring.boot.web.client.test.ClientTestApp; @@ -132,7 +133,11 @@ void shouldCallAsyncWithAuthentication() { boolean sorted = false; try { - assertThat(actual).asList().hasSize(100).extracting("time").isSorted(); + assertThat(actual) + .asInstanceOf(InstanceOfAssertFactories.LIST) + .hasSize(100) + .extracting("time") + .isSorted(); sorted = true; } catch (AssertionError ignored) { // ignore diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/test/AsyncClientAdapter.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/test/AsyncClientAdapter.java index 33449eb70..6236abcc9 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/test/AsyncClientAdapter.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/client/test/AsyncClientAdapter.java @@ -12,7 +12,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import java.util.concurrent.CompletableFuture; import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Component; @Component @@ -43,6 +42,6 @@ CompletableFuture getSomethingAsync() { var time = System.nanoTime(); var timeAsJsonNode = objectMapper.convertValue(time, JsonNode.class); jsonNodes.set("time", timeAsJsonNode); - return new AsyncResult<>(objectMapper.convertValue(jsonNodes, Object.class)).completable(); + return CompletableFuture.completedFuture(objectMapper.convertValue(jsonNodes, Object.class)); } } diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/logging/JsonLoggingTest.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/logging/JsonLoggingTest.java index 1b4fc2964..ec72bb12d 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/logging/JsonLoggingTest.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/logging/JsonLoggingTest.java @@ -14,6 +14,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junitpioneer.jupiter.ClearSystemProperty; @@ -39,7 +40,7 @@ void shouldLogRegular(CapturedOutput output) { assertThat(output).asString().contains("Started JsonLoggingTest.LoggingTestApp"); assertThat(nonTestLogLines(output)) .as("Log contains no JSON:\n{}", output.toString()) - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .noneMatch(l -> l.toString().startsWith("{")); } @@ -54,7 +55,7 @@ void shouldLogJson(CapturedOutput output) throws JsonProcessingException { } assertThat(onlyConfigurableLogLines(nonTestLogLines(output))) .as("Log contains JSON:\n{}", output.toString()) - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .isNotEmpty() .allMatch(l -> l.toString().startsWith("{")); } @@ -77,7 +78,7 @@ void shouldLogJsonUsingDifferentTimeStampFormat(CapturedOutput output) } assertThat(onlyConfigurableLogLines(nonTestLogLines(output))) .as("Log contains JSON:\n{}", output.toString()) - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .isNotEmpty() .allMatch(l -> l.toString().startsWith("{")); } diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/monitoring/HealthCheckOpaDisabledIT.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/monitoring/HealthCheckOpaDisabledIT.java index e9f974e97..6e2565804 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/monitoring/HealthCheckOpaDisabledIT.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/monitoring/HealthCheckOpaDisabledIT.java @@ -65,7 +65,7 @@ void shouldReturnOpaHealthNotFoundForOpaDisabled() { .thenReturn(getAllowedResponse()); var responseEntity = getHealthCheck(); assertThat(responseEntity.getStatusCode().is4xxClientError()).isTrue(); - assertThat(responseEntity.getStatusCodeValue()).isEqualTo(404); + assertThat(responseEntity.getStatusCode().value()).isEqualTo(404); } private OpaResponse getAllowedResponse() { diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/headers/AbstractSecurityHeadersTest.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/headers/AbstractSecurityHeadersTest.java index 942ac658e..e01eb3df9 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/headers/AbstractSecurityHeadersTest.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/headers/AbstractSecurityHeadersTest.java @@ -14,7 +14,6 @@ import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; @@ -154,7 +153,7 @@ void verifyExistingDefaultHeaders() { "Vary", "Trace-Token"), predefinedSecurityHeaders().map(Arguments::get).map(it -> it[0])) - .collect(Collectors.toList())); + .toList()); } /** @@ -183,7 +182,7 @@ void verifyExistingDefaultHeadersInCaseOfError() { "Vary", "Trace-Token"), predefinedSecurityHeaders().map(Arguments::get).map(it -> it[0])) - .collect(Collectors.toList())); + .toList()); } @Test @@ -191,7 +190,7 @@ void verifyAllowedMethods() { List httpMethods = client.optionsForAllow(getServerBaseUrl() + "/api/resource").stream().toList(); assertThat(httpMethods) - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .containsExactlyInAnyOrder(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS); } diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/om/CustomObjectMapperAdviceTest.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/om/CustomObjectMapperAdviceTest.java index beeb3a645..316d5f889 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/om/CustomObjectMapperAdviceTest.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/om/CustomObjectMapperAdviceTest.java @@ -21,7 +21,7 @@ void shouldPreventStartupIfSdaObjectMapperIsNotConfigured() { assertThat(ContextUtils.createTestContext(NoSdaObjectMapperApp.class)) .hasFailed() .getFailure() - .getRootCause() + .rootCause() .isInstanceOf(InsecureConfigurationException.class) .hasMessage( "Missing sdaObjectMapperBuilder bean from org.sdase.commons.spring.boot.web.jackson. " diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/trace/SecureMethodsAdviceTest.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/trace/SecureMethodsAdviceTest.java index 5e678326d..ad74cf5fa 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/trace/SecureMethodsAdviceTest.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/security/validation/trace/SecureMethodsAdviceTest.java @@ -24,7 +24,7 @@ void shouldPreventStartupIfTracingIsEnabled() { Assertions.assertThat(ContextUtils.createTestContext(TraceAllowedApp.class)) .hasFailed() .getFailure() - .getRootCause() + .rootCause() .isInstanceOfSatisfying( InsecureConfigurationException.class, e -> assertThat(e.getMessage()).isEqualTo("The server accepts insecure methods.")); diff --git a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/tracing/TraceTokenClientInterceptorTest.java b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/tracing/TraceTokenClientInterceptorTest.java index 2154f3d08..61779130b 100644 --- a/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/tracing/TraceTokenClientInterceptorTest.java +++ b/sda-commons-starter-web/src/test/java/org/sdase/commons/spring/boot/web/tracing/TraceTokenClientInterceptorTest.java @@ -14,6 +14,7 @@ import java.util.HashSet; import java.util.List; import org.apache.commons.lang3.StringUtils; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -57,7 +58,7 @@ void shouldCreateNewTraceTokenIfNotInRequestContext() { assertThat(given.headers()) .containsKey("Trace-Token") .extracting("Trace-Token") - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .hasSize(1) .first() .asString() @@ -78,7 +79,7 @@ void shouldCreateNewTraceTokenIfExistingNotAsExpected() { assertThat(given.headers()) .containsKey("Trace-Token") .extracting("Trace-Token") - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .hasSize(1) .first() .asString() diff --git a/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthBuilderTest.java b/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthBuilderTest.java index b607d945e..893768c8d 100644 --- a/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthBuilderTest.java +++ b/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthBuilderTest.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -70,7 +71,7 @@ void shouldAddDateClaim() throws ParseException { Date testDate = new Date(); String token = authBuilder.addClaim("testKey", testDate).token(); JWT claim = decodeJwt(token); - assertThat(claim.getJWTClaimsSet().getDateClaim("testKey")).isEqualToIgnoringMillis(testDate); + assertThat(claim.getJWTClaimsSet().getDateClaim("testKey")).isCloseTo(testDate, 1_100); } @Test @@ -78,7 +79,7 @@ void shouldAddStringArrayClaim() throws ParseException { String token = authBuilder.addClaim("testKey", new String[] {"Hello", "World"}).token(); JWT claim = decodeJwt(token); assertThat(claim.getJWTClaimsSet().getClaim("testKey")) - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .containsExactly("Hello", "World"); } @@ -86,14 +87,18 @@ void shouldAddStringArrayClaim() throws ParseException { void shouldAddLongArrayClaim() throws ParseException { String token = authBuilder.addClaim("testKey", new Long[] {1L, 2L}).token(); JWT claim = decodeJwt(token); - assertThat(claim.getJWTClaimsSet().getClaim("testKey")).asList().containsExactly(1L, 2L); + assertThat(claim.getJWTClaimsSet().getClaim("testKey")) + .asInstanceOf(InstanceOfAssertFactories.LIST) + .containsExactly(1L, 2L); } @Test void shouldAddIntArrayClaim() throws ParseException { String token = authBuilder.addClaim("testKey", new Integer[] {1, 2}).token(); JWT claim = decodeJwt(token); - assertThat(claim.getJWTClaimsSet().getClaim("testKey")).asList().containsExactly(1L, 2L); + assertThat(claim.getJWTClaimsSet().getClaim("testKey")) + .asInstanceOf(InstanceOfAssertFactories.LIST) + .containsExactly(1L, 2L); } @Test @@ -117,9 +122,13 @@ void shouldAddAllSupportedTypesWithOneCall() throws ParseException { assertThat(jwt.getJWTClaimsSet().getDoubleClaim("d")).isEqualTo(3.141D); assertThat(jwt.getJWTClaimsSet().getBooleanClaim("b")).isTrue(); assertThat(jwt.getJWTClaimsSet().getStringListClaim("s[]")).containsExactly("Hello", "World"); - assertThat(jwt.getJWTClaimsSet().getClaim("i[]")).asList().containsExactly(1L, 2L); - assertThat(jwt.getJWTClaimsSet().getClaim("l[]")).asList().containsExactly(1L, 2L); - assertThat(jwt.getJWTClaimsSet().getDateClaim("date")).isEqualToIgnoringMillis(dateValue); + assertThat(jwt.getJWTClaimsSet().getClaim("i[]")) + .asInstanceOf(InstanceOfAssertFactories.LIST) + .containsExactly(1L, 2L); + assertThat(jwt.getJWTClaimsSet().getClaim("l[]")) + .asInstanceOf(InstanceOfAssertFactories.LIST) + .containsExactly(1L, 2L); + assertThat(jwt.getJWTClaimsSet().getDateClaim("date")).isCloseTo(dateValue, 1_100); } @Test diff --git a/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthMockTest.java b/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthMockTest.java index 0c1d46377..ffd1f2780 100644 --- a/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthMockTest.java +++ b/sda-commons-web-testing/src/test/java/org/sdase/commons/spring/boot/web/testing/auth/AuthMockTest.java @@ -12,6 +12,7 @@ import com.nimbusds.jwt.JWTParser; import java.text.ParseException; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -45,7 +46,7 @@ void shouldProvideKeys() throws ParseException { var keys = client.getForObject(baseUrl + "/issuer/keys", Object.class); assertThat(keys) .extracting("keys") - .asList() + .asInstanceOf(InstanceOfAssertFactories.LIST) .extracting("kty", "use", "kid") .containsExactly(tuple("RSA", "sig", kid)); }