diff --git a/README.md b/README.md index 95e2f89..c45923e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Gradle multi-module project for experiments with Java [![Java CI](https://github.com/mfvanek/java-experiments/actions/workflows/gradle.yml/badge.svg)](https://github.com/mfvanek/java-experiments/actions/workflows/gradle.yml) ## Modules -* [Spring Boot 2 app with custom BOM](spring-boot-2-app-example%2FREADME.md) +* [mongo-db-reactive-app-example](mongo-db-reactive-app-example) * [Spring Boot 3 app with PostgreSQL cluster](spring-boot-app-example%2FREADME.md) ## Useful Java links diff --git a/build.gradle.kts b/build.gradle.kts index 8beb30d..324ef80 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ description = "Experiments with Java" allprojects { group = "io.github.mfvanek" - version = "0.2.1" + version = "0.3.0" repositories { mavenLocal() @@ -48,7 +48,7 @@ tasks.named("dependencyUpdates").configure { tasks { wrapper { - gradleVersion = "8.13" + gradleVersion = "8.14.3" } jar { diff --git a/buildSrc/src/main/kotlin/java-experiments.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/java-experiments.java-conventions.gradle.kts index d98f94f..ab981d1 100644 --- a/buildSrc/src/main/kotlin/java-experiments.java-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/java-experiments.java-conventions.gradle.kts @@ -17,8 +17,8 @@ dependencies { testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") testRuntimeOnly("org.junit.platform:junit-platform-launcher") - errorprone("com.google.errorprone:error_prone_core:2.38.0") - errorprone("jp.skypencil.errorprone.slf4j:errorprone-slf4j:0.1.28") + errorprone("com.google.errorprone:error_prone_core:2.40.0") + errorprone("jp.skypencil.errorprone.slf4j:errorprone-slf4j:0.1.29") } java { @@ -28,7 +28,7 @@ java { } jacoco { - toolVersion = "0.8.12" + toolVersion = "0.8.13" } tasks { diff --git a/buildSrc/src/main/kotlin/java-experiments.pitest.gradle.kts b/buildSrc/src/main/kotlin/java-experiments.pitest.gradle.kts index 33af916..c700b68 100644 --- a/buildSrc/src/main/kotlin/java-experiments.pitest.gradle.kts +++ b/buildSrc/src/main/kotlin/java-experiments.pitest.gradle.kts @@ -11,8 +11,8 @@ dependencies { pitest { verbosity = "DEFAULT" - junit5PluginVersion = "1.2.2" - pitestVersion = "1.19.1" + junit5PluginVersion = "1.2.3" + pitestVersion = "1.20.0" threads = 4 outputFormats = setOf("XML", "HTML") timestampedReports = false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 14f9445..4f27ef9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -spring-boot-v3 = "3.5.0" +spring-boot-v3 = "3.5.3" [libraries] spring-boot-v3-dependencies = { group = "org.springframework.boot", name = "spring-boot-dependencies", version.ref = "spring-boot-v3" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 9bbc975..1b33c55 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37f853b..d4081da 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index faf9300..23d15a9 100755 --- a/gradlew +++ b/gradlew @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..db3a6ac 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/internal-bom/build.gradle.kts b/internal-bom/build.gradle.kts index 0cb525e..0e60691 100644 --- a/internal-bom/build.gradle.kts +++ b/internal-bom/build.gradle.kts @@ -10,16 +10,16 @@ javaPlatform { } dependencies { - api(platform("org.junit:junit-bom:5.13.3")) + api(platform("org.junit:junit-bom:5.13.4")) api(platform("org.testcontainers:testcontainers-bom:1.21.3")) - api(platform("io.github.mfvanek:pg-index-health-bom:0.15.0")) + api(platform("io.github.mfvanek:pg-index-health-bom:0.20.2")) api(platform("org.mockito:mockito-bom:5.18.0")) api(platform("org.assertj:assertj-bom:3.27.3")) constraints { api("com.google.code.findbugs:jsr305:3.0.2") api("org.postgresql:postgresql:42.7.7") - api("com.zaxxer:HikariCP:6.3.0") + api("com.zaxxer:HikariCP:6.3.1") api("ch.qos.logback:logback-classic:1.5.18") api("org.slf4j:slf4j-api:2.0.17") api("com.h2database:h2:2.3.232") diff --git a/internal-spring-boot-2-bom/build.gradle.kts b/internal-spring-boot-2-bom/build.gradle.kts deleted file mode 100644 index f62cae8..0000000 --- a/internal-spring-boot-2-bom/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -plugins { - id("java-platform") - id("java-experiments.bom-publish") -} - -description = "Spring Boot 2 cumulative BOM" - -javaPlatform { - allowDependencies() -} - -dependencies { - api(platform(project(":internal-bom"))) - api(platform("org.springdoc:springdoc-openapi:1.8.0")) - val spring2Version = "2.7.18" - api(platform("org.springframework.boot:spring-boot-dependencies:$spring2Version")) - api(platform("org.springframework:spring-framework-bom:5.3.37")) - api(platform("org.springframework.cloud:spring-cloud-dependencies:2021.0.9")) - api(platform("org.springframework.cloud:spring-cloud-sleuth-otel-dependencies:1.1.4")) - api(platform("org.springframework.security:spring-security-bom:5.8.12")) - - constraints { - api("org.springframework.boot:spring-boot-gradle-plugin:$spring2Version") - - api("ch.qos.logback:logback-classic") { - version { - strictly("1.2.13") - because("java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder") - } - } - api("org.slf4j:slf4j-api") { - version { - strictly("1.7.36") - because("SLF4J: No SLF4J providers were found.") - } - } - api("org.yaml:snakeyaml") { - version { - strictly("1.33") - because("org.yaml:snakeyaml:1.30 -> 2.0 (c)") - } - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index cb5826a..847d1ab 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,7 +6,5 @@ include("computer-science") include("spring-only-app-example") include("db-commons") include("internal-bom") -include("internal-spring-boot-2-bom") -include("spring-boot-2-app-example") include("internal-spring-boot-3-bom") include("mongo-db-reactive-app-example") diff --git a/spring-boot-2-app-example/README.md b/spring-boot-2-app-example/README.md deleted file mode 100644 index 95595b1..0000000 --- a/spring-boot-2-app-example/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Spring Boot 2 app with custom BOM - -## Explore dependencies - -```shell -cd ../ -./gradlew spring-boot-2-app-example:dependencies -``` - -```shell -cd ../ -./gradlew spring-boot-2-app-example:dependencyInsight --dependency org.yaml:snakeyaml -``` diff --git a/spring-boot-2-app-example/build.gradle.kts b/spring-boot-2-app-example/build.gradle.kts deleted file mode 100644 index 1df1ee8..0000000 --- a/spring-boot-2-app-example/build.gradle.kts +++ /dev/null @@ -1,37 +0,0 @@ -plugins { - id("java-experiments.java-conventions") - id("org.springframework.boot") version "2.7.18" - id("com.google.osdetector") version "1.7.3" -} - -description = "Spring Boot 2 application with Swagger" - -dependencies { - implementation(platform(project(":internal-spring-boot-2-bom"))) - - implementation("org.springframework.boot:spring-boot-starter-web") - implementation("org.springframework.boot:spring-boot-starter-actuator") - implementation("org.springframework.boot:spring-boot-starter-security") - implementation("org.springdoc:springdoc-openapi-ui") - implementation("org.springdoc:springdoc-openapi-security") - implementation("io.micrometer:micrometer-registry-prometheus") - - testImplementation("org.springframework.boot:spring-boot-starter-test") - testImplementation("org.springframework.boot:spring-boot-starter-webflux") - - // https://github.com/netty/netty/issues/11020 - if (osdetector.arch == "aarch_64") { - testImplementation("io.netty:netty-all") - } -} - -springBoot { - buildInfo() -} - -tasks.bootRun { - if (project.hasProperty("jvmArgs")) { - val jvmArgsFromCommandLine = project.properties["jvmArgs"].toString().split("\\s".toRegex()) - jvmArgs = jvmArgsFromCommandLine - } -} diff --git a/spring-boot-2-app-example/src/main/java/io/github/mfvanek/bom/example/BomExampleApplication.java b/spring-boot-2-app-example/src/main/java/io/github/mfvanek/bom/example/BomExampleApplication.java deleted file mode 100644 index f5eb953..0000000 --- a/spring-boot-2-app-example/src/main/java/io/github/mfvanek/bom/example/BomExampleApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.mfvanek.bom.example; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class BomExampleApplication { - - public static void main(String[] args) { - SpringApplication.run(BomExampleApplication.class, args); - } -} diff --git a/spring-boot-2-app-example/src/main/java/io/github/mfvanek/bom/example/controller/SimpleController.java b/spring-boot-2-app-example/src/main/java/io/github/mfvanek/bom/example/controller/SimpleController.java deleted file mode 100644 index e535694..0000000 --- a/spring-boot-2-app-example/src/main/java/io/github/mfvanek/bom/example/controller/SimpleController.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.mfvanek.bom.example.controller; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.time.LocalDateTime; - -@RestController -@RequestMapping("/v1/") -public class SimpleController { - - @GetMapping("/test") - public LocalDateTime test() { - return LocalDateTime.now(); - } -} diff --git a/spring-boot-2-app-example/src/main/resources/application.yml b/spring-boot-2-app-example/src/main/resources/application.yml deleted file mode 100644 index 949395d..0000000 --- a/spring-boot-2-app-example/src/main/resources/application.yml +++ /dev/null @@ -1,57 +0,0 @@ -spring: - main.banner-mode: off - application: - name: spring-boot-2-bom-example - -server: - port: 8080 - servlet: - context-path: /api - tomcat: - threads: - max: 10 - min-spare: 5 # actuator port uses the same configuration - shutdown: graceful - -management: - server: - port: 8090 - endpoints: - enabled-by-default: false - web: - exposure.include: health,info,prometheus,openapi,swaggerui - endpoint: - health: - enabled: true - probes.enabled: true - group: - readiness: - include: readinessState - additional-path: server:/readyz # In order to collect probes from application main port - info: - enabled: true - prometheus: - enabled: true - info: - env.enabled: true - health: - livenessstate: - enabled: true - readinessstate: - enabled: true - metrics: - distribution: - percentiles-histogram: - http.server.requests: true - minimum-expected-value: - http.server.requests: 10ms - maximum-expected-value: - http.server.requests: 10s - slo: - http.server.requests: 1s - export: - prometheus.enabled: true - -springdoc: - show-actuator: true - use-management-port: true diff --git a/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/ActuatorEndpointTest.java b/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/ActuatorEndpointTest.java deleted file mode 100644 index e3c34b8..0000000 --- a/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/ActuatorEndpointTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package io.github.mfvanek.bom.example; - -import io.github.mfvanek.bom.example.support.BaseTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.springframework.http.MediaType; -import org.springframework.test.web.reactive.server.WebTestClient; - -import javax.annotation.Nonnull; - -import static org.assertj.core.api.Assertions.assertThat; - -class ActuatorEndpointTest extends BaseTest { - - private WebTestClient actuatorClient; - - @BeforeEach - void setUp() { - this.actuatorClient = WebTestClient.bindToServer() - .baseUrl("http://localhost:" + actuatorPort + "/actuator/") - .defaultHeaders(super::setUpBasicAuth) - .build(); - } - - @Test - void actuatorShouldBeRunOnSeparatePort() { - assertThat(actuatorPort) - .isNotEqualTo(port); - } - - @ParameterizedTest - @CsvSource(value = { - "prometheus|jvm_threads_live_threads|text/plain", - "health|{\"status\":\"UP\",\"groups\":[\"liveness\",\"readiness\"]}|application/json", - "health/liveness|{\"status\":\"UP\"}|application/json", - "health/readiness|{\"status\":\"UP\"}|application/json", - "info|\"version\":|application/json"}, delimiter = '|') - void actuatorEndpointShouldReturnOk(@Nonnull final String endpointName, - @Nonnull final String expectedSubstring, - @Nonnull final String mediaType) { - final var result = actuatorClient.get() - .uri(uriBuilder -> uriBuilder - .path(endpointName) - .build()) - .accept(MediaType.valueOf(mediaType)) - .exchange() - .expectStatus().isOk() - .expectBody(String.class) - .returnResult() - .getResponseBody(); - assertThat(result) - .contains(expectedSubstring); - } - - @Test - void swaggerUiEndpointShouldReturnFound() { - final byte[] result = actuatorClient.get() - .uri(uriBuilder -> uriBuilder - .pathSegment("swagger-ui") - .build()) - .accept(MediaType.TEXT_HTML) - .exchange() - .expectStatus().isFound() - .expectHeader().location("/actuator/swagger-ui/index.html") - .expectBody() - .returnResult() - .getResponseBody(); - assertThat(result).isNull(); - } - - @Test - void readinessProbeShouldBeCollectedFromApplicationMainPort() { - final var result = webTestClient.get() - .uri(uriBuilder -> uriBuilder - .pathSegment("readyz") - .build()) - .accept(MediaType.APPLICATION_JSON) - .headers(super::setUpBasicAuth) - .exchange() - .expectStatus().isOk() - .expectBody(String.class) - .returnResult() - .getResponseBody(); - assertThat(result) - .isEqualTo("{\"status\":\"UP\"}"); - - final String metricsResult = actuatorClient.get() - .uri(uriBuilder -> uriBuilder - .path("prometheus") - .build()) - .accept(MediaType.valueOf("text/plain")) - .exchange() - .expectStatus().isOk() - .expectBody(String.class) - .returnResult() - .getResponseBody(); - assertThat(metricsResult) - .contains("http_server_requests_seconds_bucket"); - } -} diff --git a/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/BomExampleApplicationTest.java b/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/BomExampleApplicationTest.java deleted file mode 100644 index a59e082..0000000 --- a/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/BomExampleApplicationTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.mfvanek.bom.example; - -import io.github.mfvanek.bom.example.support.BaseTest; -import org.junit.jupiter.api.Test; - -class BomExampleApplicationTest extends BaseTest { - - @Test - void contextLoads() { - // no action - } -} diff --git a/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/support/BaseTest.java b/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/support/BaseTest.java deleted file mode 100644 index 32be386..0000000 --- a/spring-boot-2-app-example/src/test/java/io/github/mfvanek/bom/example/support/BaseTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.mfvanek.bom.example.support; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalManagementPort; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.web.reactive.server.WebTestClient; - -import javax.annotation.Nonnull; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles("test") -public abstract class BaseTest { - - @LocalServerPort - protected int port; - - @LocalManagementPort - protected int actuatorPort; - - @Autowired - protected WebTestClient webTestClient; - - @Autowired - private SecurityProperties securityProperties; - - protected final void setUpBasicAuth(@Nonnull final HttpHeaders httpHeaders) { - httpHeaders.setBasicAuth(securityProperties.getUser().getName(), securityProperties.getUser().getPassword()); - } -} diff --git a/spring-only-app-example/build.gradle.kts b/spring-only-app-example/build.gradle.kts index 167d16d..f1897ae 100644 --- a/spring-only-app-example/build.gradle.kts +++ b/spring-only-app-example/build.gradle.kts @@ -6,7 +6,7 @@ description = "Spring only application with embedded database" dependencies { implementation(platform(project(":internal-bom"))) - implementation(platform("org.springframework:spring-framework-bom:6.2.7")) + implementation(platform("org.springframework:spring-framework-bom:6.2.9")) implementation("org.springframework:spring-context") implementation("org.springframework:spring-jdbc")