Skip to content

feature: upgrade to Spring Boot 3.2.5 / Java 17#746

Open
devin-ai-integration[bot] wants to merge 1 commit into
masterfrom
devin/1782935281-springboot3-java17
Open

feature: upgrade to Spring Boot 3.2.5 / Java 17#746
devin-ai-integration[bot] wants to merge 1 commit into
masterfrom
devin/1782935281-springboot3-java17

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jul 1, 2026

Copy link
Copy Markdown

Summary

Modernizes the backend from Spring Boot 2.6.3 / Java 11 to Spring Boot 3.2.5 / Java 17. ./gradlew clean test spotlessJavaCheck passes: 68 tests, 0 failures.

Repo note: this was requested against ankehao-demo/spring-boot-realworld-example-app, but the integration has no write access there (push 403). It's opened against COG-GTM/... (same shared backend, where prior PRs land). Can be re-pointed if ankehao-demo access is granted.

Build config (build.gradle, wrapper)

  • Spring Boot plugin 2.6.33.2.5; io.spring.dependency-management 1.0.11.RELEASE1.1.4.
  • sourceCompatibility/targetCompatibility 1117.
  • Gradle wrapper 7.48.7.
  • DGS codegen plugin 5.0.66.0.3; spotless 6.2.16.25.0.
  • DGS runtime pinned via the DGS BOM (graphql-dgs-platform-dependencies:8.1.1) instead of a hard-coded starter version.
  • MyBatis starter (+test) 2.2.23.0.3; jjwt 0.11.20.11.5; joda-time & sqlite-jdbc bumped; rest-assured 4.5.15.4.0.
  • Spotless target scoped to src/**/*.java (was whole rootDir) to avoid a Gradle 8 implicit-dependency error between spotlessJava and compileJava.

javax → jakarta

Repo-wide migration of javax.validation.* and javax.servlet.*jakarta.* (validation params/constraints/validators, controllers, JwtTokenFilter, exception handlers). javax.crypto.* in DefaultJwtService is JDK API and left untouched.

Spring Security 6 rewrite (WebSecurityConfig)

Removed WebSecurityConfigurerAdapter; replaced configure(HttpSecurity) with a SecurityFilterChain bean using the lambda DSL. authorizeRequests()/antMatchers()authorizeHttpRequests()/requestMatchers(). Same rules preserved (STATELESS, CORS, 401 entry point, JWT filter before UsernamePasswordAuthenticationFilter). Matcher order preserves /articles/feed = authenticated ahead of the /articles/** permitAll.

Breakages fixed after bumps

  • DGS / graphql-java 21: GraphQLCustomizeExceptionHandler implemented DataFetcherExceptionHandler.onException (removed). Rewrote to handleException(...) returning CompletableFuture<DataFetcherExceptionHandlerResult>, delegating to defaultHandler.handleException(...).
  • DGS codegen 6: generated connection types no longer map the schema PageInfo to graphql.relay.PageInfo. Datafetchers built graphql.relay.DefaultPageInfo; switched to the generated io.spring.graphql.types.PageInfo builder:
    // before
    new DefaultPageInfo(startCursor, endCursor, hasPrev, hasNext)
    // after
    PageInfo.newBuilder().startCursor(...).endCursor(...).hasPreviousPage(...).hasNextPage(...).build()
  • Spring 6 MVC: ResponseEntityExceptionHandler.handleMethodArgumentNotValid signature HttpStatusHttpStatusCode in CustomizeExceptionHandler.

CI (.github/workflows/gradle.yml)

JDK 1117, and bumped deprecated actions (checkout@v2v4, setup-java@v2v4, cache@v2v4; cache@v2 was 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

Status Commit
⚪ Not started

Run Devin Review

Open in Devin Review (Staging)
Open in Devin Review

@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 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
Author

Choose a reason for hiding this comment

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

Devin Review found 10 potential issues.

Open in Devin Review

Comment thread frontend/src/pages/ArticleView.tsx Outdated
Comment thread frontend/src/pages/Home.tsx Outdated
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable())
.cors(cors -> {})

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

📝 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.

Open in Devin Review

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

Comment on lines 63 to +69
.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);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

📝 Info: GraphQL exception handler correctly migrated from synchronous to async API

The onExceptionhandleException 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)

Open in Devin Review

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

Comment thread frontend/src/pages/Profile.tsx Outdated
Comment thread frontend/src/pages/Settings.tsx Outdated
Comment thread frontend/src/hooks/useAuth.ts Outdated
Comment on lines +45 to +61
.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());

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

📝 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 antMatchersrequestMatchers migration is semantically equivalent for these patterns.

Open in Devin Review

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

Comment thread frontend/.env Outdated
Comment thread frontend/.env Outdated
…ecurity 6, DGS/MyBatis bumps)

Co-Authored-By: andrew.zhao <andrewzhao150@gmail.com>
@devin-ai-integration devin-ai-integration Bot force-pushed the devin/1782935281-springboot3-java17 branch from f130399 to cbc822f Compare July 1, 2026 19:59

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

Open in Devin Review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

🚩 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)

Open in Devin Review

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

Comment thread build.gradle
Comment on lines +2 to +3
id 'org.springframework.boot' version '3.2.5'
id 'io.spring.dependency-management' version '1.1.4'

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

📝 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.

Open in Devin Review

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

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.

0 participants