Skip to content

Commit

Permalink
feat: upgrade to Spring Boot 3.2 and Java 21
Browse files Browse the repository at this point in the history
  • Loading branch information
gerritschlueter authored and gschlueter-jaconi committed Dec 12, 2023
1 parent 317d343 commit b2cb480
Show file tree
Hide file tree
Showing 18 changed files with 58 additions and 98 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/continuous.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
- name: Install Java
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'

- name: Validate Gradle wrapper
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Install Java
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'

- name: Validate Gradle wrapper
Expand Down
27 changes: 0 additions & 27 deletions Dockerfile

This file was deleted.

27 changes: 10 additions & 17 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
jacoco
`jvm-test-suite`
id("io.freefair.lombok") version "8.4"
id("org.springframework.boot") version "3.1.5"
id("org.springframework.boot") version "3.2.0"
id("io.spring.dependency-management") version "1.1.4"
id("org.graalvm.buildtools.native") version "0.9.28"
id("com.github.rising3.semver") version "0.8.2"
Expand All @@ -29,7 +29,7 @@ dependencies {
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
implementation("ch.qos.logback:logback-classic")

implementation(platform("org.springframework.cloud:spring-cloud-dependencies:2022.0.4"))
implementation(platform("org.springframework.cloud:spring-cloud-dependencies:2023.0.0"))

implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
Expand Down Expand Up @@ -63,7 +63,7 @@ dependencies {
}

java {
sourceCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
}

sonarqube {
Expand All @@ -74,7 +74,11 @@ sonarqube {
}
}

extra["testcontainersVersion"] = "1.18.2"
tasks.processTestAot {
enabled = false
}

extra["testcontainersVersion"] = "1.19.3"

// setup separate test suites for unit and integration tests
testing {
Expand Down Expand Up @@ -115,7 +119,7 @@ testing {
targets {
all {
testTask.configure {
mustRunAfter(tasks.named("dockerBuild"))
mustRunAfter(tasks.bootBuildImage)
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
testLogging.showStandardStreams = true
}
Expand All @@ -125,17 +129,6 @@ testing {
}
}

tasks.create<Exec>("dockerBuild") {
mustRunAfter(tasks.test)
executable("docker")
args(listOf("build", "-t", "${registry}/${project.name}:${project.version}", "-t", "${registry}/${project.name}:latest", "."))
}

tasks.create<Exec>("dockerBuildPush") {
executable("docker")
args(listOf("buildx", "build", "--platform", "linux/amd64,linux/arm64", "-t", "${registry}/${project.name}:${project.version}", "--push", "."))
}

tasks.withType<BootBuildImage> {
mustRunAfter(tasks.test)
imageName.value("${registry}/${project.name}:${project.version}")
Expand All @@ -157,7 +150,7 @@ tasks.withType<BootBuildImage> {

tasks.check {
dependsOn(tasks.test)
dependsOn(tasks.named("dockerBuild"))
dependsOn(tasks.bootBuildImage)
dependsOn(testing.suites.named("integrationTest"))
dependsOn(tasks.jacocoTestReport)
}
Expand Down
3 changes: 2 additions & 1 deletion compose/application.demo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ spring:
uri: https://httpbin.org
order: 2
predicates:
- Host={tenant}.localtest.me:8080
# Ports in these kinds of predicates are no longer supported: https://github.com/spring-cloud/spring-cloud-gateway/pull/3037
- Host={tenant}.localtest.me

morp:
default-oauth2-client-registration: keycloak
Expand Down
9 changes: 5 additions & 4 deletions compose/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ spring:
uri: https://httpbin.org
order: 2
predicates:
- Host={tenant}.localtest.me:8080
# Ports in these kinds of predicates are no longer supported: https://github.com/spring-cloud/spring-cloud-gateway/pull/3037
- Host={tenant}.localtest.me
- id: host-mapping-with-stage
uri: https://httpbin.org
order: 1
predicates:
- Host={tenant}-{stage}.localtest.me:8080
- Host={tenant}-{stage}.localtest.me
- id: path-mapping
uri: https://httpbin.org
predicates:
Expand All @@ -26,8 +27,8 @@ spring:
- name: TenantFromHost
args:
patterns:
- static.localtest.me:8080
- another-static.localtest.me:8080
- static.localtest.me
- another-static.localtest.me
tenant: foo
- id: header-mapping
uri: https://httpbin.org
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
14 changes: 7 additions & 7 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,15 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
Expand Down Expand Up @@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.

set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Expand Down
6 changes: 3 additions & 3 deletions src/integrationTest/java/io/jaconi/morp/ProxyIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void testKeycloak() {
var step1 = containerSetup.getWebTestClient().get()
.uri("/upstream/tenant1/test")
.accept(MediaType.TEXT_HTML)
.header("host", "morp:8081")
.header("host", "morp:8080")
.exchange()
.expectStatus().is3xxRedirection()
.expectHeader().location("/oauth2/authorization/tenant1")
Expand Down Expand Up @@ -114,7 +114,7 @@ void testKeycloak() {
var step5 = containerSetup.getWebTestClient().get()
.uri(step4.getResponseHeaders().getLocation())
.cookie(SESSION_COOKIE, session)
.header("host", "morp:8081")
.header("host", "morp:8080")
.exchange()
.expectStatus().is3xxRedirection()
.expectHeader().location("/upstream/tenant1/test")
Expand All @@ -129,7 +129,7 @@ void testKeycloak() {
var step6 = containerSetup.getWebTestClient().get()
.uri(step5.getResponseHeaders().getLocation().getPath())
.accept(MediaType.TEXT_HTML)
.header("host", "morp:8081")
.header("host", "morp:8080")
.cookie(SESSION_COOKIE, session)
.header("x-tenant-id", "tenant1")
.exchange()
Expand Down
13 changes: 6 additions & 7 deletions src/integrationTest/java/io/jaconi/morp/SeleniumIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ static class Config {


// we start Chrome for each test to ensure a clean state (i.e. cookies etc)
// screen recording not working on ARM Mac due to missing ARM image of vnc-recorder
@Container
public final BrowserWebDriverContainer<?> chrome = new BrowserWebDriverContainer<>(ArmUtil.select("seleniarm/standalone-chromium:107.0", "selenium/standalone-chrome:107.0"))
public final BrowserWebDriverContainer<?> chrome = new BrowserWebDriverContainer<>(ArmUtil.select("seleniarm/standalone-chromium:latest", "selenium/standalone-chrome:latest"))
.withNetwork(containerSetup.getNetwork())
.withNetworkAliases("chrome")
.withCapabilities(new ChromeOptions())
Expand Down Expand Up @@ -83,8 +82,8 @@ void tearDown() {

@ParameterizedTest
@CsvSource({
"tenant1, morp:8081, /upstream/tenant1, /test",
"tenant1, tenant1-morp:8081, /upstream, /test"
"tenant1, morp:8080, /upstream/tenant1, /test",
"tenant1, tenant1-morp:8080, /upstream, /test"
})
void testWithKeycloak(String tenant, String host, String prefix, String path) throws MalformedURLException {

Expand All @@ -105,7 +104,7 @@ void testWithKeycloak(String tenant, String host, String prefix, String path) th
// assert that we ended up in the right place
URL url = new URL(driver.getCurrentUrl());
assertThat(url.getHost()).isEqualTo(StringUtils.substringBefore(host, ":"));
assertThat(url.getPort()).isEqualTo(8081);
assertThat(url.getPort()).isEqualTo(8080);
assertThat(url.getPath()).isEqualTo(prefix + path);

assertThat(driver.findElement(By.id("test")).getText()).isEqualTo("Hello from mockserver");
Expand All @@ -128,8 +127,8 @@ void testWithKeycloak(String tenant, String host, String prefix, String path) th

@ParameterizedTest
@CsvSource({
"tenant2, morp:8081, /upstream/tenant2, /test",
"tenant2, tenant2-morp:8081, /upstream, /test"
"tenant2, morp:8080, /upstream/tenant2, /test",
"tenant2, tenant2-morp:8080, /upstream, /test"
})
void testWithOkta(String tenant, String host, String prefix, String path) {

Expand Down
30 changes: 15 additions & 15 deletions src/integrationTest/java/io/jaconi/morp/TestContainerSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.testcontainers.containers.Network;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
import org.testcontainers.lifecycle.Startables;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.DockerLoggerFactory;
import reactor.netty.http.client.HttpClient;
Expand Down Expand Up @@ -54,29 +55,28 @@ public TestContainerSetup() {

// setup mockserver (as protected upstream)
var tag = "mockserver-%s".formatted(MockServerClient.class.getPackage().getImplementationVersion());
this.mockserver = new MockServerContainer(DockerImageName.parse("mockserver/mockserver").withTag(tag))
DockerImageName mockServerImage = DockerImageName.parse("mockserver/mockserver").withTag(tag);
this.mockserver = new MockServerContainer(mockServerImage)
.withNetwork(network)
.withNetworkAliases("upstream");
.withNetworkAliases("upstream")
.withLogConsumer(new Slf4jLogConsumer(DockerLoggerFactory.getLogger(mockServerImage.asCanonicalNameString())));

// setup morp as auth proxy for upstream
this.morp = new GenericContainer<>(DockerImageName.parse("ghcr.io/jaconi-io/morp:latest"))
DockerImageName morpImage = DockerImageName.parse("ghcr.io/jaconi-io/morp:latest");
this.morp = new GenericContainer<>(morpImage)
.withNetwork(network)
.withNetworkAliases("morp", "tenant1-morp", "tenant2-morp")
.withExposedPorts(8081, 8082)
.withExposedPorts(8080, 8081)
.withEnv("SPRING_PROFILES_ACTIVE", "test")
.withFileSystemBind(
"./src/integrationTest/resources/morp/application.yaml",
"/workspace/config/application.yaml",
BindMode.READ_ONLY)
.waitingFor(new HttpWaitStrategy()
.forPort(8082)
.forPort(8081)
.forPath("/actuator/health/readiness")
.withStartupTimeout(Duration.ofMinutes(5)));

// start the containers
keycloak.start();
mockserver.withLogConsumer(new Slf4jLogConsumer(DockerLoggerFactory.getLogger(mockserver.getDockerImageName())))
.start();
.withStartupTimeout(Duration.ofMinutes(5)))
.withLogConsumer(new Slf4jLogConsumer(DockerLoggerFactory.getLogger(morpImage.asCanonicalNameString())));

// for local development convenience, bind mount the git-ignored 'secret.properties' (if it exists)
if (Files.exists(Path.of("./secret.properties"))) {
Expand All @@ -92,8 +92,8 @@ public TestContainerSetup() {
.filter(e -> e.getKey().startsWith("MORP_"))
.forEach(e -> morp.withEnv(e.getKey(), e.getValue()));

morp.withLogConsumer(new Slf4jLogConsumer(DockerLoggerFactory.getLogger(morp.getDockerImageName())))
.start();
// start the containers
Startables.deepStart(keycloak, mockserver, morp).join();

// create client to control mockserver (running as container)
mockServerClient = new MockServerClient(mockserver.getHost(), mockserver.getServerPort());
Expand All @@ -103,11 +103,11 @@ public TestContainerSetup() {
.wiretap(true) // hex dump wiretap
.compress(true);
webTestClient = WebTestClient.bindToServer(new ReactorClientHttpConnector(httpClient))
.baseUrl("http://localhost:" + morp.getMappedPort(8081))
.baseUrl("http://localhost:" + morp.getMappedPort(8080))
.build();

managementTestClient = WebTestClient.bindToServer(new ReactorClientHttpConnector(httpClient))
.baseUrl("http://localhost:" + morp.getMappedPort(8082))
.baseUrl("http://localhost:" + morp.getMappedPort(8081))
.build();
}

Expand Down
11 changes: 2 additions & 9 deletions src/integrationTest/resources/morp/application.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
# keycloak is running on 8080 so we need different ports for Morp here
server:
port: 8081
management:
server:
port: 8082

# Routing config
spring:
cloud:
Expand All @@ -14,7 +7,7 @@ spring:
- id: upstream-tenant-path
uri: http://upstream:1080
predicates:
- Host=morp:8081
- Host=morp
- Path=/upstream/{tenant}/{path}
filters:
- SetPath=/{path}
Expand All @@ -23,7 +16,7 @@ spring:
- id: upstream-tenant-host
uri: http://upstream:1080
predicates:
- Host={tenant}-morp:8081
- Host={tenant}-morp
- Path=/upstream/{path}
filters:
- SetPath=/{path}
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/io/jaconi/morp/MorpApplicationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MorpApplicationTests {

@Nested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@SpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MorpReactiveOAuth2UserServiceTest {

@Autowired
Expand Down
Loading

0 comments on commit b2cb480

Please sign in to comment.