Skip to content

Fix compilation failures after Spring Boot 4.x / Jackson 3.x / Spring Security 7 / Hibernate 7 upgrade - #2

Merged
gortazar merged 13 commits into
mainfrom
copilot/update-springboot-java-versions
Oct 29, 2026
Merged

gortazar merged 13 commits into
mainfrom
copilot/update-springboot-java-versions

Conversation

@gortazar

Copy link
Copy Markdown
Contributor
  • upgrade: Spring Boot to 4.0.5 and Java to 21
  • Actualizar maven-build.yml
  • Add spring-boot-starter-json
  • Fix Jackson 3.x migration: update imports and API changes in rest_ejem8, bd_ejem19, comunicacion-ws-ejem2
  • Fix compilation failures after Spring Boot 4.x / Jackson 3.x upgrade
  • Fix all remaining compilation failures: Jackson 3.x, Hibernate 7, Spring Security 7, Spring Session 4.x, CI workflow

gortazar and others added 9 commits April 4, 2026 16:43
…m8, bd_ejem19, comunicacion-ws-ejem2

Agent-Logs-Url: https://github.com/codeurjc/dad2425/sessions/62560d7f-165d-47e7-ba36-87588d19ffb2

Co-authored-by: gortazar <203272+gortazar@users.noreply.github.com>
…ing Security 7, Spring Session 4.x, CI workflow

Agent-Logs-Url: https://github.com/codeurjc/dad2425/sessions/63ada7cb-c19d-454b-9ff6-ea5c62f687b3

Co-authored-by: gortazar <203272+gortazar@users.noreply.github.com>
Spring Boot 4 ships Jackson 3, so com.fasterxml.jackson.databind is gone
from the classpath and Jackson2JsonMessageConverter fails at startup with
ClassNotFoundException on com.fasterxml.jackson.databind.json.JsonMapper.
Spring AMQP 4 provides JacksonJsonMessageConverter as the Jackson 3
equivalent.

The ExampleData classes in these projects had already been moved to
tools.jackson.databind; only the converter bean was left behind.

Verified on Temurin 21: all six compile and their Spring context starts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
H2 treats USER as reserved, so Hibernate's generated DDL failed at startup
in three samples. MySQL accepts it, which is why these ran for years and
only broke on the H2-backed profiles.

Renamed the entity rather than quoting the identifier: a delimited name
would be case-sensitive and would have to be quoted in every hand-written
query, which is a trap for students using the H2 console.

- parte_5/ejem3-cache-distribuida: User -> AppUser
- parte_5/ejem4b-haproxy-ssl-passthrough: User -> AppUser
- parte_2/tema_2.5_db/bd_ejer2: Post.user -> Post.author, since the clash
  there is a column, not a table; templates and the form field follow.

