Skip to content

Upgrade to Java 17 (LTS) with Spring Boot 2.7.18 across Maven and Gradle - #61

Open
tobydrinkall wants to merge 2 commits into
masterfrom
devin/1785430760-java17-upgrade
Open

tobydrinkall wants to merge 2 commits into
masterfrom
devin/1785430760-java17-upgrade

Conversation

@tobydrinkall

@tobydrinkall tobydrinkall commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Moves both build systems from Java 8 to Java 17. Spring Boot 2.0.2 cannot run on JDK 17, so Boot is bumped to 2.7.18 — the last 2.x release, which supports JDK 17 while keeping the javax.* namespace, so no Jakarta EE 9 migration is needed (Boot 3.x would force javax.* -> jakarta.* across the app).

pom.xml and build.gradle declare the Java level independently, so both were updated:

  • pom.xml: parent 2.0.2.RELEASE -> 2.7.18; <java.version>1.8</java.version> -> 17. Also <packaging>pom</packaging> -> jar — with pom packaging Maven never compiled src/main/java at all, so mvn verify was passing vacuously and would not have caught any Java 17 breakage. With jar it now compiles and repackages via spring-boot-maven-plugin. Dropped spring-boot-properties-migrator (a temporary 2.0-era migration aid) and moved h2 to <scope>runtime</scope> to match the Gradle declaration.
  • build.gradle: plugin classpath -> 2.7.18; sourceCompatibility/targetCompatibility = 1.8 replaced with a toolchain:
    java { toolchain { languageVersion = JavaLanguageVersion.of(17) } }
    compile/testCompile -> implementation/testImplementation (removed in Gradle 7), and bootJar { baseName/version } -> archiveBaseName/archiveVersion. Added spring-boot-starter-jdbc + h2 (runtime) which the Gradle build was missing — Application.java imports JdbcTemplate, so the Gradle build could not compile without them (this was already broken pre-upgrade).
  • Wrappers: Gradle 4.6 -> 7.6.4 (4.6 cannot run on JDK 17), including regenerated gradlew/gradlew.bat/gradle-wrapper.jar; Maven wrapper distribution 3.3.9 -> 3.9.9. Also set the executable bit on gradlew/mvnw.

No javax -> jakarta changes, and no application source changes were required.

Validation

Both builds run green on openjdk 17.0.13:

  • mvn clean verify -> BUILD SUCCESS (compiles 13 sources, produces gs-spring-boot-0.1.0.jar)
  • ./gradlew clean build -> BUILD SUCCESSFUL

The repo contains no test sources (:test NO-SOURCE, no surefire tests), so the builds' test phases execute with nothing to run. To get real runtime evidence the boot jar was also executed. Boot 2.7.18 pulls H2 1.4.197 -> 2.1.214, and the legacy-looking startup SQL in Application.java (DROP TABLE customers IF EXISTS, CREATE TABLE customers(id SERIAL, ...)) still works against H2 2.x:

INFO hello.Application : Started Application in 1.072 seconds
INFO hello.Application : Creating tables
INFO hello.Application : Inserting customer record for John Woo
...
INFO hello.Application : Customer{id=3, firstName='Josh', lastName='Bloch'}
INFO hello.Application : Customer{id=4, firstName='Josh', lastName='Long'}

Pre-existing, unrelated to this PR: the app then exits non-zero because the CommandLineRunner at Application.java:52 calls http://gturnquist-quoters.cfapps.io/api/random, a host that no longer resolves.

Note: Maven Central rate-limited (HTTP 429) this machine's IP, so artifacts were fetched through a local-only mirror config in ~/.m2/settings.xml / ~/.gradle/init.gradle. Nothing mirror-related is committed.

Link to Devin session: https://app.devin.ai/sessions/fc811dde869648ada4227c75b83f2c4e
Requested by: @tobydrinkall


Devin Review

Status Commit
⚪ Not started

Run Devin Review

Open in Devin Review (Staging)
Open in Devin Review

Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
@tobydrinkall tobydrinkall self-assigned this Jul 30, 2026
@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 4 potential issues.

