-
Notifications
You must be signed in to change notification settings - Fork 0
feat(spring-caffeine): initialize Spring Caffeine example project wit… #144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…h caching implementation and Docker support
WalkthroughAdds a new spring-caffeine-example module to the repository, including complete Spring Boot application code demonstrating in-memory caching with Caffeine, GitHub Actions CI/CD workflows, Docker configuration, and Maven wrapper setup. Updates root configuration files to register the new project. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 16
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (29)
.github/labeler.yml(1 hunks).github/workflows/spring-caffeine-example.yml(1 hunks)README.md(1 hunks)pom.xml(1 hunks)spring-caffeine-example/.dockerignore(1 hunks)spring-caffeine-example/.gitattributes(1 hunks)spring-caffeine-example/.github/workflows/maven.yml(1 hunks)spring-caffeine-example/.gitignore(1 hunks)spring-caffeine-example/.mvn/wrapper/maven-wrapper.properties(1 hunks)spring-caffeine-example/Dockerfile(1 hunks)spring-caffeine-example/README.md(1 hunks)spring-caffeine-example/compose.yaml(1 hunks)spring-caffeine-example/mvnw(1 hunks)spring-caffeine-example/mvnw.cmd(1 hunks)spring-caffeine-example/pom.xml(1 hunks)spring-caffeine-example/src/main/java/com/io/example/SpringCaffeineExampleApplication.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/client/CaffeineVersionClient.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/config/CacheConfig.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/controller/CaffeineController.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/dto/CaffeineResponseDto.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/external/controller/ExternalApiController.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/external/dto/ExternalApiResponseDto.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/properties/CaffeineProperties.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/repository/CaffeineDescriptionRepository.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/service/CaffeineService.java(1 hunks)spring-caffeine-example/src/main/java/com/io/example/service/CaffeineServiceImpl.java(1 hunks)spring-caffeine-example/src/main/resources/application-prd.yaml(1 hunks)spring-caffeine-example/src/main/resources/application.yaml(1 hunks)spring-caffeine-example/src/main/resources/sql/init.sql(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: igorcampos-dev
Repo: igorcampos-dev/spring-integrations-examples PR: 21
File: spring-kafka-example/README.md:12-17
Timestamp: 2025-07-22T01:35:41.406Z
Learning: User igorcampos-dev prefers minimal, high-level documentation in README files without detailed version specifications, choosing to keep tech stack information simple rather than adding precise version numbers.
Learnt from: igorcampos-dev
Repo: igorcampos-dev/spring-integrations-examples PR: 21
File: spring-kafka-example/compose.yaml:30-32
Timestamp: 2025-07-22T01:30:57.054Z
Learning: User igorcampos-dev prefers to maintain environment parity between local development and production, avoiding development-specific configurations like ALLOW_PLAINTEXT_LISTENER even when they might provide clearer intent or safety nets.
Learnt from: igorcampos-dev
Repo: igorcampos-dev/spring-integrations-examples PR: 26
File: spring-kafka-example/compose.yaml:3-4
Timestamp: 2025-07-24T01:40:49.337Z
Learning: User igorcampos-dev requires hard-coded container names in Docker Compose files (like `container_name: app`) for CI pipeline validation purposes, which is a valid operational requirement that overrides the general best practice of avoiding hard-coded container names.
📚 Learning: 2025-07-27T19:51:52.736Z
Learnt from: igorcampos-dev
Repo: igorcampos-dev/spring-integrations-examples PR: 40
File: spring-kafka-example/src/main/java/com/io/example/consumer/KafkaConsumerService.java:3-3
Timestamp: 2025-07-27T19:51:52.736Z
Learning: In the spring-integrations-examples project, user igorcampos-dev uses SuppressWarnings("unused") annotations to suppress IntelliJ IDEA alerts, and these annotations should not be suggested for removal as they serve a specific purpose in their development workflow.
Applied to files:
spring-caffeine-example/.dockerignorespring-caffeine-example/.gitignore
📚 Learning: 2025-07-27T19:57:31.204Z
Learnt from: igorcampos-dev
Repo: igorcampos-dev/spring-integrations-examples PR: 40
File: spring-kafka-example/src/main/java/com/io/example/consumer/KafkaConsumerServiceImpl.java:18-22
Timestamp: 2025-07-27T19:57:31.204Z
Learning: In the spring-integrations-examples project, user igorcampos-dev prefers to keep simple example implementations minimal without additional error handling complexity, as the examples are for demonstration purposes rather than production use.
Applied to files:
README.mdspring-caffeine-example/README.mdspring-caffeine-example/pom.xmlpom.xmlspring-caffeine-example/src/main/java/com/io/example/SpringCaffeineExampleApplication.java
🧬 Code graph analysis (4)
spring-caffeine-example/src/main/java/com/io/example/external/dto/ExternalApiResponseDto.java (2)
spring-wolf-example/src/main/java/com/io/example/dto/KafkaDto.java (1)
KafkaDto(3-3)spring-kafka-example/src/main/java/com/io/example/controller/dto/response/SimpleTopicDtoResponse.java (1)
SimpleTopicDtoResponse(3-3)
spring-caffeine-example/src/main/java/com/io/example/dto/CaffeineResponseDto.java (2)
spring-wolf-example/src/main/java/com/io/example/dto/KafkaDto.java (1)
KafkaDto(3-3)spring-kafka-example/src/main/java/com/io/example/controller/dto/response/SimpleTopicDtoResponse.java (1)
SimpleTopicDtoResponse(3-3)
spring-caffeine-example/src/main/java/com/io/example/repository/CaffeineDescriptionRepository.java (2)
spring-batch-db-examples/src/main/java/com/io/example/repository/query/TestEntityQuery.java (1)
RequiredArgsConstructor(6-27)spring-batch-db-examples/src/main/java/com/io/example/repository/TestEntityRepository.java (1)
Repository(7-9)
spring-caffeine-example/src/main/java/com/io/example/external/controller/ExternalApiController.java (1)
spring-caffeine-example/src/main/java/com/io/example/controller/CaffeineController.java (1)
RestController(12-25)
🪛 Checkov (3.2.334)
spring-caffeine-example/Dockerfile
[low] 1-49: Ensure that HEALTHCHECK instructions have been added to container images
(CKV_DOCKER_2)
🪛 Hadolint (2.14.0)
spring-caffeine-example/Dockerfile
[warning] 16-16: Quote this to prevent word splitting.
(SC2046)
[warning] 42-42: COPY to a relative destination without WORKDIR set.
(DL3045)
[warning] 43-43: COPY to a relative destination without WORKDIR set.
(DL3045)
[warning] 44-44: COPY to a relative destination without WORKDIR set.
(DL3045)
[warning] 45-45: COPY to a relative destination without WORKDIR set.
(DL3045)
🪛 LanguageTool
spring-caffeine-example/README.md
[uncategorized] ~28-~28: The official name of this software platform is spelled with a capital “H”.
Context: ...---------------------------| | Caffeine Github | https://github.com/ben-manes...
(GITHUB)
🪛 markdownlint-cli2 (0.18.1)
README.md
30-30: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
spring-caffeine-example/README.md
19-19: Bare URL used
(MD034, no-bare-urls)
20-20: Bare URL used
(MD034, no-bare-urls)
28-28: Bare URL used
(MD034, no-bare-urls)
29-29: Bare URL used
(MD034, no-bare-urls)
🪛 OSV Scanner (2.3.0)
spring-caffeine-example/pom.xml
[HIGH] 1-1: commons-fileupload:commons-fileupload 1.5: Apache Commons FileUpload, Apache Commons FileUpload: FileUpload DoS via part headers
🪛 YAMLlint (1.37.1)
spring-caffeine-example/src/main/resources/application.yaml
[warning] 29-29: too few spaces before comment: expected 2
(comments)
[error] 32-32: too many blank lines (1 > 0)
(empty-lines)
spring-caffeine-example/.github/workflows/maven.yml
[warning] 3-3: truthy value should be one of [false, true]
(truthy)
[error] 14-14: too many spaces inside brackets
(brackets)
[error] 14-14: too many spaces inside brackets
(brackets)
[error] 15-15: too many spaces inside brackets
(brackets)
[error] 15-15: too many spaces inside brackets
(brackets)
.github/workflows/spring-caffeine-example.yml
[warning] 3-3: truthy value should be one of [false, true]
(truthy)
[error] 23-23: too many spaces inside brackets
(brackets)
[error] 23-23: too many spaces inside brackets
(brackets)
[error] 24-24: too many spaces inside brackets
(brackets)
[error] 24-24: too many spaces inside brackets
(brackets)
spring-caffeine-example/src/main/resources/application-prd.yaml
[error] 32-32: too many blank lines (1 > 0)
(empty-lines)
🔇 Additional comments (27)
.github/labeler.yml (1)
29-31: LGTM!The new
spring-caffeine-examplelabeler entry follows the established pattern, uses the correct glob syntax, and is properly positioned in alphabetical order.spring-caffeine-example/.gitattributes (1)
1-2: LGTM!The line-ending configuration is correct for Maven wrapper scripts. Unix shell scripts require LF endings, while Windows batch files require CRLF.
README.md (1)
30-30: LGTM!The new table entry follows the consistent format of existing entries and provides appropriate high-level documentation for the Spring Boot + Caffeine integration example.
pom.xml (1)
26-26: LGTM!The new module is correctly added to the Maven multi-module build configuration.
spring-caffeine-example/src/main/resources/application-prd.yaml (1)
1-31: LGTM!The production configuration properly externalizes all environment-specific values through environment variables, following 12-factor app principles.
spring-caffeine-example/src/main/java/com/io/example/SpringCaffeineExampleApplication.java (1)
1-15: LGTM!Clean and minimal Spring Boot application entry point with proper Feign client support enabled.
spring-caffeine-example/.github/workflows/maven.yml (1)
1-30: LGTM!The CI workflow is correctly configured to build the project using Java 21 and the Maven wrapper. The workflow structure, steps, and matrix configuration are all appropriate.
spring-caffeine-example/src/main/resources/sql/init.sql (1)
1-7: LGTM!The SQL initialization script provides a clean, minimal schema and seed data appropriate for this demonstration project. The table structure is well-suited for H2 database integration.
spring-caffeine-example/README.md (1)
1-29: LGTM! Documentation aligns with project preferences.The README is concise and high-level, effectively documenting the purpose and usage of the Caffeine caching example without over-explaining implementation details.
spring-caffeine-example/src/main/java/com/io/example/service/CaffeineService.java (1)
1-7: LGTM!The interface is clean and follows standard Spring service patterns with a clear, single-responsibility method signature.
spring-caffeine-example/compose.yaml (1)
3-4: LGTM!The hard-coded container name is appropriate for CI pipeline validation purposes.
spring-caffeine-example/src/main/resources/application.yaml (2)
1-24: LGTM!The Spring Boot, datasource, H2, and SQL initialization configurations are properly structured and follow best practices.
25-26: Verify the URL format includes the protocol.Similar to the Docker compose configuration, the
caffeine-version-urlis missing the protocol (http:// or https://). This should be consistent with how the Feign client expects URL configuration.spring-caffeine-example/src/main/java/com/io/example/dto/CaffeineResponseDto.java (1)
1-3: LGTM!The record is clean and follows established patterns in the codebase for DTOs.
spring-caffeine-example/.dockerignore (1)
1-62: LGTM!The .dockerignore file comprehensively excludes appropriate artifacts, helping to minimize the Docker build context.
spring-caffeine-example/src/main/java/com/io/example/repository/CaffeineDescriptionRepository.java (1)
1-24: LGTM!The repository uses the modern
JdbcClientAPI appropriately with clean text block SQL. The hard-coded ID parameter is acceptable for a demonstration example.spring-caffeine-example/src/main/java/com/io/example/external/dto/ExternalApiResponseDto.java (1)
1-3: LGTM!The record follows the established pattern for DTOs in the project.
spring-caffeine-example/.gitignore (1)
1-32: LGTM!The
.gitignorefile comprehensively covers Maven build artifacts and all major IDE configurations. The negation patterns for source directories are appropriate.spring-caffeine-example/src/main/java/com/io/example/service/CaffeineServiceImpl.java (2)
21-24: LGTM!The implementation correctly delegates to cached helper methods and constructs the response DTO. The caching pattern with side-effectful logging on first fetch clearly demonstrates cache behavior.
26-40: LGTM!Both
getVersion()andgetDescription()correctly implement the cache-aside pattern using Caffeine'sget()method with a loading function. The logging statements effectively demonstrate when cache misses occur.spring-caffeine-example/Dockerfile (3)
1-11: LGTM!The dependency stage efficiently uses build caching and bind mounts to fetch dependencies offline. The Maven wrapper setup is correct.
21-26: LGTM!The extraction stage correctly uses Spring Boot's layertools to extract layers, which optimizes Docker image caching and reduces layer sizes.
31-40: LGTM!The non-root user setup follows security best practices, with configurable UID via build argument and proper user restrictions (no password, no login shell, no home directory).
spring-caffeine-example/pom.xml (1)
28-80: No action needed. This project uses Spring Boot 4.0.0, which does not includecommons-fileuploadas a transitive dependency. Spring Framework 6 (the foundation of Boot 4.0.0) removed theCommonsMultipartResolverintegration entirely, andcommons-fileuploadis not pulled in by any of the declared starters (spring-boot-starter-webmvc,spring-boot-starter-jdbc, orspring-boot-h2console). While GHSA-vv7r-c36w-3prj is a legitimate high-severity vulnerability incommons-fileupload < 1.6.0, it does not affect this codebase since the library is neither explicitly declared nor transitively included.Likely an incorrect or invalid review comment.
.github/workflows/spring-caffeine-example.yml (1)
39-68: Health check job structure looks good.The approach of extracting service names dynamically and using compose-action with build flags is appropriate. The fixed 10-second sleep is acceptable for this example project, though for production CI you might consider polling-based readiness checks.
spring-caffeine-example/mvnw.cmd (1)
1-189: Standard Maven Wrapper script.This is the official Apache Maven Wrapper startup batch script, version 3.3.4. The script correctly handles distribution download, SHA-256 validation, credential cleanup, and supports both standard Maven and mvnd variants. No issues identified.
spring-caffeine-example/mvnw (1)
1-295: Standard Maven Wrapper script.This is the official Apache Maven Wrapper shell script (version 3.3.4) with comprehensive cross-platform support including Cygwin/MinGW compatibility, multiple download methods (wget/curl/Java fallback), SHA-256 validation, and proper credential sanitization before exec. No issues identified.
| distribution: [ 'temurin' ] | ||
| java: [ '21' ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Fix bracket spacing for YAML lint compliance.
YAMLlint reports extra spaces inside brackets on these lines.
Apply this diff:
- distribution: [ 'temurin' ]
- java: [ '21' ]
+ distribution: ['temurin']
+ java: ['21']📝 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.
| distribution: [ 'temurin' ] | |
| java: [ '21' ] | |
| distribution: ['temurin'] | |
| java: ['21'] |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 23-23: too many spaces inside brackets
(brackets)
[error] 23-23: too many spaces inside brackets
(brackets)
[error] 24-24: too many spaces inside brackets
(brackets)
[error] 24-24: too many spaces inside brackets
(brackets)
🤖 Prompt for AI Agents
.github/workflows/spring-caffeine-example.yml lines 23-24: the array brackets
contain extra spaces which fails YAML lint; remove the spaces inside the
brackets so the arrays use compact form (e.g. change "distribution: [ 'temurin'
]" to "distribution: ['temurin']" and "java: [ '21' ]" to "java: ['21']").
| H2_CONSOLE_PATH: /h2-console | ||
| H2_INIT_MODE: always | ||
| H2_INIT_SCHEMA: classpath:sql/init.sql | ||
| CAFFEINE_VERSION_URL: localhost:7079/external |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check Feign client configuration and URL usage
# Find Feign client configurations
echo "=== Searching for FeignClient declarations ==="
rg -n "FeignClient\|@FeignClient" --type java -A 3
echo ""
echo "=== Searching for caffeine-version-url property usage ==="
rg -n "caffeine-version-url\|CAFFEINE_VERSION_URL" --type yaml --type java --type properties
echo ""
echo "=== Checking compose.yaml for all environment variables ==="
cat spring-caffeine-example/compose.yamlRepository: igorcampos-dev/spring-integrations-examples
Length of output: 936
🏁 Script executed:
#!/bin/bash
# Find files in spring-caffeine-example module
echo "=== Files in spring-caffeine-example ==="
find spring-caffeine-example -type f -name "*.java" -o -name "*.properties" -o -name "*.yml" | head -20
echo ""
echo "=== Search for Feign dependency ==="
rg -l "feign\|Feign" spring-caffeine-example
echo ""
echo "=== Search for property usage with broader patterns ==="
rg -n "CAFFEINE_VERSION\|caffeine" spring-caffeine-example --type java -i
echo ""
echo "=== Check if this is a client calling an external service ==="
rg -n "@RestClient\|@FeignClient\|RestTemplate\|WebClient" spring-caffeine-example --type java -iRepository: igorcampos-dev/spring-integrations-examples
Length of output: 1372
🏁 Script executed:
#!/bin/bash
echo "=== CaffeineVersionClient.java ==="
cat spring-caffeine-example/src/main/java/com/io/example/client/CaffeineVersionClient.java
echo ""
echo "=== CaffeineProperties.java ==="
cat spring-caffeine-example/src/main/java/com/io/example/properties/CaffeineProperties.java
echo ""
echo "=== Check application properties files ==="
find spring-caffeine-example/src -name "application*.properties" -o -name "application*.yml" | xargs catRepository: igorcampos-dev/spring-integrations-examples
Length of output: 1014
🏁 Script executed:
#!/bin/bash
echo "=== Search for external.caffeine-version-url references ==="
rg -n "external.caffeine-version-url\|external\.caffeine" spring-caffeine-example
echo ""
echo "=== Check for all application config files ==="
find spring-caffeine-example -type f \( -name "*.properties" -o -name "*.yml" -o -name "*.yaml" \) | grep -v ".mvn\|wrapper\|workflows"
echo ""
echo "=== Check Dockerfile for property configuration ==="
cat spring-caffeine-example/Dockerfile
echo ""
echo "=== Check pom.xml for spring-cloud-openfeign ==="
grep -A 5 -B 5 "feign\|openfeign" spring-caffeine-example/pom.xmlRepository: igorcampos-dev/spring-integrations-examples
Length of output: 2574
🏁 Script executed:
#!/bin/bash
echo "=== application.yaml ==="
cat spring-caffeine-example/src/main/resources/application.yaml
echo ""
echo "=== application-prd.yaml ==="
cat spring-caffeine-example/src/main/resources/application-prd.yamlRepository: igorcampos-dev/spring-integrations-examples
Length of output: 1282
The CAFFEINE_VERSION_URL is missing the protocol (http:// or https://), which will cause Feign client connection failures.
Both environment configurations are affected:
- Local:
localhost:8080/externalinapplication.yaml - Production:
localhost:7079/externalincompose.yaml(mapped viaapplication-prd.yaml)
Update the URL to include the protocol: http://localhost:7079/external
🤖 Prompt for AI Agents
In spring-caffeine-example/compose.yaml around line 18, the CAFFEINE_VERSION_URL
value lacks an HTTP scheme which will break Feign client calls; update the
environment value to include the protocol (e.g. change to
"http://localhost:7079/external") so the service has a fully qualified URL, and
ensure any other environment configs (local/production) are likewise updated to
include "http://" or "https://" as appropriate.
| RUN --mount=type=bind,source=pom.xml,target=pom.xml \ | ||
| --mount=type=cache,target=/root/.m2 \ | ||
| ./mvnw package -DskipTests && \ | ||
| mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix shell quoting to prevent word splitting.
Line 19 uses unquoted command substitutions that could cause word splitting issues if the artifact ID or version contains spaces or special characters.
Apply this diff:
./mvnw package -DskipTests && \
- mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar
+ mv "target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar" target/app.jar📝 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.
| RUN --mount=type=bind,source=pom.xml,target=pom.xml \ | |
| --mount=type=cache,target=/root/.m2 \ | |
| ./mvnw package -DskipTests && \ | |
| mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar | |
| RUN --mount=type=bind,source=pom.xml,target=pom.xml \ | |
| --mount=type=cache,target=/root/.m2 \ | |
| ./mvnw package -DskipTests && \ | |
| mv "target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar" target/app.jar |
🧰 Tools
🪛 Hadolint (2.14.0)
[warning] 16-16: Quote this to prevent word splitting.
(SC2046)
🤖 Prompt for AI Agents
In spring-caffeine-example/Dockerfile around lines 16 to 19, the mv command uses
unquoted command substitutions which can lead to word splitting if artifactId or
version contain spaces or special characters; update the Dockerfile to capture
the two evaluated values into variables or directly quote the command
substitution expansions so the resulting filename is treated as a single
argument (e.g., wrap each $(...) expansion in double quotes or assign them to
variables and then reference the variables quoted) and ensure the mv source and
destination arguments are properly quoted to prevent splitting and unexpected
behavior.
| FROM eclipse-temurin:21-jre-jammy AS final | ||
|
|
||
|
|
||
| ARG UID=10001 | ||
| RUN adduser \ | ||
| --disabled-password \ | ||
| --gecos "" \ | ||
| --home "/nonexistent" \ | ||
| --shell "/sbin/nologin" \ | ||
| --no-create-home \ | ||
| --uid "${UID}" \ | ||
| appuser | ||
| USER appuser | ||
|
|
||
| COPY --from=extract build/target/extracted/dependencies/ ./ | ||
| COPY --from=extract build/target/extracted/spring-boot-loader/ ./ | ||
| COPY --from=extract build/target/extracted/snapshot-dependencies/ ./ | ||
| COPY --from=extract build/target/extracted/application/ ./ | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Add WORKDIR and HEALTHCHECK for production readiness.
The final stage has two issues:
- Missing
WORKDIRbeforeCOPYcommands (lines 42-45), which means files are copied to the root directory - Missing
HEALTHCHECKinstruction for container health monitoring
Apply this diff:
FROM eclipse-temurin:21-jre-jammy AS final
+WORKDIR /app
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser
COPY --from=extract build/target/extracted/dependencies/ ./
COPY --from=extract build/target/extracted/spring-boot-loader/ ./
COPY --from=extract build/target/extracted/snapshot-dependencies/ ./
COPY --from=extract build/target/extracted/application/ ./
EXPOSE 7079
+HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
+ CMD java -cp . org.springframework.boot.actuate.health.HealthEndpoint || exit 1
+
ENTRYPOINT [ "java", "org.springframework.boot.loader.launch.JarLauncher" ]Note: For the HEALTHCHECK to work properly, you'll need Spring Boot Actuator. If not using Actuator, consider a simple HTTP health check using curl or wget.
Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Hadolint (2.14.0)
[warning] 42-42: COPY to a relative destination without WORKDIR set.
(DL3045)
[warning] 43-43: COPY to a relative destination without WORKDIR set.
(DL3045)
[warning] 44-44: COPY to a relative destination without WORKDIR set.
(DL3045)
[warning] 45-45: COPY to a relative destination without WORKDIR set.
(DL3045)
🤖 Prompt for AI Agents
In spring-caffeine-example/Dockerfile around lines 28 to 46, the final stage is
missing a WORKDIR before the COPYs and lacks a HEALTHCHECK; add a WORKDIR (e.g.
/app) before the COPY lines and ensure the directory exists/has correct
ownership (create and chown if necessary or set before switching to the
unprivileged USER), then add a HEALTHCHECK that probes your app (preferably
Spring Boot Actuator /actuator/health on the container port) with sensible
interval/timeout/retries or a simple curl/wget HTTP check if Actuator is not
available; keep the USER placement and permissions consistent so the health
probe can run and files are placed under the intended app directory.
| @FeignClient( | ||
| name = "caffeineVersionClient", | ||
| url = "${external.caffeine-version-url}" | ||
| ) | ||
| public interface CaffeineVersionClient { | ||
|
|
||
| @GetMapping("/v1/caffeine-version") | ||
| ExternalApiResponseDto getVersionCaffeine(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, find and check the pom.xml or gradle build files to see actual versions
find . -name "pom.xml" -o -name "build.gradle" -o -name "build.gradle.kts" | head -20Repository: igorcampos-dev/spring-integrations-examples
Length of output: 615
🏁 Script executed:
# Check the parent pom.xml for version properties
cat ./pom.xml | grep -A 50 "<properties>" | head -60Repository: igorcampos-dev/spring-integrations-examples
Length of output: 69
🏁 Script executed:
# Read the parent pom.xml to see version definitions
wc -l ./pom.xmlRepository: igorcampos-dev/spring-integrations-examples
Length of output: 99
🏁 Script executed:
# Read parent pom.xml
cat -n ./pom.xmlRepository: igorcampos-dev/spring-integrations-examples
Length of output: 1378
🏁 Script executed:
# Read spring-caffeine-example pom.xml
wc -l ./spring-caffeine-example/pom.xml && echo "---" && cat -n ./spring-caffeine-example/pom.xmlRepository: igorcampos-dev/spring-integrations-examples
Length of output: 3617
🌐 Web query:
Spring Boot 4.0.0 release date
💡 Result:
Spring Boot 4.0.0 was released on November 20, 2025. [1][2]
Sources:
[1] Spring blog — "Spring Boot 4.0.0 available now."
[2] endoflife.date — Spring Boot release listing.
🌐 Web query:
Spring Cloud OpenFeign 5.0.0 release date
💡 Result:
I couldn't find a GA release for Spring Cloud OpenFeign 5.0.0. The latest published release is 5.0.0-M4 (milestone) on 17 Oct 2025. [1][2]
Sources:
- spring-cloud-openfeign releases (GitHub) — 5.0.0-M4 (17 Oct 2025). [1]
- Spring blog / Spring Cloud 2025.1.0 announcement (mentions OpenFeign updates). [2]
Feign client implementation is correct, but the project has a critical dependency version issue.
The interface follows standard Spring Cloud OpenFeign patterns with externalized URL configuration. However, there is a build configuration problem: spring.cloud.openfeign.version is set to 5.0.0 in the pom.xml, but Spring Cloud OpenFeign 5.0.0 GA has not been released. Only 5.0.0-M4 (milestone release from October 17, 2025) is currently available. This will cause dependency resolution to fail.
Update the version to 5.0.0-M4 or use the latest stable release (e.g., 4.1.0). For production applications, also consider adding a fallback or fallbackFactory for resilience.
🤖 Prompt for AI Agents
In
spring-caffeine-example/src/main/java/com/io/example/client/CaffeineVersionClient.java
around lines 7 to 14: the Feign client is fine but your build will fail because
pom.xml pins spring.cloud.openfeign.version to a non-existent 5.0.0 GA; update
the spring.cloud.openfeign.version property in pom.xml to a valid release (e.g.,
5.0.0-M4 or the latest stable 4.1.0), run mvn -U verify to refresh dependencies,
and for production consider adding a fallback or fallbackFactory to this
@FeignClient declaration for resilience.
| @Data | ||
| @Component | ||
| @ConfigurationProperties(prefix = "caffeine") | ||
| public class CaffeineProperties { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider using @EnableConfigurationProperties instead of @component.
Using @Component with @ConfigurationProperties works but is not the recommended pattern. The preferred approach is to remove @Component and enable this configuration class using @EnableConfigurationProperties(CaffeineProperties.class) in a configuration class (e.g., CacheConfig).
Apply this diff to CaffeineProperties.java:
@Data
-@Component
@ConfigurationProperties(prefix = "caffeine")
public class CaffeineProperties {Then update CacheConfig.java to enable the properties:
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
@Configuration
+@EnableConfigurationProperties(CaffeineProperties.class)
@RequiredArgsConstructor
public class CacheConfig {Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
spring-caffeine-example/src/main/java/com/io/example/properties/CaffeineProperties.java
around lines 7-10, remove the @Component annotation and keep
@ConfigurationProperties(prefix = "caffeine") (so the class is a plain
configuration properties bean), then update your configuration class (e.g.,
CacheConfig.java) to include @Configuration and
@EnableConfigurationProperties(CaffeineProperties.class) so Spring will bind and
register the properties bean via the configuration class instead of component
scanning.
| private long expireAfterWrite; | ||
| private int initialCapacity; | ||
| private long maximumSize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider adding validation constraints.
The configuration properties lack validation, which could lead to runtime issues if invalid values are provided (e.g., negative numbers, zero capacity).
Consider adding validation annotations:
+import jakarta.validation.constraints.Min;
+
public class CaffeineProperties {
+ @Min(1)
private long expireAfterWrite;
+ @Min(1)
private int initialCapacity;
+ @Min(1)
private long maximumSize;
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
spring-caffeine-example/src/main/java/com/io/example/properties/CaffeineProperties.java
around lines 11-13, the three numeric configuration fields currently have no
validation; add bean-validation to prevent invalid values at startup: annotate
the class with @org.springframework.validation.annotation.Validated (or ensure
@Validated is applied where the @ConfigurationProperties bean is registered) and
add appropriate Jakarta validation annotations on fields (e.g.,
@jakarta.validation.constraints.PositiveOrZero on expireAfterWrite,
@jakarta.validation.constraints.Min(1) on initialCapacity to forbid zero, and
@jakarta.validation.constraints.Positive on maximumSize or @PositiveOrZero if
zero is allowed) and import the constraint annotations; keep existing
getters/setters and ensure the configuration binding will fail fast on invalid
values.
| @RequiredArgsConstructor | ||
| public class CaffeineServiceImpl implements CaffeineService{ | ||
|
|
||
| private final Cache<@NonNull String, String> caffeineCache; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Reconsider the @nonnull annotation on the generic type parameter.
Similar to the issue in CacheConfig, the @NonNull annotation on Cache<@NonNull String, String> is redundant since Caffeine rejects null keys by default.
-private final Cache<@NonNull String, String> caffeineCache;
+private final Cache<String, String> caffeineCache;📝 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.
| private final Cache<@NonNull String, String> caffeineCache; | |
| private final Cache<String, String> caffeineCache; |
🤖 Prompt for AI Agents
In
spring-caffeine-example/src/main/java/com/io/example/service/CaffeineServiceImpl.java
around line 17, remove the redundant @NonNull annotation on the generic key type
(Cache<@NonNull String, String>) because Caffeine already disallows null keys;
change the field declaration to use a plain Cache<String, String> instead and
update any imports/usages accordingly to avoid unused annotation imports or
compiler warnings.
| expireAfterWrite: ${CAFFEINE_EXPIRES} | ||
| initialCapacity: ${CAFFEINE_CAPACITY} | ||
| maximumSize: ${CAFFEINE_MAXIMUM_SIZE} | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove trailing blank line.
YAMLlint flags an extra blank line at the end of the file.
Apply this diff:
maximumSize: ${CAFFEINE_MAXIMUM_SIZE}
-📝 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.
| maximumSize: ${CAFFEINE_MAXIMUM_SIZE} |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 32-32: too many blank lines (1 > 0)
(empty-lines)
🤖 Prompt for AI Agents
In spring-caffeine-example/src/main/resources/application-prd.yaml around line
32, the file contains an extra trailing blank line flagged by YAMLlint; remove
the empty final line so the file ends immediately after the last content line
(ensure exactly one newline at EOF if your editor requires it) and save the
file.
| caffeine: | ||
| expireAfterWrite: 60 # seconds | ||
| initialCapacity: 200 | ||
| maximumSize: 500 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Optional: Clean up YAML formatting.
Minor formatting issues flagged by YAMLlint:
- Line 29: Comment should have 2 spaces before it (currently has 1)
- Line 32: Extra blank line at end of file
Apply this diff:
caffeine:
- expireAfterWrite: 60 # seconds
+ expireAfterWrite: 60 # seconds
initialCapacity: 200
maximumSize: 500
-📝 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.
| caffeine: | |
| expireAfterWrite: 60 # seconds | |
| initialCapacity: 200 | |
| maximumSize: 500 | |
| caffeine: | |
| expireAfterWrite: 60 # seconds | |
| initialCapacity: 200 | |
| maximumSize: 500 |
🧰 Tools
🪛 YAMLlint (1.37.1)
[warning] 29-29: too few spaces before comment: expected 2
(comments)
[error] 32-32: too many blank lines (1 > 0)
(empty-lines)
🤖 Prompt for AI Agents
In spring-caffeine-example/src/main/resources/application.yaml around lines 28
to 32, the YAML has minor formatting issues: the inline comment on line 29 needs
one additional space before the "#" (make it two spaces before the comment text)
and the trailing extra blank line at the end of the file (line 32) should be
removed; update the file to add the extra space before the comment and delete
the final blank line so the file ends immediately after the last configuration
entry.
…h caching implementation and Docker support
Summary by CodeRabbit
Release Notes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.