In new_post.html only the form field was renamed. The {{#user}} section
there reads the model attribute the controller sets from UserSession,
which is a different thing and still named user. Visible labels are left
untouched.

Verified on Temurin 21: the three compile and their Spring context starts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
spring-cloud-dependencies 2023.0.0 is built for Spring Boot 3.2, so under
4.0.5 the OpenFeign autoconfiguration failed to start looking for
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,
which Boot 4 moved.

2025.1.4 is the current stable train and declares spring-boot.version 4.0.9,
checked against its published POM on Maven Central. It is the only project
in the branch that imports a Spring Cloud BOM.

Verified on Temurin 21: compiles and the Spring context starts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gortazar

Copy link
Copy Markdown
Contributor Author

Upgrades every sample to Spring Boot 4.0.5 and Java 21, and fixes the ten
projects that were left broken by the first pass.

Verification

Full sweep of all 85 Maven projects on Temurin 21:

Before After
Compile 85 85
Start up 62 72
Fail 11 1
Skipped 12 12

"Start up" means spring-boot:run on a random port reaching Started … in Ns.
Skipped are the projects that need MySQL from docker-compose.

The one remaining failure, parte_5/ejem0-jmeter, is not a regression: it takes
its datasource URL from docker-compose, so it belongs with the skipped group.

What was fixed on top of the upgrade

Jackson 3 migration left half-done — 6 projects. Spring Boot 4 ships Jackson 3,
so com.fasterxml.jackson.databind is gone and Jackson2JsonMessageConverter
threw ClassNotFoundException on JsonMapper at startup. Spring AMQP 4 provides
JacksonJsonMessageConverter for Jackson 3. The ExampleData classes in these
same projects had already been moved to tools.jackson.databind; only the
converter bean was missed.

USER is a SQL reserved word — 3 projects. H2 rejected Hibernate's generated
DDL. MySQL accepts it, which is why these ran for years and only broke on the
H2-backed profiles. Renamed rather than quoted: a delimited identifier is
case-sensitive and must be quoted in every hand-written query, which is a trap
for students using the H2 console.

  • parte_5/ejem3-cache-distribuida: User → AppUser
  • parte_5/ejem4b-haproxy-ssl-passthrough: User → AppUser
  • parte_2/tema_2.5_db/bd_ejer2: the clash is a column, not a table, so
    Post.user → Post.author, with templates and the form field following

In new_post.html only the form field was renamed. The {{#user}} section there
reads the model attribute the controller sets from UserSession, which is a
different thing. Visible labels are left untouched.

Spring Cloud train too old — 1 project. rest_ejem9 imported
spring-cloud-dependencies 2023.0.0, built for Boot 3.2, so OpenFeign's
autoconfiguration looked for WebMvcAutoConfiguration where Boot 4 no longer
keeps it. Moved to 2025.1.4, whose published POM declares
spring-boot.version 4.0.9. It is the only project here importing a Spring
Cloud BOM.

Known issue, not addressed here

parte_2/tema_2.5_db/bd_ejem17 declares querydsl-apt as a provided
dependency with no annotationProcessorPaths, so it relies on implicit
annotation processing. That still works on Java 21, but JDK 23 and later no
longer run processors found on the classpath, and QPost stops being generated.
It will need an explicit annotationProcessorPaths before the next JDK bump.

Supersedes codeurjc#2.

gortazar and others added 2 commits October 28, 2026 14:09
main had moved parte_5/ejem1-mysql to parte_5/ejem1-jmeter/ejem-1 and
reorganised the scalability examples, so git flagged the two poms this
branch had already bumped. Both conflicts are the same file under a new
path: resolved to 4.0.5, the version this branch is standardising on.

ejem-2-cache-redis arrived from main at 3.5.12 and was bumped to match.
The merged tree now has all 86 poms on Spring Boot 4.0.5 and Java 21.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two separate breakages in ejem1-jmeter/ejem-2-cache-redis, both from the
Boot 4 restructuring, found by booting it against real MySQL and Redis
containers rather than by compiling it.

Boot 4 split autoconfiguration into per-area modules, so
spring-boot-starter-data-redis alone no longer contributes the cache
autoconfiguration and @EnableCaching found no CacheManager. Added
spring-boot-starter-cache.

With that in place the next failure was the same Jackson 2 to 3 move as in
the AMQP samples: GenericJackson2JsonRedisSerializer is gone from the
classpath. Spring Data Redis 4 provides GenericJacksonJsonRedisSerializer,
which unlike its predecessor has no no-arg constructor and takes a
tools.jackson.databind.ObjectMapper.

Verified on Temurin 21: starts in 5s against mysql:8.0 and redis:alpine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gortazar

Copy link
Copy Markdown
Contributor Author

Merged main and verified the samples it brought in

The branch was 6 commits behind and the PR could not merge. Resolved and re-verified.

The conflict was a rename. main had moved parte_5/ejem1-mysql to
parte_5/ejem1-jmeter/ejem-1 and reorganised the scalability examples, so the two
poms this branch had already bumped showed up as conflicts under a new path. Both
resolved to 4.0.5. ejem-2-cache-redis arrived from main still on 3.5.12 and was
bumped to match. All 86 poms are now on Spring Boot 4.0.5 and Java 21.

Two more breakages, found by running rather than compiling.
ejem1-jmeter/ejem-2-cache-redis compiled fine but did not start:

  1. Boot 4 split autoconfiguration into per-area modules, so
    spring-boot-starter-data-redis alone no longer contributes the cache
    autoconfiguration and @EnableCaching found no CacheManager. Added
    spring-boot-starter-cache. This is the same restructuring that broke the
    Spring Cloud import in rest_ejem9.
  2. With that fixed, the same Jackson 2 to 3 move as in the AMQP samples surfaced:
    GenericJackson2JsonRedisSerializer is gone. Spring Data Redis 4 provides
    GenericJacksonJsonRedisSerializer, which takes a
    tools.jackson.databind.ObjectMapper and has no no-arg constructor.

These three projects need MySQL, so the automated sweep skips them. They were
booted by hand against mysql:8.0 and redis:alpine containers, with the
repository's own initdb/data_load.sql loaded. All three start.

Current state

Count
Projects 86
Compile 86
Start up 75 (72 from the sweep + these 3 by hand)
Fail 0
Skipped 11 (need MySQL from docker-compose)

parte_5/ejem0-jmeter is in the skipped group: it takes its datasource URL from
docker-compose, so it cannot start standalone. It is not a regression.

Still open, unrelated to this upgrade

parte_2/tema_2.5_db/bd_ejem17 declares querydsl-apt as provided with no
annotationProcessorPaths, relying on implicit annotation processing. That works
on Java 21 but JDK 23 and later no longer run processors found on the classpath,
so QPost silently stops being generated. Worth fixing before the next JDK bump.

gortazar and others added 2 commits October 29, 2026 07:43
Nothing in this branch was covered by a test: only one of the 86 projects
shipped any, so "it compiles" was the whole guarantee behind the Spring
Boot 4 upgrade. Every project now has a SmokeTest that boots it.

Three shapes, picked per project:

- Spring Boot apps with no external service: @SpringBootTest, which fails
  if any bean cannot be created. That is what caught the Jackson 3 and
  autoconfiguration breakage earlier in this branch.
- Apps backed by MySQL, RabbitMQ or Redis: Testcontainers via
  @Serviceconnection, plus a test that opens the connection and checks it
  answers. 21 projects, with real containers.
- parte_4/tema_4.2/ejemplo-2 is a plain command-line program with no
  Spring: it runs main() and asserts the arguments come out. JUnit and
  surefire are declared there by hand, since that pom has no Boot parent.

Three projects needed more than the test itself:

- parte_4/tema_4.3/ejemplo-{2,3} have a second @SpringBootConfiguration
  (DatabaseWaitConfigurator), so the test says classes = WebApp.class
  instead of letting the search find two candidates.
- parte_2/tema_2.6_despliegue/despliegue_ejem2 defaults to the dev
  profile, which pins H2Dialect. @Serviceconnection replaces the URL and
  the credentials but not the dialect, so Hibernate emitted sequence DDL
  against MySQL. The test runs under the prod profile instead.

parte_5/ejem0-jmeter had an Ejem0EmployeeApplicationTests doing
contextLoads() against a database that only exists under docker-compose,
so it could never pass on its own. The new SmokeTest replaces it and
brings its own container.

Verified on Temurin 21: mvn clean verify on all 86 projects, 86 green,
132 tests, 21 of them against real containers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The matrix was 86 paths written out one by one, and it went stale as soon
as parte_5 was reorganised: the last run failed on a working directory
that no longer existed, not on any code. A discover job now derives the
list from git ls-files, so moving or adding a project needs no edit here.

Using git ls-files rather than find keeps generated poms under target/
out of the list. It refuses to continue on zero projects, and on more
than 256, which is the matrix limit GitHub enforces.

Two other things were wrong in this file:

- The branch filter was '*', which does not match a branch name with a
  slash in it. Pushes to copilot/update-springboot-java-versions never
  triggered a run; what did run came in as a pull_request event, whose
  filter applies to the base branch. It is '**' now.
- The build ran mvn clean package -DskipTests, so the tests added in the
  previous commit would never have run in CI. It is mvn clean verify.

A result job gates the whole matrix, so branch protection has one check
to require instead of 86 names that change.

Added concurrency cancel-in-progress: one push is 86 jobs, and there is
no point finishing a run whose commit is already superseded. Drop that
block if you would rather keep every run.

Verified: the discovery pipeline returns the same 86 projects the hand
written matrix listed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gortazar

Copy link
Copy Markdown
Contributor Author

Smoke tests on every project, and a CI matrix that discovers them

Two commits on top of the previous report.

9724c66 — a smoke test in all 86 projects

Only one project in the branch shipped a test, so "it compiles" was the whole guarantee behind the Spring Boot 4 upgrade. Three shapes, picked per project:

  • Spring Boot apps with no external service — @SpringBootTest, which fails if any bean cannot be created. That is the check that caught the Jackson 3 and autoconfiguration breakage earlier in this branch.
  • Apps backed by MySQL, RabbitMQ or Redis — Testcontainers through @ServiceConnection, plus a test that opens the connection and checks it answers. 21 projects.
  • parte_4/tema_4.2/ejemplo-2 — a plain command-line program with no Spring. It runs main() and asserts the arguments come out. JUnit and surefire are declared by hand there, since that pom has no Boot parent.

Three projects needed more than the test itself:

Project Problem Fix
parte_4/tema_4.3/ejemplo-2 Two @SpringBootConfiguration classes (WebApp plus DatabaseWaitConfigurator) @SpringBootTest(classes = WebApp.class)
parte_4/tema_4.3/ejemplo-3 same same
parte_2/tema_2.6_despliegue/despliegue_ejem2 The dev profile pins H2Dialect; @ServiceConnection replaces the URL and credentials but not the dialect, so Hibernate emitted sequence DDL against MySQL The test runs under the prod profile

parte_5/ejem0-jmeter had an Ejem0EmployeeApplicationTests running contextLoads() against a database that only exists under docker-compose, so it could never pass on its own. The new SmokeTest replaces it and brings its own container.

f061417 — CI discovers the projects

The matrix was 86 paths written out by hand, and it went stale as soon as parte_5 was reorganised: run 40696456183 failed on a working directory that no longer existed, not on any code. A discover job now derives the list from git ls-files, so moving or adding a project needs no edit to the workflow. git ls-files rather than find, to keep generated poms under target/ out of the list.

Two other things were wrong in that file:

  • The branch filter was '*', which does not match a branch name containing a slash. Pushes to this branch never triggered a run; what did run arrived as a pull_request event, whose filter applies to the base branch. It is '**' now.
  • The build ran mvn clean package -DskipTests, so the tests above would never have run in CI. It is mvn -B -ntp clean verify.

A result job gates the matrix, so branch protection has one stable check to require instead of 86 names that change.

Local verification

mvn clean verify on all 86 projects with Temurin 21:

Projects 86
Green 86
Tests run 132
Against real containers 21

Still open, unrelated to this upgrade

parte_2/tema_2.5_db/bd_ejem17 declares querydsl-apt as provided without annotationProcessorPaths. It works on Java 21, but from JDK 23 on javac no longer runs annotation processors found on the classpath, so QPost silently stops being generated.

@gortazar
gortazar marked this pull request as ready for review October 29, 2026 07:18
Copilot AI balanced review requested due to automatic review settings October 29, 2026 07:18

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@gortazar
gortazar merged commit 39f3529 into main Oct 29, 2026
176 checks passed
@gortazar
gortazar deleted the copilot/update-springboot-java-versions branch October 29, 2026 07:53
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.

3 participants