Open in Devin Review

Comment thread pom.xml

<properties>
<java.version>1.8</java.version>
<java.version>17</java.version>

@devin-ai-integration devin-ai-integration Bot Jul 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Startup DDL/behaviour affected by H2 1.4 -> 2.x bump

The Boot bump pulls H2 from 1.4.x to 2.1.x, and hello/Application.java:66-68 runs DROP TABLE customers IF EXISTS / CREATE TABLE customers(id SERIAL, ...) on every startup via CommandLineRunner. That SQL is still accepted by H2 2.x (same snippet is used by the current Spring relational-data-access guide), so this is not flagged as a bug, but the runtime path was not exercised by the build-only validation described in the PR — a manual mvn spring-boot:run smoke test would confirm. Note the app also has two runners hitting the long-dead gturnquist-quoters.cfapps.io endpoint, which will NPE on startup; that is pre-existing and unrelated to the upgrade.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified by actually running the app on JDK 17 (java -jar target/gs-spring-boot-0.1.0.jar). H2 does resolve to 2.1.214 via the 2.7.18 BOM, and both statements execute fine against it:

INFO hello.Application : Creating tables
INFO hello.Application : Inserting customer record for John Woo
...
INFO hello.Application : Customer{id=3, firstName='Josh', lastName='Bloch'}
INFO hello.Application : Customer{id=4, firstName='Josh', lastName='Long'}

DROP TABLE customers IF EXISTS and SERIAL are both still accepted by H2 2.x in its default (REGULAR) compatibility mode, so no SQL change is needed. The app does still exit non-zero afterwards, but only because the CommandLineRunner at Application.java:52 calls http://gturnquist-quoters.cfapps.io/api/random, a host that no longer exists (UnknownHostException) — pre-existing and unrelated to this upgrade.

Comment thread build.gradle
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-jdbc")
runtimeOnly("com.h2database:h2")
testImplementation("junit:junit")

@devin-ai-integration devin-ai-integration Bot Jul 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Unversioned junit:junit relies on the Boot BOM still managing JUnit 4

testImplementation("junit:junit") has no version and depends on io.spring.dependency-management supplying it from spring-boot-dependencies. Boot 2.7.x still manages junit:junit, so this resolves; note that this breaks if the project is later moved to Boot 3.x, where JUnit 4 management was dropped. Also relevant: Gradle 7.6.4 was a deliberate pick since the Boot 2.7 Gradle plugin does not support Gradle 8.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that this declaration isn't exercised, but I'd rather not change test-framework wiring in a build-level upgrade PR. For the record the coordinate does resolve — the Boot 2.7.18 BOM manages junit:junit at 4.13.2 — it's just that with no test sources nothing forces resolution. Leaving it as-is; swapping to spring-boot-starter-test makes sense as a follow-up when tests are actually added.

Comment thread build.gradle
Comment thread pom.xml
Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment thread pom.xml
Comment on lines 17 to -22
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: properties-migrator removal is silent but harmless here

The spring-boot-properties-migrator runtime dependency is dropped without being mentioned in the PR description. It is only a diagnostic aid for renamed/removed Boot properties, and the only configuration file in the repo (application.properties at the repo root, single commented-out #server.port line) contains no active properties, so no 2.0 -> 2.7 property renames can silently break. Worth noting separately that application.properties sits at the repo root rather than src/main/resources, so it is not packaged into the new jar at all — with the packaging switch to jar it may be worth moving it if it is ever intended to take effect.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description has since been updated to call out both the spring-boot-properties-migrator removal and the H2 runtime-scope change, so that's covered.

Agreed on the analysis: the root application.properties has only a commented-out #server.port, so there are no 2.0 -> 2.7 renames for the migrator to have caught. Leaving the file where it is — moving it into src/main/resources would newly activate a config file that has never taken effect, which is a behavior change beyond the scope of a JDK/Boot upgrade. Happy to do it as a follow-up if that's wanted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant