Skip to content

KPMP 6414 upgrade deps#34

Merged
zwright merged 10 commits into
developfrom
KPMP-6414_upgrade-deps
Jun 8, 2026
Merged

KPMP 6414 upgrade deps#34
zwright merged 10 commits into
developfrom
KPMP-6414_upgrade-deps

Conversation

@Dert1129

@Dert1129 Dert1129 commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • Dependencies

    • Upgraded Java support from version 8 to 21.
    • Upgraded Spring Boot to version 4.0.6 with corresponding dependency management updates.
    • Updated Docker base image to Alpine 3.22.4.
  • Bug Fixes

    • Patched Tomcat embedded dependency to address CVE vulnerability.
  • Chores

    • Modernized build configuration and Gradle wrapper (v8.14).
    • Migrated servlet APIs to Jakarta standards for compatibility.
    • Updated test framework from JUnit 4 to JUnit 5 across all tests.
    • Enhanced Docker image building process using Spring Boot's native tooling.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The pull request upgrades the cassiopeia-data application from Spring Boot 2.x/Java 8 to Spring Boot 4.0.6/Java 21, modernizing the build system from legacy Gradle buildscript syntax to plugins DSL, updating Docker containerization, migrating servlet imports from javax to jakarta namespace, and converting all test code from JUnit 4 to JUnit 5.

Changes

Spring Boot 4 and Jakarta Servlet Upgrade

Layer / File(s) Summary
Build Configuration and Infrastructure
build.gradle, gradle/wrapper/gradle-wrapper.properties, Dockerfile, .github/workflows/build-gradle-project.yml
build.gradle refactored from buildscript/apply plugin to plugins DSL for Spring Boot 4.0.6 and Dependency Management 1.1.6; Java target raised to 21; project version bumped to 1.6; Palantir Docker plugin removed and replaced with bootBuildImage task; Tomcat embed core CVE override added. Gradle wrapper upgraded to version 8.14. Dockerfile updated to Alpine 3.22.4 with openjdk21 and multi-line package update. GitHub Actions workflow updated to use Java 21 JDK and ./gradlew bootBuildImage command with image tag default 1.6.
Jakarta Servlet API Migration
src/main/java/org/kpmp/error/ErrorController.java, src/main/java/org/kpmp/logging/LoggingService.java, src/main/java/org/kpmp/shibboleth/ShibbolethUserService.java, src/main/java/org/kpmp/slides/SlideController.java
Application code imports updated from javax.servlet.http.HttpServletRequest to jakarta.servlet.http.HttpServletRequest across controllers and services, aligning with Spring Boot 4 Servlet API namespace change.
Test Suite Modernization to JUnit 5 and Jakarta Servlets
src/test/java/org/kpmp/WebConfigTest.java, src/test/java/org/kpmp/error/ErrorControllerTest.java, src/test/java/org/kpmp/shibboleth/ShibbolethUserServiceTest.java, src/test/java/org/kpmp/shibboleth/ShibbolethUserTest.java, src/test/java/org/kpmp/shibboleth/UTF8EncoderTest.java, src/test/java/org/kpmp/slides/ParticipantTest.java, src/test/java/org/kpmp/slides/SlideControllerTest.java, src/test/java/org/kpmp/slides/SlideServiceTest.java, src/test/java/org/kpmp/slides/SlideTest.java, src/test/java/org/kpmp/slides/StainTest.java
All test files migrated from JUnit 4 to JUnit 5: @Before/@After annotations replaced with @BeforeEach/@AfterEach, assertion imports updated to org.junit.jupiter.api.Assertions, MockitoAnnotations.initMocks replaced with openMocks. Test files using HttpServletRequest updated to jakarta.servlet.http namespace.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch KPMP-6414_upgrade-deps
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch KPMP-6414_upgrade-deps

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Dockerfile (1)

1-19: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Run the container as a non-root user.

The image currently runs as root (no USER set), which is an avoidable security risk.

Suggested hardening patch
 FROM alpine:3.22.4
@@
 RUN apk add openjdk21
+RUN addgroup -S app && adduser -S app -G app
@@
 COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
 COPY ${DEPENDENCY}/META-INF /app/META-INF
 COPY ${DEPENDENCY}/BOOT-INF/classes /app
+RUN chown -R app:app /app /tmp
@@
 ENTRYPOINT ["java","-cp","app:app/lib/*","org.kpmp.Application"]
+USER app

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e6966e23-8a65-418f-b84b-e858a1e2c2ef

📥 Commits

Reviewing files that changed from the base of the PR and between 59a238d and 45ddafb.

📒 Files selected for processing (18)
  • .github/workflows/build-gradle-project.yml
  • Dockerfile
  • build.gradle
  • gradle/wrapper/gradle-wrapper.properties
  • src/main/java/org/kpmp/error/ErrorController.java
  • src/main/java/org/kpmp/logging/LoggingService.java
  • src/main/java/org/kpmp/shibboleth/ShibbolethUserService.java
  • src/main/java/org/kpmp/slides/SlideController.java
  • src/test/java/org/kpmp/WebConfigTest.java
  • src/test/java/org/kpmp/error/ErrorControllerTest.java
  • src/test/java/org/kpmp/shibboleth/ShibbolethUserServiceTest.java
  • src/test/java/org/kpmp/shibboleth/ShibbolethUserTest.java
  • src/test/java/org/kpmp/shibboleth/UTF8EncoderTest.java
  • src/test/java/org/kpmp/slides/ParticipantTest.java
  • src/test/java/org/kpmp/slides/SlideControllerTest.java
  • src/test/java/org/kpmp/slides/SlideServiceTest.java
  • src/test/java/org/kpmp/slides/SlideTest.java
  • src/test/java/org/kpmp/slides/StainTest.java

- name: Run build with Gradle Wrapper
run: |
./gradlew build docker
./gradlew bootBuildImage

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify build.gradle expects optional -Ptag and otherwise falls back to git branch detection.
rg -nC2 "hasProperty\\('tag'\\)|git rev-parse --abbrev-ref HEAD|bootBuildImage|imageName" build.gradle

# Verify workflow currently calls bootBuildImage without -Ptag while push uses separate tags.
rg -nC3 "IMAGE_TAG|bootBuildImage|docker push" .github/workflows/build-gradle-project.yml

Repository: KPMP/cassiopeia-data

Length of output: 1436


Pass -Ptag to bootBuildImage so the built image tag matches the Docker push tag in CI.

bootBuildImage uses getCurrentGitBranch() which falls back to git rev-parse --abbrev-ref HEAD when -Ptag isn’t provided. The workflow currently builds without -Ptag, but pushes kingstonduo/cassiopeia-data:$IMAGE_TAG for develop (IMAGE_TAG=1.7) and kingstonduo/cassiopeia-data:${current_branch} otherwise—leading to mismatched tags (e.g., detached HEAD yielding :HEAD).
Fix by computing TAG the same way as the push step and running ./gradlew bootBuildImage -Ptag="$TAG".

Comment thread Dockerfile
RUN apk update && \
apk upgrade
RUN apk add openjdk8
RUN apk add openjdk21

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use --no-cache for apk add on Line 5.

Without --no-cache, APK index/cache layers are kept and unnecessarily bloat the image.

Suggested patch
-RUN apk add openjdk21
+RUN apk add --no-cache openjdk21
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN apk add openjdk21
RUN apk add --no-cache openjdk21
🧰 Tools
🪛 Trivy (0.69.3)

[error] 5-5: 'apk add' is missing '--no-cache'

'--no-cache' is missed: apk add openjdk21

Rule: DS-0025

Learn more

(IaC/Dockerfile)

Comment on lines +26 to 35
@BeforeEach
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
controller = new ErrorController(logger);
}

