feature: upgrade to Spring Boot 3.2.5 / Java 17#746
feature: upgrade to Spring Boot 3.2.5 / Java 17#746devin-ai-integration[bot] wants to merge 1 commit into
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| @Bean | ||
| public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
| http.csrf(csrf -> csrf.disable()) | ||
| .cors(cors -> {}) |
There was a problem hiding this comment.
📝 Info: SecurityFilterChain migration uses empty CORS lambda that relies on bean discovery
The CORS configuration at src/main/java/io/spring/api/security/WebSecurityConfig.java:38 uses .cors(cors -> {}) which is an empty customizer. In Spring Security 6, this is equivalent to Customizer.withDefaults() and will discover the CorsConfigurationSource bean defined at line 69. This works correctly, but is subtly different from the old .cors().and() pattern. If the corsConfigurationSource() bean were ever removed or renamed, CORS would silently fall back to defaults instead of failing. Worth noting but not a bug.
Was this helpful? React with 👍 or 👎 to provide feedback.
| .path(handlerParameters.getPath()) | ||
| .extensions(errorsToMap(errors)) | ||
| .build(); | ||
| return DataFetcherExceptionHandlerResult.newResult().error(graphqlError).build(); | ||
| return CompletableFuture.completedFuture( | ||
| DataFetcherExceptionHandlerResult.newResult().error(graphqlError).build()); | ||
| } else { | ||
| return defaultHandler.onException(handlerParameters); | ||
| return defaultHandler.handleException(handlerParameters); |
There was a problem hiding this comment.
📝 Info: GraphQL exception handler correctly migrated from synchronous to async API
The onException → handleException migration at src/main/java/io/spring/graphql/exception/GraphQLCustomizeExceptionHandler.java:32 changes the return type from DataFetcherExceptionHandlerResult to CompletableFuture<DataFetcherExceptionHandlerResult>. The implementation wraps results with CompletableFuture.completedFuture() (lines 41-42, 66-67), which is correct for synchronous exception handling in the new async API. The fallback at line 69 correctly delegates to defaultHandler.handleException() which already returns the right type.
(Refers to lines 32-69)
Was this helpful? React with 👍 or 👎 to provide feedback.
| .authorizeHttpRequests( | ||
| authorize -> | ||
| authorize | ||
| .requestMatchers(HttpMethod.OPTIONS) | ||
| .permitAll() | ||
| .requestMatchers("/graphiql") | ||
| .permitAll() | ||
| .requestMatchers("/graphql") | ||
| .permitAll() | ||
| .requestMatchers(HttpMethod.GET, "/articles/feed") | ||
| .authenticated() | ||
| .requestMatchers(HttpMethod.POST, "/users", "/users/login") | ||
| .permitAll() | ||
| .requestMatchers(HttpMethod.GET, "/articles/**", "/profiles/**", "/tags") | ||
| .permitAll() | ||
| .anyRequest() | ||
| .authenticated()); |
There was a problem hiding this comment.
📝 Info: Spring Security requestMatchers order correctly preserves feed authentication
The security config at src/main/java/io/spring/api/security/WebSecurityConfig.java:54-58 correctly places .requestMatchers(HttpMethod.GET, "/articles/feed").authenticated() BEFORE .requestMatchers(HttpMethod.GET, "/articles/**", ...).permitAll(). Spring Security evaluates matchers in order, and first match wins. This preserves the original behavior where GET /articles/feed requires authentication while other article GET endpoints are public. The antMatchers → requestMatchers migration is semantically equivalent for these patterns.
Was this helpful? React with 👍 or 👎 to provide feedback.
…ecurity 6, DGS/MyBatis bumps) Co-Authored-By: andrew.zhao <andrewzhao150@gmail.com>
f130399 to
cbc822f
Compare
There was a problem hiding this comment.
🚩 Pre-existing bug: updatedAt uses createdAt timestamp in comment GraphQL result
In buildCommentResult at src/main/java/io/spring/graphql/CommentDatafetcher.java:115, the updatedAt field is populated with comment.getCreatedAt() instead of comment.getUpdatedAt(). This means comment updates are never reflected in the GraphQL updatedAt field. This is a pre-existing bug not introduced by this PR, but since the file was touched for the PageInfo migration, it's worth noting.
(Refers to line 115)
Was this helpful? React with 👍 or 👎 to provide feedback.
| id 'org.springframework.boot' version '3.2.5' | ||
| id 'io.spring.dependency-management' version '1.1.4' |
There was a problem hiding this comment.
📝 Info: Flyway + SQLite compatibility depends on Spring Boot 3.2.x using Flyway 9.x
The project uses SQLite (src/main/resources/application.properties:1) with org.flywaydb:flyway-core (version managed by Spring Boot). Spring Boot 3.2.5 bundles Flyway 9.22.x, which still includes SQLite support in the core module. However, starting with Spring Boot 3.3+ (which uses Flyway 10+), SQLite support was moved to a separate flyway-database-sqlite module. If this project upgrades Spring Boot further, it will need to add that dependency explicitly or Flyway will fail to recognize the SQLite database.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Modernizes the backend from Spring Boot 2.6.3 / Java 11 to Spring Boot 3.2.5 / Java 17.
./gradlew clean test spotlessJavaCheckpasses: 68 tests, 0 failures.Build config (
build.gradle, wrapper)2.6.3→3.2.5;io.spring.dependency-management1.0.11.RELEASE→1.1.4.sourceCompatibility/targetCompatibility11→17.7.4→8.7.5.0.6→6.0.3; spotless6.2.1→6.25.0.graphql-dgs-platform-dependencies:8.1.1) instead of a hard-coded starter version.2.2.2→3.0.3; jjwt0.11.2→0.11.5; joda-time & sqlite-jdbc bumped; rest-assured4.5.1→5.4.0.targetscoped tosrc/**/*.java(was whole rootDir) to avoid a Gradle 8 implicit-dependency error betweenspotlessJavaandcompileJava.javax → jakarta
Repo-wide migration of
javax.validation.*andjavax.servlet.*→jakarta.*(validation params/constraints/validators, controllers,JwtTokenFilter, exception handlers).javax.crypto.*inDefaultJwtServiceis JDK API and left untouched.Spring Security 6 rewrite (
WebSecurityConfig)Removed
WebSecurityConfigurerAdapter; replacedconfigure(HttpSecurity)with aSecurityFilterChainbean using the lambda DSL.authorizeRequests()/antMatchers()→authorizeHttpRequests()/requestMatchers(). Same rules preserved (STATELESS, CORS, 401 entry point, JWT filter beforeUsernamePasswordAuthenticationFilter). Matcher order preserves/articles/feed= authenticated ahead of the/articles/**permitAll.Breakages fixed after bumps
GraphQLCustomizeExceptionHandlerimplementedDataFetcherExceptionHandler.onException(removed). Rewrote tohandleException(...)returningCompletableFuture<DataFetcherExceptionHandlerResult>, delegating todefaultHandler.handleException(...).PageInfotographql.relay.PageInfo. Datafetchers builtgraphql.relay.DefaultPageInfo; switched to the generatedio.spring.graphql.types.PageInfobuilder:ResponseEntityExceptionHandler.handleMethodArgumentNotValidsignatureHttpStatus→HttpStatusCodeinCustomizeExceptionHandler.CI (
.github/workflows/gradle.yml)JDK
11→17, and bumped deprecated actions (checkout@v2→v4,setup-java@v2→v4,cache@v2→v4;cache@v2was auto-failing the build).Verification
./gradlew clean test spotlessJavaCheck→ BUILD SUCCESSFUL, 68 tests, 0 failures/errors/skipped.Link to Devin session: https://app.devin.ai/sessions/9ef7bf70da234daf99c712491aa28842
Requested by: @Azhao15
Devin Review