diff --git a/boot-mongodb-elasticsearch/README.md b/boot-mongodb-elasticsearch/README.md index fd6ce68a4..3e39226e1 100644 --- a/boot-mongodb-elasticsearch/README.md +++ b/boot-mongodb-elasticsearch/README.md @@ -158,8 +158,8 @@ docker compose -f docker/docker-compose.yml up -d ## Configuration Properties Key application properties: ```properties -spring.data.mongodb.database=mongoes -spring.data.mongodb.uri=mongodb://localhost:27017/mongoes?replicaSet=rs0 +spring.mongodb.database=mongoes +spring.mongodb.uri=mongodb://localhost:27017/mongoes?replicaSet=rs0&readPreference=primary&directConnection=true spring.elasticsearch.uris=localhost:9200 spring.elasticsearch.socket-timeout=10s ``` diff --git a/boot-mongodb-elasticsearch/pom.xml b/boot-mongodb-elasticsearch/pom.xml index 546c8c544..929c70e7f 100644 --- a/boot-mongodb-elasticsearch/pom.xml +++ b/boot-mongodb-elasticsearch/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 4.0.0-M1 + 4.0.0 com.example.mongoes @@ -48,7 +48,7 @@ org.springframework.boot - spring-boot-starter-aop + spring-boot-starter-aspectj org.springframework.boot @@ -89,7 +89,7 @@ org.springframework.boot - spring-boot-starter-test + spring-boot-starter-webflux-test test @@ -97,24 +97,19 @@ spring-boot-testcontainers test - - io.projectreactor - reactor-test - test - org.testcontainers - junit-jupiter + testcontainers-junit-jupiter test org.testcontainers - mongodb + testcontainers-mongodb test org.testcontainers - elasticsearch + testcontainers-elasticsearch test diff --git a/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/GlobalExceptionHandler.java b/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/GlobalExceptionHandler.java index c3dae559f..68380e7c9 100644 --- a/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/GlobalExceptionHandler.java +++ b/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/GlobalExceptionHandler.java @@ -3,40 +3,50 @@ import com.example.mongoes.web.exception.DuplicateRestaurantException; import com.example.mongoes.web.exception.RestaurantNotFoundException; import jakarta.validation.ConstraintViolationException; +import java.net.URI; import java.util.Comparator; import java.util.List; import java.util.Objects; -import org.springframework.http.HttpStatusCode; +import org.jspecify.annotations.NonNull; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.support.WebExchangeBindException; +import org.springframework.web.server.MissingRequestValueException; import reactor.core.publisher.Mono; @RestControllerAdvice +@Order(Ordered.HIGHEST_PRECEDENCE) public class GlobalExceptionHandler { @ExceptionHandler(DuplicateRestaurantException.class) - public Mono handleDuplicateRestaurantException(DuplicateRestaurantException ex) { + public Mono<@NonNull ProblemDetail> handleDuplicateRestaurantException( + DuplicateRestaurantException ex) { ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(ex.getHttpStatus(), ex.getMessage()); + problemDetail.setType(URI.create("https://api.mongoes.com/errors/duplicate-restaurant")); return Mono.just(problemDetail); } @ExceptionHandler(RestaurantNotFoundException.class) - Mono handleRestaurantNotFoundException(RestaurantNotFoundException ex) { + Mono<@NonNull ProblemDetail> handleRestaurantNotFoundException(RestaurantNotFoundException ex) { ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(ex.getHttpStatus(), ex.getMessage()); + problemDetail.setType(URI.create("https://api.mongoes.com/errors/restaurant-not-found")); return Mono.just(problemDetail); } @ExceptionHandler(WebExchangeBindException.class) - Mono handleValidationErrors(WebExchangeBindException ex) { + Mono<@NonNull ProblemDetail> handleValidationErrors(WebExchangeBindException ex) { ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail( - HttpStatusCode.valueOf(400), "Request failed validation checks."); - problemDetail.setTitle("Constraint Violation"); + HttpStatus.BAD_REQUEST, "Invalid request content."); + problemDetail.setTitle("Bad Request"); + problemDetail.setType(URI.create("https://api.mongoes.com/errors/validation-error")); List validationErrorsList = ex.getAllErrors().stream() .map( @@ -56,11 +66,12 @@ Mono handleValidationErrors(WebExchangeBindException ex) { } @ExceptionHandler(ConstraintViolationException.class) - Mono handleConstraintViolation(ConstraintViolationException ex) { + Mono<@NonNull ProblemDetail> handleConstraintViolation(ConstraintViolationException ex) { ProblemDetail problemDetail = - ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(400), "Validation failed"); + ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "Validation failed"); problemDetail.setTitle("Constraint Violation"); + problemDetail.setType(URI.create("https://api.mongoes.com/errors/validation-error")); List validationErrorsList = ex.getConstraintViolations().stream() .map( @@ -76,5 +87,13 @@ Mono handleConstraintViolation(ConstraintViolationException ex) { return Mono.just(problemDetail); } + @ExceptionHandler(MissingRequestValueException.class) + Mono<@NonNull ProblemDetail> handleException(MissingRequestValueException ex) { + ProblemDetail problemDetail = + ProblemDetail.forStatusAndDetail(ex.getStatusCode(), ex.getBody().getDetail()); + problemDetail.setType(URI.create("https://api.mongoes.com/errors/validation-error")); + return Mono.just(problemDetail); + } + record ApiValidationError(String object, String field, Object rejectedValue, String message) {} } diff --git a/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/WebFluxConfig.java b/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/WebFluxConfig.java index d57785cf1..ef0986567 100644 --- a/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/WebFluxConfig.java +++ b/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/config/WebFluxConfig.java @@ -1,8 +1,9 @@ package com.example.mongoes.config; +import org.jspecify.annotations.NonNull; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.geo.GeoModule; +import org.springframework.data.geo.GeoJacksonModule; import org.springframework.web.reactive.config.CorsRegistry; import org.springframework.web.reactive.config.WebFluxConfigurer; @@ -16,16 +17,16 @@ public WebFluxConfig(ApplicationProperties properties) { } @Override - public void addCorsMappings(CorsRegistry registry) { + public void addCorsMappings(@NonNull CorsRegistry registry) { registry.addMapping(properties.getCors().getPathPattern()) - .allowedMethods(properties.getCors().getAllowedMethods()) - .allowedHeaders(properties.getCors().getAllowedHeaders()) - .allowedOriginPatterns(properties.getCors().getAllowedOriginPatterns()) + .allowedMethods(properties.getCors().getAllowedMethods().split(",")) + .allowedHeaders(properties.getCors().getAllowedHeaders().split(",")) + .allowedOriginPatterns(properties.getCors().getAllowedOriginPatterns().split(",")) .allowCredentials(properties.getCors().isAllowCredentials()); } @Bean - GeoModule jacksonGeoModule() { - return new GeoModule(); + GeoJacksonModule geoJacksonModule() { + return new GeoJacksonModule(); } } diff --git a/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/document/Grades.java b/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/document/Grades.java index 283c5c3e3..5633022cc 100644 --- a/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/document/Grades.java +++ b/boot-mongodb-elasticsearch/src/main/java/com/example/mongoes/document/Grades.java @@ -1,11 +1,11 @@ package com.example.mongoes.document; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import java.time.LocalDateTime; import java.util.StringJoiner; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; +import tools.jackson.databind.annotation.JsonDeserialize; +import tools.jackson.databind.ext.javatime.deser.LocalDateTimeDeserializer; public class Grades { private String grade; diff --git a/boot-mongodb-elasticsearch/src/main/resources/application-cluster.properties b/boot-mongodb-elasticsearch/src/main/resources/application-cluster.properties index 6d6d3e52b..3d257a9c9 100644 --- a/boot-mongodb-elasticsearch/src/main/resources/application-cluster.properties +++ b/boot-mongodb-elasticsearch/src/main/resources/application-cluster.properties @@ -1,2 +1,2 @@ #clusterURL -spring.data.mongodb.uri=mongodb://localhost:27017,localhost:27018,localhost:27019/mongoes?replicaSet=myReplicaSet +spring.mongodb.uri=mongodb://localhost:27017,localhost:27018,localhost:27019/mongoes?replicaSet=myReplicaSet diff --git a/boot-mongodb-elasticsearch/src/main/resources/application.properties b/boot-mongodb-elasticsearch/src/main/resources/application.properties index a3b6d9d92..8d1566e61 100644 --- a/boot-mongodb-elasticsearch/src/main/resources/application.properties +++ b/boot-mongodb-elasticsearch/src/main/resources/application.properties @@ -23,8 +23,8 @@ spring.jackson.serialization.fail-on-empty-beans=false #spring.data.mongodb.authentication-database=admin #spring.data.mongodb.username=admin #spring.data.mongodb.password=passcode -spring.data.mongodb.database=mongoes -spring.data.mongodb.uri=mongodb://localhost:27017/mongoes?replicaSet=rs0&readPreference=primary&directConnection=true +spring.mongodb.database=mongoes +spring.mongodb.uri=mongodb://localhost:27017/mongoes?replicaSet=rs0&readPreference=primary&directConnection=true spring.elasticsearch.uris=localhost:9200 spring.elasticsearch.socket-timeout=10s diff --git a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/AbstractIntegrationTest.java b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/AbstractIntegrationTest.java index 2d01ce46a..3c83bdb71 100644 --- a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/AbstractIntegrationTest.java +++ b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/AbstractIntegrationTest.java @@ -5,8 +5,8 @@ import com.example.mongoes.repository.elasticsearch.RestaurantESRepository; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.reactive.server.WebTestClient; diff --git a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/ContainersConfig.java b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/ContainersConfig.java index 9e4ed6314..fd49380d8 100644 --- a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/ContainersConfig.java +++ b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/common/ContainersConfig.java @@ -5,8 +5,8 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.mongodb.MongoDBContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) diff --git a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/model/request/RestaurantRequestTest.java b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/model/request/RestaurantRequestTest.java index 7900121d7..99beed82d 100644 --- a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/model/request/RestaurantRequestTest.java +++ b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/model/request/RestaurantRequestTest.java @@ -13,10 +13,10 @@ import org.springframework.boot.test.json.JsonContent; import org.springframework.context.annotation.Import; import org.springframework.data.geo.Point; -import org.springframework.data.web.config.SpringDataJacksonConfiguration; +import org.springframework.data.web.config.SpringDataJackson3Configuration; @JsonTest -@Import(SpringDataJacksonConfiguration.class) +@Import(SpringDataJackson3Configuration.class) class RestaurantRequestTest { @Autowired private JacksonTester jacksonTester; diff --git a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerIntTest.java b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerIntTest.java index bd96d32d1..8f19cecbc 100644 --- a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerIntTest.java +++ b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerIntTest.java @@ -72,7 +72,7 @@ void createRestaurant_WithDuplicateName_ShouldReturnConflict() { .json( """ { - "type":"about:blank", + "type":"https://api.mongoes.com/errors/duplicate-restaurant", "title":"Conflict", "status":409, "detail":"Restaurant with name 'Restaurant2' already exists", @@ -243,7 +243,7 @@ void findRestaurantById_WithNonExistentId_ShouldReturnNotFound() { .json( """ { - "type":"about:blank", + "type":"https://api.mongoes.com/errors/restaurant-not-found", "title":"Not Found", "status":404, "detail":"Restaurant not found with id: 999999", @@ -265,7 +265,7 @@ void findRestaurantByName_WithNonExistentName_ShouldReturnNotFound() { .json( """ { - "type":"about:blank", + "type":"https://api.mongoes.com/errors/restaurant-not-found", "title":"Not Found", "status":404, "detail":"Restaurant not found with name: Non Existent Restaurant", diff --git a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerTest.java b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerTest.java index 86a7d1b8b..f8697a8b0 100644 --- a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerTest.java +++ b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/RestaurantControllerTest.java @@ -18,7 +18,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.boot.webflux.test.autoconfigure.WebFluxTest; import org.springframework.data.geo.Point; import org.springframework.http.MediaType; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -79,7 +79,7 @@ void findAllRestaurants_WithInvalidLimit_ShouldReturnBadRequest() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Constraint Violation", "status": 400, "detail": "Validation failed", @@ -114,7 +114,7 @@ void whenRestaurantRequestWithNullName_thenBadRequest() { .expectBody() .json( """ - {"type":"about:blank","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant"} + {"type":"https://api.mongoes.com/errors/validation-error","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant"} """); } @@ -136,7 +136,7 @@ void whenRestaurantRequestWithEmptyBorough_thenBadRequest() { .expectBody() .json( """ - {"type":"about:blank","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant"} + {"type":"https://api.mongoes.com/errors/validation-error","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant"} """); } @@ -180,7 +180,7 @@ void whenInvalidGrade_willReturns400() { .expectBody() .json( """ - {"type":"about:blank","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant/1/grade"} + {"type":"https://api.mongoes.com/errors/validation-error","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant/1/grade"} """); } @@ -204,7 +204,7 @@ void whenNegativeScore_willReturns400() { .expectBody() .json( """ - {"type":"about:blank","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant/1/grade"} + {"type":"https://api.mongoes.com/errors/validation-error","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant/1/grade"} """); } @@ -281,7 +281,7 @@ void findRestaurantByName_WithTooLongName_ShouldReturnBadRequest() { .expectBody() .json( """ - {"type":"about:blank","title":"Constraint Violation","status":400,"detail":"Validation failed","instance":"/api/restaurant/name/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","violations":[{"object":"RestaurantController","field":"findRestaurantByName.restaurantName","rejectedValue":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","message":"size must be between 0 and 255"}]} + {"type":"https://api.mongoes.com/errors/validation-error","title":"Constraint Violation","status":400,"detail":"Validation failed","instance":"/api/restaurant/name/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","violations":[{"object":"RestaurantController","field":"findRestaurantByName.restaurantName","rejectedValue":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","message":"size must be between 0 and 255"}]} """); } @@ -316,7 +316,7 @@ void findRestaurantByName_WithInvalidCharacters_ShouldReturnBadRequest( .isBadRequest() .expectBody() .jsonPath("$.type") - .isEqualTo("about:blank") + .isEqualTo("https://api.mongoes.com/errors/validation-error") .jsonPath("$.title") .isEqualTo("Constraint Violation") .jsonPath("$.status") @@ -451,7 +451,7 @@ void createRestaurant_WithInvalidRequest_ShouldReturnBadRequest() { .expectBody() .json( """ - {"type":"about:blank","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant"} + {"type":"https://api.mongoes.com/errors/validation-error","title":"Bad Request","status":400,"detail":"Invalid request content.","instance":"/api/restaurant"} """); } @@ -493,7 +493,7 @@ void updateGradesOfRestaurant_WithInvalidRequest_ShouldReturnBadRequest() { .expectBody() .json( """ - {"type":"about:blank","title":"Constraint Violation","status":400,"detail":"Validation failed","instance":"/api/restaurant/1/grades","violations":[{"object":"RestaurantController","field":"updateGradesOfRestaurant.grades[0].date","rejectedValue":null,"message":"Date cannot be null"},{"object":"RestaurantController","field":"updateGradesOfRestaurant.grades[0].grade","rejectedValue":null,"message":"Grade cannot be blank"},{"object":"RestaurantController","field":"updateGradesOfRestaurant.grades[0].score","rejectedValue":null,"message":"Score cannot be null"}]} + {"type":"https://api.mongoes.com/errors/validation-error","title":"Constraint Violation","status":400,"detail":"Validation failed","instance":"/api/restaurant/1/grades","violations":[{"object":"RestaurantController","field":"updateGradesOfRestaurant.grades[0].date","rejectedValue":null,"message":"Date cannot be null"},{"object":"RestaurantController","field":"updateGradesOfRestaurant.grades[0].grade","rejectedValue":null,"message":"Grade cannot be blank"},{"object":"RestaurantController","field":"updateGradesOfRestaurant.grades[0].score","rejectedValue":null,"message":"Score cannot be null"}]} """); } diff --git a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/SearchControllerTest.java b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/SearchControllerTest.java index a67c892ac..386107a43 100644 --- a/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/SearchControllerTest.java +++ b/boot-mongodb-elasticsearch/src/test/java/com/example/mongoes/web/controller/SearchControllerTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.boot.webflux.test.autoconfigure.WebFluxTest; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.reactive.server.WebTestClient; import reactor.core.publisher.Flux; @@ -310,7 +310,7 @@ class CoordinateValidationTests { private static final String MISSING_PARAMETER_ERROR_JSON = """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Bad Request", "status": 400, "detail": "Required query parameter '%s' is not present.", @@ -348,7 +348,7 @@ void whenCoordinatesOutOfRange_thenReturns400( .isBadRequest() .expectBody() .jsonPath("$.type") - .isEqualTo("about:blank") + .isEqualTo("https://api.mongoes.com/errors/validation-error") .jsonPath("$.title") .isEqualTo("Constraint Violation") .jsonPath("$.status") @@ -432,7 +432,7 @@ void whenDistanceMissing_thenReturns400() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Bad Request", "status": 400, "detail": "Required query parameter 'distance' is not present.", @@ -462,7 +462,7 @@ void whenDistanceNegative_thenReturns400() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Constraint Violation", "status": 400, "detail": "Validation failed", @@ -709,7 +709,7 @@ void searchRestaurantIdRange_WithNullLowerLimit_ShouldReturnBadRequest() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Bad Request", "status": 400, "detail": "Required query parameter 'lowerLimit' is not present.", @@ -735,7 +735,7 @@ void searchRestaurantIdRange_WithNullUpperLimit_ShouldReturnBadRequest() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Bad Request", "status": 400, "detail": "Required query parameter 'upperLimit' is not present.", @@ -762,7 +762,7 @@ void searchRestaurantIdRange_WithZeroLowerLimit_ShouldReturnBadRequest() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Constraint Violation", "status": 400, "detail": "Validation failed", @@ -797,7 +797,7 @@ void searchRestaurantIdRange_WithZeroUpperLimit_ShouldReturnBadRequest() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Constraint Violation", "status": 400, "detail": "Validation failed", @@ -832,7 +832,7 @@ void searchRestaurantIdRange_WithNegativeLowerLimit_ShouldReturnBadRequest() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Constraint Violation", "status": 400, "detail": "Validation failed", @@ -867,7 +867,7 @@ void searchRestaurantIdRange_WithNegativeUpperLimit_ShouldReturnBadRequest() { .json( """ { - "type": "about:blank", + "type": "https://api.mongoes.com/errors/validation-error", "title": "Constraint Violation", "status": 400, "detail": "Validation failed", diff --git a/scheduler/boot-scheduler-quartz/pom.xml b/scheduler/boot-scheduler-quartz/pom.xml index b6233e075..2e07dc570 100644 --- a/scheduler/boot-scheduler-quartz/pom.xml +++ b/scheduler/boot-scheduler-quartz/pom.xml @@ -111,6 +111,11 @@ org.springframework.boot spring-boot-starter-webmvc-test test + + + org.springframework.boot + spring-boot-starter-actuator-test + test org.springframework.boot diff --git a/scheduler/boot-scheduler-quartz/src/main/java/com/scheduler/quartz/config/WebMvcConfig.java b/scheduler/boot-scheduler-quartz/src/main/java/com/scheduler/quartz/config/WebMvcConfig.java index c115f3dc1..036f17fd1 100644 --- a/scheduler/boot-scheduler-quartz/src/main/java/com/scheduler/quartz/config/WebMvcConfig.java +++ b/scheduler/boot-scheduler-quartz/src/main/java/com/scheduler/quartz/config/WebMvcConfig.java @@ -1,7 +1,7 @@ package com.scheduler.quartz.config; +import org.jspecify.annotations.NonNull; import org.springframework.context.annotation.Configuration; -import org.springframework.lang.NonNull; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;