@After
@AfterEach
public void tearDown() throws Exception {
controller = null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file and print the relevant section with line numbers
FILE="src/test/java/org/kpmp/error/ErrorControllerTest.java"
if [ -f "$FILE" ]; then
  echo "=== $FILE (lines around 20-60) ==="
  nl -ba "$FILE" | sed -n '1,120p'
else
  echo "File not found: $FILE"
  exit 1
fi

# Search for usage patterns of MockitoAnnotations.openMocks in the test suite
echo "=== Search for MockitoAnnotations.openMocks usage ==="
rg -n "MockitoAnnotations\.openMocks\(" src/test/java || true

# Check if any existing tearDown closes mocks elsewhere in this file
echo "=== Search for ".close()". patterns in this file ==="
rg -n "\.close\(\)" "$FILE" || true

Repository: KPMP/cassiopeia-data

Length of output: 208


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the file by name (path may differ)
echo "=== Locating ErrorControllerTest.java ==="
FILE_PATH="$(fd -H "ErrorControllerTest\.java$" . || true | head -n 1)"
echo "Found: ${FILE_PATH:-<none>}"

if [ -z "${FILE_PATH:-}" ]; then
  exit 0
fi

# Print a focused section with line numbers (use cat -n since nl may be unavailable)
echo "=== File excerpt (lines 1-160) ==="
cat -n "$FILE_PATH" | sed -n '1,160p'

# Search for MockitoAnnotations.openMocks usage
echo "=== Search for MockitoAnnotations.openMocks usage ==="
rg -n "MockitoAnnotations\.openMocks\(" "$(dirname "$FILE_PATH")" || true

# Search for closing calls in this file
echo "=== Search for .close() in this file ==="
rg -n "\.close\(\)" "$FILE_PATH" || true

# Search for AutoCloseable field/variable in this file
echo "=== Search for AutoCloseable in this file ==="
rg -n "AutoCloseable" "$FILE_PATH" || true

Repository: KPMP/cassiopeia-data

Length of output: 2344


Close Mockito openMocks resources in tearDown.

MockitoAnnotations.openMocks(this) in setUp() returns an AutoCloseable, but tearDown() only nulls controller and never closes the mocks, risking test resource leaks.

Proposed fix
 public class ErrorControllerTest {
 
 	private ErrorController controller;
+	private AutoCloseable mocks;
 	`@Mock`
 	private LoggingService logger;
 
 	`@BeforeEach`
 	public void setUp() throws Exception {
-		MockitoAnnotations.openMocks(this);
+		mocks = MockitoAnnotations.openMocks(this);
 		controller = new ErrorController(logger);
 	}
 
 	`@AfterEach`
 	public void tearDown() throws Exception {
+		if (mocks != null) {
+			mocks.close();
+		}
 		controller = null;
 	}

Comment on lines +26 to 35
@BeforeEach
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
shibbolethUserService = new ShibbolethUserService(utf8Encoder);
}

@After
@AfterEach
public void tearDown() throws Exception {
shibbolethUserService = null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and print the relevant test file
FILE="src/test/java/org/kpmp/shibboleth/ShibbolethUserServiceTest.java"
if [ -f "$FILE" ]; then
  echo "=== $FILE ==="
  nl -ba "$FILE" | sed -n '1,200p'
else
  echo "File not found: $FILE"
  exit 1
fi

# Search for other uses of MockitoAnnotations.openMocks without closing in test sources
echo
echo "=== Search for MockitoAnnotations.openMocks(this) in tests ==="
rg -n --hidden --no-ignore -S "MockitoAnnotations\.openMocks\(\s*this\s*\)" src/test/java || true

# Search for close() on the result of openMocks (rough heuristic)
echo
echo "=== Search for patterns closing mocks returned from openMocks ==="
rg -n --hidden --no-ignore -S "openMocks\\(.*\\).*close\\(" src/test/java || true

Repository: KPMP/cassiopeia-data

Length of output: 198


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/test/java/org/kpmp/shibboleth/ShibbolethUserServiceTest.java"

if [ -f "$FILE" ]; then
  echo "=== $FILE (first 200 lines) ==="
  cat -n "$FILE" | sed -n '1,200p'
else
  echo "File not found: $FILE"
  exit 1
fi

echo
echo "=== Search for MockitoAnnotations.openMocks(this) in src/test/java ==="
rg -n -S "MockitoAnnotations\.openMocks\(\s*this\s*\)" src/test/java || true

echo
echo "=== Search for close() on the returned value of openMocks (heuristic) ==="
rg -n -S "openMocks\([^)]*\)\s*;|openMocks\([^)]*\)\s*\\)" src/test/java || true
rg -n -S "openMocks\([^)]*\).*close\(" src/test/java || true
rg -n -S "AutoCloseable\s+.*mocks|mocks\.close\(" src/test/java || true

Repository: KPMP/cassiopeia-data

Length of output: 3890


Close MockitoAnnotations.openMocks(...) AutoCloseable in @AfterEach. (src/test/java/org/kpmp/shibboleth/ShibbolethUserServiceTest.java:26-35)

MockitoAnnotations.openMocks(this) returns an AutoCloseable that’s currently discarded; store it and close it in tearDown() to avoid mock initialization resource leakage across tests.

Proposed fix
 public class ShibbolethUserServiceTest {
 
 	private ShibbolethUserService shibbolethUserService;
+	private AutoCloseable mocks;
 	`@Mock`
 	private UTF8Encoder utf8Encoder;
 
 	`@BeforeEach`
 	public void setUp() throws Exception {
-		MockitoAnnotations.openMocks(this);
+		mocks = MockitoAnnotations.openMocks(this);
 		shibbolethUserService = new ShibbolethUserService(utf8Encoder);
 	}
 
 	`@AfterEach`
 	public void tearDown() throws Exception {
+		if (mocks != null) {
+			mocks.close();
+		}
 		shibbolethUserService = null;
 	}

Comment on lines +33 to 42
@BeforeEach
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
controller = new SlideController(slideService, logger, shibbolethUserService);
}

@After
@AfterEach
public void tearDown() throws Exception {
controller = null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Close the Mockito openMocks handle in @AfterEach
MockitoAnnotations.openMocks(this) returns an AutoCloseable, but tearDown() currently only nulls controller, leaving the Mockito open-mocks resources unclosed.

Proposed fix
 public class SlideControllerTest {
 
 	`@Mock`
 	private SlideService slideService;
+	private AutoCloseable mocks;
 	private SlideController controller;
 	`@Mock`
 	private LoggingService logger;
 	`@Mock`
 	private ShibbolethUserService shibbolethUserService;
 
 	`@BeforeEach`
 	public void setUp() throws Exception {
-		MockitoAnnotations.openMocks(this);
+		mocks = MockitoAnnotations.openMocks(this);
 		controller = new SlideController(slideService, logger, shibbolethUserService);
 	}
 
 	`@AfterEach`
 	public void tearDown() throws Exception {
+		if (mocks != null) {
+			mocks.close();
+		}
 		controller = null;
 	}

Comment on lines +23 to 32
@BeforeEach
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
service = new SlideService(participantRepository);
}

@After
@AfterEach
public void tearDown() throws Exception {
service = null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file (in case path differs) and print relevant sections with line numbers
fd -a "SlideServiceTest.java" . || true
FILE="src/test/java/org/kpmp/slides/SlideServiceTest.java"
if [ -f "$FILE" ]; then
  echo "=== $FILE (lines 1-200) ==="
  nl -ba "$FILE" | sed -n '1,200p'
else
  echo "File not found: $FILE"
fi

# Search for openMocks usage in repo to see any patterns/other tests
rg -n "MockitoAnnotations\.openMocks\\(this\\)|openMocks\\(" src/test/java/org/kpmp/slides -S || true
rg -n "MockitoAnnotations\.openMocks\\(" src/test/java -S || true

Repository: KPMP/cassiopeia-data

Length of output: 270


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/test/java/org/kpmp/slides/SlideServiceTest.java"
echo "=== $FILE (first 200 lines) ==="
if [ -f "$FILE" ]; then
  cat -n "$FILE" | sed -n '1,200p'
else
  echo "File not found: $FILE" >&2
  exit 0
fi

echo "=== Search for MockitoAnnotations.openMocks usage ==="
rg -n "MockitoAnnotations\.openMocks\s*\(" src/test/java -S || true

echo "=== Search for closing returned handle (.close()) around openMocks ==="
rg -n "openMocks\s*\(.*\)|close\(\)\s*;|AutoCloseable\s+mocks|MockitoAnnotations\." src/test/java/org/kpmp/slides -S || true

Repository: KPMP/cassiopeia-data

Length of output: 4762


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILES=(
  "src/test/java/org/kpmp/slides/SlideControllerTest.java"
  "src/test/java/org/kpmp/error/ErrorControllerTest.java"
  "src/test/java/org/kpmp/shibboleth/ShibbolethUserServiceTest.java"
)

for f in "${FILES[@]}"; do
  echo "=== $f (lines 1-160) ==="
  if [ -f "$f" ]; then
    cat -n "$f" | sed -n '1,160p'
  else
    echo "Missing: $f" >&2
  fi
done

echo "=== Search across src/test/java for openMocks handle assignment + close ==="
rg -n "MockitoAnnotations\.openMocks\s*\(.*\)|openMocks\s*\(.*\)" src/test/java -S

echo "=== Search across src/test/java for close() near openMocks ==="
rg -n "openMocks\s*\(.*\)[\s\S]{0,200}?close\s*\(" src/test/java -S || true

echo "=== Search across src/test/java for '.close();' on an AutoCloseable mocks handle ==="
rg -n "AutoCloseable\s+[^;]*mocks|mocks\s*=\s*MockitoAnnotations\.openMocks|mocks\.close\(" src/test/java -S || true

Repository: KPMP/cassiopeia-data

Length of output: 8907


Close the MockitoAnnotations.openMocks(...) resource in @AfterEach.

MockitoAnnotations.openMocks(this) (line 25) returns an AutoCloseable, but tearDown() only sets service = null and never closes it.

Proposed fix
 public class SlideServiceTest {
 
 	`@Mock`
 	private ParticipantRepository participantRepository;
+	private AutoCloseable mocks;
 	private SlideService service;
 
 	`@BeforeEach`
 	public void setUp() throws Exception {
-		MockitoAnnotations.openMocks(this);
+		mocks = MockitoAnnotations.openMocks(this);
 		service = new SlideService(participantRepository);
 	}
 
 	`@AfterEach`
 	public void tearDown() throws Exception {
+		if (mocks != null) {
+			mocks.close();
+		}
 		service = null;
 	}

@zwright zwright merged commit 0bd0b96 into develop Jun 8, 2026
1 check passed
@zwright zwright deleted the KPMP-6414_upgrade-deps branch June 8, 2026 16:57
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.

2 participants