From 27c553afa378bd7b6bfe120c7756e1a858c8460d Mon Sep 17 00:00:00 2001 From: vitorhugo-dotnet Date: Mon, 14 Sep 2026 21:21:22 -0300 Subject: [PATCH 1/3] feat(ai): configure Gemini thinking options --- .env.example | 2 ++ src/main/resources/application.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.env.example b/.env.example index 2acf87c..8f75da8 100644 --- a/.env.example +++ b/.env.example @@ -34,6 +34,8 @@ APP_ASSISTANT_ENABLED=false APP_ASSISTANT_PROVIDER=none GEMINI_API_KEY= GEMINI_CHAT_MODEL=gemini-2.5-flash +GEMINI_THINKING_BUDGET=0 +GEMINI_THINKING_LEVEL= OPENAI_GPT_CLIENT_ID= OPENAI_GPT_CLIENT_SECRET= diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 69f0fd7..e7de5da 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -12,6 +12,8 @@ spring: chat: options: model: ${GEMINI_CHAT_MODEL:gemini-2.5-flash} + thinking-budget: ${GEMINI_THINKING_BUDGET:0} + thinking-level: ${GEMINI_THINKING_LEVEL:} mcp: server: enabled: true From 244c8cb2050849f96d8ab8457e98338485a6878e Mon Sep 17 00:00:00 2001 From: vitorhugo-dotnet Date: Sun, 27 Sep 2026 12:21:31 -0300 Subject: [PATCH 2/3] docs: add Spring Boot 4 migration design --- ...26-09-27-spring-boot-4-migration-design.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 docs/superpowers/specs/2026-09-27-spring-boot-4-migration-design.md diff --git a/docs/superpowers/specs/2026-09-27-spring-boot-4-migration-design.md b/docs/superpowers/specs/2026-09-27-spring-boot-4-migration-design.md new file mode 100644 index 0000000..c93cb65 --- /dev/null +++ b/docs/superpowers/specs/2026-09-27-spring-boot-4-migration-design.md @@ -0,0 +1,49 @@ +# Spring Boot 4.1 and Spring AI 2.0 Migration Design + +## Goal + +Migrate the backend from Spring Boot 3.5.0 to stable Spring Boot 4.1.x and Spring AI 2.0.x while retaining Java 21 and the behavior of existing application, security, assistant/MCP, API documentation, and observability features. + +## Scope + +- Upgrade Spring Boot to the stable 4.1.x release selected for implementation and Spring AI to the latest stable 2.0.x release. +- Use Boot 4-native starters and modules for MVC, OAuth2, AOP, Flyway, testing, and other dependencies where the project needs them. +- Move application Jackson integration to Jackson 3; keep Jackson 2 only where a third-party library requires it, without making its compatibility module the application default. +- Align Spring Security and authorization-server configuration with the Boot 4 / Security 7 generation, preserving OAuth2, OIDC, PKCE, registration, and token behavior. +- Adapt Spring AI assistant, Google GenAI configuration, tool calling, and MCP WebMVC server code to Spring AI 2 APIs and artifacts. +- Upgrade springdoc to a Boot 4-compatible 3.x release and Resilience4j to its Spring Boot 4 integration. +- Audit explicitly versioned direct dependencies and Maven plugins; remove versions already owned by the Boot or Spring AI BOMs and refresh other versions only when compatible. +- Audit application and test configuration, deployment configuration, and dependency documentation for changed properties or requirements. + +## Constraints + +- Keep Java 21. +- Do not use Spring Boot 4.2 milestones or release candidates. +- Do not retain `spring-boot-starter-classic` or Jackson 2 compatibility as the final application architecture. +- Preserve MariaDB, JPA, and Flyway; do not add AI provider credentials to CI requirements. +- Keep changes limited to compatibility and maintenance work required by this migration. + +## Approach + +Update dependency management and artifacts first, then migrate compile-time API changes in source, then audit configuration and deployment documentation. Keep the existing application architecture and public API. Resolve compatibility failures at the narrowest responsible boundary, and retain regression coverage around affected security, assistant/MCP, serialization, OpenAPI, and observability behavior. + +## Verification + +Verify Maven dependency resolution and compilation, then run focused tests for modified behavior and relevant existing security, assistant/MCP, serialization, and OpenAPI flows. Run the issue's full `./mvnw clean verify` and dependency-tree checks when the migration compiles. Review Java 21 compatibility, dependency convergence (especially Spring and Jackson generations), and normal application startup/configuration. + +## Current Code Areas Identified + +- `pom.xml` owns the Boot parent, Spring AI BOM, explicit library versions, starters, and Maven plugins. +- `src/main/resources/application.yml` and `src/test/resources/application-test.yml` carry AI, actuator, Resilience4j, and test-profile properties. +- Security configuration is centered in `config/SecurityConfig.java`, `config/AuthorizationServerConfig.java`, and adjacent `config/*OAuth*` classes. +- Assistant and MCP APIs are used in `service/assistant/*`, `config/AssistantToolCallingConfiguration.java`, and `mcp/*`. +- Jackson APIs appear in utility, DTO, service, configuration, and related test files; the exact migration set will be determined by compiler/dependency evidence. +- OpenAPI and observability are configured through `config/OpenApiConfig.java`, application properties, and existing integration tests. + +## Risks and Mitigations + +- Boot 4 modularization can break dependencies that relied on transitive modules. Declare only the Boot 4 modules required by the code and let the Boot BOM manage their versions. +- Jackson 3 package and exception changes may affect multiple serialized DTO and provider paths. Compile and exercise representative serialization and assistant/provider tests after migrating imports. +- Spring Security 7 and authorization-server API changes may affect protocol behavior. Preserve existing authorization-server configuration and use existing OAuth/OIDC/PKCE integration tests as regression checks. +- Spring AI 2 changes MCP transports and tool APIs. Validate both server startup/discovery and assistant tool calling without relying on paid external providers. +- Other explicitly pinned libraries may not yet support the target ecosystem. Keep compatible versions when required and document any justified override rather than forcing unrelated major upgrades. From 4023e14db0db0bbeba68e2ed3f1f141c922d370b Mon Sep 17 00:00:00 2001 From: vitorhugo-dotnet Date: Sun, 27 Sep 2026 13:30:03 -0300 Subject: [PATCH 3/3] chore: migrate to Spring Boot 4 and Spring AI 2 --- README.md | 4 +- .../2026-09-27-spring-boot-4-migration.md | 113 ++++++++++++++++++ pom.xml | 73 ++++++----- .../com/jobtracker/JobTrackerApplication.java | 10 +- .../AssistantToolCallingConfiguration.java | 6 +- .../config/AuthorizationServerConfig.java | 14 ++- .../jobtracker/config/UserDetailsConfig.java | 15 ++- .../dto/auth/PasskeyOptionsResponse.java | 2 +- .../dto/auth/PasskeyVerifyRequest.java | 2 +- .../gdrive/GoogleDriveBaseResumeRequest.java | 8 +- .../com/jobtracker/mcp/McpPromptsConfig.java | 6 +- .../jobtracker/mcp/audit/McpAuditAspect.java | 2 +- .../McpApplicationCreationRulesResource.java | 4 +- .../McpApplicationLifecycleRulesResource.java | 4 +- .../McpApplicationStatusesResource.java | 4 +- .../McpBaseInformationContentResource.java | 4 +- .../McpBaseResumeContentResource.java | 4 +- .../McpGeneratedResumeContentResource.java | 4 +- .../McpReadOnlySnapshotResources.java | 10 +- .../McpResumeWorkflowRulesResource.java | 4 +- .../mcp/tools/McpAnalyticsTools.java | 8 +- .../mcp/tools/McpApplicationTools.java | 8 +- .../mcp/tools/McpBaseInformationTools.java | 8 +- .../mcp/tools/McpGamificationTools.java | 8 +- .../mcp/tools/McpGoogleDriveTools.java | 8 +- .../service/PasskeyAuthService.java | 20 ++-- .../service/TokenEstimatorService.java | 2 +- .../service/export/ExportConfigCodec.java | 12 +- src/main/resources/application.yml | 2 +- .../JobTrackerApplicationTests.java | 4 +- .../e2e/ChatGptConnectorOAuthE2ETest.java | 4 +- .../integration/AbstractIntegrationTest.java | 2 +- .../integration/ApplicationControllerIT.java | 2 +- .../integration/AuthControllerIT.java | 2 +- .../integration/AuthRateLimiterIT.java | 2 +- .../jobtracker/integration/DcrDisabledIT.java | 2 +- .../DynamicClientRegistrationIT.java | 4 +- .../integration/ExportControllerIT.java | 2 +- .../integration/ExportRateLimitIT.java | 2 +- .../ExportScheduleControllerIT.java | 2 +- .../integration/ExportSchedulerIT.java | 2 +- .../integration/GamificationControllerIT.java | 2 +- .../integration/GitHubControllerIT.java | 2 +- .../integration/GoogleDriveControllerIT.java | 4 +- .../integration/GptOAuthFlowIT.java | 10 +- .../integration/OpenApiDocumentationIT.java | 4 +- .../PasskeyRegistrationOptionsIT.java | 2 +- .../integration/UserDeletionCascadeIT.java | 2 +- .../jobtracker/integration/mcp/McpAuthIT.java | 2 +- .../unit/ApplicationConfigTest.java | 2 +- .../unit/ApplicationPatchRequestTest.java | 5 +- .../unit/AssistantConversationMemoryTest.java | 2 + .../unit/mcp/McpApplicationToolsTest.java | 4 +- .../unit/mcp/McpAuditAspectProxyTest.java | 2 +- .../unit/mcp/McpAuditAspectTest.java | 4 +- .../unit/mcp/McpDashboardToolsTest.java | 4 +- .../unit/mcp/McpGamificationToolsTest.java | 4 +- .../unit/mcp/McpProfileToolsTest.java | 4 +- .../unit/mcp/McpPromptsConfigTest.java | 4 +- 59 files changed, 303 insertions(+), 159 deletions(-) create mode 100644 docs/superpowers/plans/2026-09-27-spring-boot-4-migration.md diff --git a/README.md b/README.md index 93d57fa..7b35cdd 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ A production-ready Spring Boot REST API for tracking job applications, built wit ## Tech Stack - **Java 21** -- **Spring Boot 3.5** (Web, Data JPA, Security, Validation) -- **Spring AI 1.0.0** — MCP server (`spring-ai-starter-mcp-server-webmvc`, Streamable HTTP transport) +- **Spring Boot 4.1** (Web MVC, Data JPA, Security, Validation) +- **Spring AI 2.0** — MCP server (`spring-ai-starter-mcp-server-webmvc`, Streamable HTTP transport) - **Spring OAuth2 Authorization Server** (JDBC-backed, issues tokens for both GPT Actions and MCP clients) - **Spring Security** with stateless JWT authentication + role-based authorization (`USER`, `BETA`, `ADMIN`) - **JWT + Refresh Tokens** (access: 15 min, refresh: 7 days with rotation) diff --git a/docs/superpowers/plans/2026-09-27-spring-boot-4-migration.md b/docs/superpowers/plans/2026-09-27-spring-boot-4-migration.md new file mode 100644 index 0000000..4b61264 --- /dev/null +++ b/docs/superpowers/plans/2026-09-27-spring-boot-4-migration.md @@ -0,0 +1,113 @@ +# Spring Boot 4.1 / Spring AI 2.0 Migration Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Move the backend to stable Spring Boot 4.1.x and Spring AI 2.0.x, retaining Java 21 and existing application behavior. + +**Architecture:** Keep the current service, API, security, and MCP architecture. Upgrade managed dependencies and Boot-native starters, then adapt only the source/configuration surfaces that fail against the new APIs. Audit third-party libraries and deployment settings after the migration compiles. + +**Tech Stack:** Java 21, Maven, Spring Boot 4.1.x, Spring Security 7.x, Spring AI 2.0.x, Jackson 3, MariaDB/JPA/Flyway. + +**Spec:** `docs/superpowers/specs/2026-09-27-spring-boot-4-migration-design.md` + +## Global Constraints + +- Keep Java 21. +- Use stable Spring Boot 4.1.x and Spring AI 2.0.x; do not use Boot 4.2 milestones or release candidates. +- Do not retain `spring-boot-starter-classic` or Jackson 2 compatibility as the final application architecture. +- Preserve current application API, OAuth/OIDC/PKCE, MCP, OpenAPI, Actuator, Prometheus, and OpenTelemetry behavior. +- Keep MariaDB, JPA, and Flyway; do not require a paid AI provider in CI. +- Remove explicit versions already managed by Boot or Spring AI; keep third-party overrides only when compatibility requires them. + +## Review Focus + +- JSON responses and persisted token/claim serialization preserve current wire formats — cover with existing serialization and JWT tests. +- Authorization server endpoints, OAuth2/OIDC/PKCE, and refresh-token extensions still behave as before — cover with existing auth integration tests. +- MCP initializes and exposes expected resources/tools over WebMVC — cover with MCP auth/resource and assistant tests. +- OpenAPI groups/security schemes and Swagger UI still resolve — cover with `OpenApiDocumentationIT`. +- Actuator, rate limiting, Prometheus, and tracing configuration remain active — inspect dependency tree and startup/property binding; add focused checks only if existing coverage does not expose regressions. + +--- + +### Task 1: Upgrade managed versions and Boot 4 modules + +**Files:** +- Modify: `pom.xml` + +**Interfaces:** +- Consumes: existing application dependency graph and the design's stable-version constraints. +- Produces: a Boot 4.1.x / Spring AI 2.0.x Maven model with Boot 4-native starters and correctly managed Spring Security and Authorization Server artifacts. + +- [ ] Set the Boot parent to the latest stable 4.1.x release and Spring AI BOM to the latest stable 2.0.x release available at implementation time; keep `java.version` at 21. +- [ ] Replace the MVC, OAuth2 client/resource-server, AOP, Flyway, and test starters/modules with their Boot 4-native equivalents required by current code. Do not use classic compatibility starters. +- [ ] Remove the standalone Spring Authorization Server 1.5.x override and use the Security 7 generation managed by the Boot 4.1 BOM where available. +- [ ] Upgrade springdoc to stable 3.1.x and replace `resilience4j-spring-boot3` with the current stable `resilience4j-spring-boot4` artifact. +- [ ] Resolve the dependency model with `./mvnw -q -DskipTests dependency:resolve` and inspect the effective dependency tree for unavailable artifacts and duplicate Spring/Jackson generations. + +### Task 2: Migrate Jackson 3 application usage + +**Files:** +- Modify: Java source and tests identified by Jackson imports/usages, including `src/main/java/com/jobtracker/util/SecurityUtils.java`, `service/export/ExportConfigCodec.java`, Jackson-using DTO/controller/service files, and their focused tests. +- Modify: `pom.xml` only if a direct Jackson dependency is required after the Boot BOM migration. + +**Interfaces:** +- Consumes: Jackson 3 APIs managed by Boot 4; current JSON contracts and JWT serialization behavior. +- Produces: application JSON configuration and serialization using Jackson 3, with no default Jackson 2 compatibility layer. + +- [ ] Search all production and test sources for `com.fasterxml.jackson`, Jackson mapper/customizer APIs, and serialization assertions; classify imports still provided by third-party Jackson 2 dependencies. +- [ ] Update application Jackson package imports, mapper configuration, exception handling, and tests to Jackson 3 equivalents while preserving external JSON shapes. +- [ ] Keep a Jackson 2 compatibility module only if a concrete third-party dependency requires it; isolate it to that boundary and document the reason in the POM. +- [ ] Run focused mapper, export codec, JWT, controller serialization, and Spring context tests. + +### Task 3: Migrate Security 7 and authorization-server configuration + +**Files:** +- Modify: `src/main/java/com/jobtracker/config/SecurityConfig.java`, `AuthorizationServerConfig.java`, `CimdRegisteredClientRepository.java`, `PublicClientRefreshToken*.java`, `OAuth*MetadataController.java`, `DynamicClientRegistrationController.java`, and other compile-identified security classes. +- Modify: related auth integration tests under `src/test/java/com/jobtracker/integration/`. + +**Interfaces:** +- Consumes: Security 7 and Boot-managed authorization-server APIs. +- Produces: existing OAuth2/OIDC/PKCE endpoints, JWT resource-server validation, client registration, and custom refresh-token behavior on Boot 4. + +- [ ] Fix compile errors from Security 7 API and package changes with minimal source edits; preserve filter-chain ordering and authorization rules. +- [ ] Adapt authorization-server extensions to the supported Security 7 APIs without retaining the old separately versioned server implementation. +- [ ] Run targeted authorization-server, PKCE/OIDC, resource-server, passkey, and rate-limit integration tests. + +### Task 4: Migrate Spring AI 2 and MCP integrations + +**Files:** +- Modify: `src/main/java/com/jobtracker/service/assistant/**`, `config/AssistantToolCallingConfiguration.java`, `mcp/**`, and AI configuration in `src/main/resources/application.yml`. +- Modify: assistant/MCP tests under `src/test/java/com/jobtracker/unit/` and `integration/`. + +**Interfaces:** +- Consumes: Spring AI 2.0 chat/tool APIs, Google GenAI starter, and Spring AI-managed MCP WebMVC transport. +- Produces: existing SSE assistant behavior, tool registration/calls, MCP resources/prompts/tools, and provider-disabled test startup. + +- [ ] Follow Spring AI 2 upgrade notes for MCP artifact/package changes, WebMVC Streamable HTTP transport, Google GenAI model configuration, and chat/tool API changes. +- [ ] Adapt assistant streaming/error handling and tool registration with no externally visible API change. +- [ ] Preserve provider-disabled test profile behavior and use stubs/mocks for provider-specific tests. +- [ ] Run focused assistant service/controller/tool and MCP auth/resource tests. + +### Task 5: Audit direct dependencies, configuration, docs, and end-to-end verification + +**Files:** +- Modify: `pom.xml`, `src/main/resources/application.yml`, `src/test/resources/application-test.yml`, and deployment/documentation files only where version or configuration changes require it. +- Test: focused integration tests and the issue-required Maven verification commands. + +**Interfaces:** +- Consumes: compiling Boot 4 application and selected Boot/Spring AI BOMs. +- Produces: audited compatible dependency set and verified Boot 4 runtime configuration. + +- [ ] Audit all explicit direct dependency versions and Maven plugins in `pom.xml`; update stable compatible versions and remove BOM-managed overrides. Retain pinned versions only with a compatibility reason. +- [ ] Review Flyway, Jackson, mail/web, Actuator/Micrometer/OTLP, Resilience4j, and Spring AI properties across application/test/deployment configuration; remove renamed or obsolete keys. +- [ ] Update README/deployment guidance only where Java, dependency, or configuration requirements changed. +- [ ] Run the focused tests for serialization, security, assistant/MCP, OpenAPI, and configuration. +- [ ] Run `./mvnw clean verify` and `./mvnw dependency:tree`; confirm Java 21 build, AOT execution, no accidental duplicate Spring/Jackson generations, and successful normal-profile application startup if local services/configuration permit. + +## Self-Review + +- Spec coverage: dependency baseline, starters, Jackson, Security/Authorization Server, Spring AI/MCP, OpenAPI, Resilience4j, dependency audit, configuration, docs, and verification each have an owning task. +- Step scan: each checkbox identifies one bounded migration or verification action and its responsible files. +- Type/API consistency: Maven model outputs feed the Jackson, Security, and Spring AI source migration tasks; final audit runs only after those compile. +- Review focus: the five highest-risk behavior areas are paired with existing tests or an explicit targeted inspection. +- Proportion: the plan groups by migration boundary and avoids enumerating every Jackson-using file before compiler/search evidence identifies which ones actually change. diff --git a/pom.xml b/pom.xml index 0fa7b7e..c2d8dc6 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.0 + 4.1.1 @@ -19,13 +19,11 @@ 21 - 0.12.5 - 1.19.8 - 5.4.0 - 0.10.2 + 0.13.0 + 1.21.4 + 6.0.1 2.9.0 - 1.5.8 - 1.1.7 + 2.0.1 @@ -44,7 +42,11 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter-webmvc + + + org.springframework.boot + spring-boot-starter-restclient org.springframework.boot @@ -60,7 +62,7 @@ org.springframework.boot - spring-boot-starter-aop + spring-boot-starter-aspectj org.springframework.boot @@ -85,8 +87,8 @@ - org.flywaydb - flyway-core + org.springframework.boot + spring-boot-starter-flyway org.flywaydb @@ -116,7 +118,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - 2.8.9 + 3.1.1 @@ -130,6 +132,10 @@ io.micrometer micrometer-tracing-bridge-otel + + org.springframework.boot + spring-boot-micrometer-tracing-opentelemetry + @@ -144,29 +150,29 @@ io.github.resilience4j - resilience4j-spring-boot3 - 2.2.0 + resilience4j-spring-boot4 + 2.4.0 net.logstash.logback logstash-logback-encoder - 7.4 + 9.0 net.datafaker datafaker - 2.3.1 + 2.7.0 org.jsoup jsoup - 1.23.1 + 1.23.2 @@ -207,51 +213,50 @@ org.springframework.boot - spring-boot-starter-oauth2-client + spring-boot-starter-security-oauth2-client org.springframework.boot - spring-boot-starter-oauth2-resource-server + spring-boot-starter-security-oauth2-resource-server - org.springframework.security - spring-security-oauth2-authorization-server - ${spring-authorization-server.version} + org.springframework.boot + spring-boot-starter-security-oauth2-authorization-server com.google.apis google-api-services-drive - v3-rev20240521-2.0.0 + v3-rev20260913-2.0.0 com.google.apis google-api-services-docs - v1-rev20240726-2.0.0 + v1-rev20260902-2.0.0 com.google.auth google-auth-library-oauth2-http - 1.25.0 + 1.53.0 org.apache.pdfbox pdfbox - 3.0.4 + 3.0.8 org.apache.poi poi-ooxml - 5.4.0 + 5.5.1 @@ -261,8 +266,18 @@ test - org.springframework.security - spring-security-test + org.springframework.boot + spring-boot-starter-security-test + test + + + org.springframework.boot + spring-boot-starter-security-oauth2-authorization-server-test + test + + + org.springframework.boot + spring-boot-starter-webmvc-test test diff --git a/src/main/java/com/jobtracker/JobTrackerApplication.java b/src/main/java/com/jobtracker/JobTrackerApplication.java index 9e56562..2f18e27 100644 --- a/src/main/java/com/jobtracker/JobTrackerApplication.java +++ b/src/main/java/com/jobtracker/JobTrackerApplication.java @@ -2,20 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; -import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration; import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; -import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration; -import org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration; @SpringBootApplication(exclude = { JmxAutoConfiguration.class, - JmxEndpointAutoConfiguration.class, - FreeMarkerAutoConfiguration.class, - GroovyTemplateAutoConfiguration.class, - MustacheAutoConfiguration.class, - WebSocketServletAutoConfiguration.class + JmxEndpointAutoConfiguration.class }) public class JobTrackerApplication { diff --git a/src/main/java/com/jobtracker/config/AssistantToolCallingConfiguration.java b/src/main/java/com/jobtracker/config/AssistantToolCallingConfiguration.java index b6f2691..5df5504 100644 --- a/src/main/java/com/jobtracker/config/AssistantToolCallingConfiguration.java +++ b/src/main/java/com/jobtracker/config/AssistantToolCallingConfiguration.java @@ -1,7 +1,7 @@ package com.jobtracker.config; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.ObjectMapper; import org.springframework.ai.tool.execution.DefaultToolExecutionExceptionProcessor; import org.springframework.ai.tool.execution.ToolExecutionExceptionProcessor; import org.springframework.beans.factory.annotation.Value; @@ -29,7 +29,7 @@ ToolExecutionExceptionProcessor jsonSafeToolExecutionExceptionProcessor( String message = delegate.process(exception); try { return objectMapper.writeValueAsString(Map.of("error", message)); - } catch (JsonProcessingException serializationFailure) { + } catch (JacksonException serializationFailure) { return "{\"error\":\"Tool execution failed\"}"; } }; diff --git a/src/main/java/com/jobtracker/config/AuthorizationServerConfig.java b/src/main/java/com/jobtracker/config/AuthorizationServerConfig.java index b469c09..7dcbe97 100644 --- a/src/main/java/com/jobtracker/config/AuthorizationServerConfig.java +++ b/src/main/java/com/jobtracker/config/AuthorizationServerConfig.java @@ -35,8 +35,8 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository; import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; -import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; -import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; +import org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer; import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcUserInfoAuthenticationContext; import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings; import org.springframework.security.oauth2.server.authorization.settings.ClientSettings; @@ -77,6 +77,14 @@ public class AuthorizationServerConfig { @Bean @Order(Ordered.HIGHEST_PRECEDENCE) + public SecurityFilterChain protectedResourceMetadataSecurityFilterChain(HttpSecurity http) throws Exception { + http.securityMatcher(request -> request.getRequestURI().startsWith("/.well-known/oauth-protected-resource")) + .authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll()); + return http.build(); + } + + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE + 1) public SecurityFilterChain authorizationServerSecurityFilterChain( HttpSecurity http, AuthorizationServerSettings authorizationServerSettings, @@ -84,7 +92,7 @@ public SecurityFilterChain authorizationServerSecurityFilterChain( McpOAuthProperties mcpOAuthProperties, FormLoginRateLimitFilter formLoginRateLimitFilter, RegisteredClientRepository registeredClientRepository) throws Exception { - OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer.authorizationServer(); + OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer(); RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher(); RequestMatcher authServerMatcher = new OrRequestMatcher( endpointsMatcher, diff --git a/src/main/java/com/jobtracker/config/UserDetailsConfig.java b/src/main/java/com/jobtracker/config/UserDetailsConfig.java index bc7a924..dfc0e1b 100644 --- a/src/main/java/com/jobtracker/config/UserDetailsConfig.java +++ b/src/main/java/com/jobtracker/config/UserDetailsConfig.java @@ -7,10 +7,13 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.authority.FactorGrantedAuthority; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.time.Instant; @Configuration public class UserDetailsConfig { @@ -27,8 +30,13 @@ public UserDetailsService userDetailsService() { .map(user -> new org.springframework.security.core.userdetails.User( user.getEmail(), user.getPasswordHash(), - user.getRoles().stream() - .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName().name())) + Stream.concat( + user.getRoles().stream() + .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName().name())), + Stream.of(FactorGrantedAuthority.withAuthority( + FactorGrantedAuthority.PASSWORD_AUTHORITY) + .issuedAt(Instant.now()) + .build())) .collect(Collectors.toSet()))) .orElseThrow(() -> new UsernameNotFoundException("User not found: " + username)); } @@ -36,8 +44,7 @@ public UserDetailsService userDetailsService() { @Bean public DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { - DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); - provider.setUserDetailsService(userDetailsService); + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService); provider.setPasswordEncoder(passwordEncoder); return provider; } diff --git a/src/main/java/com/jobtracker/dto/auth/PasskeyOptionsResponse.java b/src/main/java/com/jobtracker/dto/auth/PasskeyOptionsResponse.java index 3517a03..dc03f44 100644 --- a/src/main/java/com/jobtracker/dto/auth/PasskeyOptionsResponse.java +++ b/src/main/java/com/jobtracker/dto/auth/PasskeyOptionsResponse.java @@ -1,6 +1,6 @@ package com.jobtracker.dto.auth; -import com.fasterxml.jackson.databind.JsonNode; +import tools.jackson.databind.JsonNode; import java.util.UUID; diff --git a/src/main/java/com/jobtracker/dto/auth/PasskeyVerifyRequest.java b/src/main/java/com/jobtracker/dto/auth/PasskeyVerifyRequest.java index 93caaa4..4fb6261 100644 --- a/src/main/java/com/jobtracker/dto/auth/PasskeyVerifyRequest.java +++ b/src/main/java/com/jobtracker/dto/auth/PasskeyVerifyRequest.java @@ -1,6 +1,6 @@ package com.jobtracker.dto.auth; -import com.fasterxml.jackson.databind.JsonNode; +import tools.jackson.databind.JsonNode; import jakarta.validation.constraints.NotNull; import java.util.UUID; diff --git a/src/main/java/com/jobtracker/dto/gdrive/GoogleDriveBaseResumeRequest.java b/src/main/java/com/jobtracker/dto/gdrive/GoogleDriveBaseResumeRequest.java index 37b8367..ea248f8 100644 --- a/src/main/java/com/jobtracker/dto/gdrive/GoogleDriveBaseResumeRequest.java +++ b/src/main/java/com/jobtracker/dto/gdrive/GoogleDriveBaseResumeRequest.java @@ -13,5 +13,9 @@ public record GoogleDriveBaseResumeRequest( String language, @Schema(description = "Whether this resume is a template", example = "true") - boolean template -) {} + Boolean template +) { + public GoogleDriveBaseResumeRequest { + template = Boolean.TRUE.equals(template); + } +} diff --git a/src/main/java/com/jobtracker/mcp/McpPromptsConfig.java b/src/main/java/com/jobtracker/mcp/McpPromptsConfig.java index 6f13fd5..94b283a 100644 --- a/src/main/java/com/jobtracker/mcp/McpPromptsConfig.java +++ b/src/main/java/com/jobtracker/mcp/McpPromptsConfig.java @@ -5,9 +5,9 @@ import io.modelcontextprotocol.spec.McpSchema.PromptMessage; import io.modelcontextprotocol.spec.McpSchema.Role; import io.modelcontextprotocol.spec.McpSchema.TextContent; -import org.springaicommunity.mcp.annotation.McpComplete; -import org.springaicommunity.mcp.annotation.McpArg; -import org.springaicommunity.mcp.annotation.McpPrompt; +import org.springframework.ai.mcp.annotation.McpComplete; +import org.springframework.ai.mcp.annotation.McpArg; +import org.springframework.ai.mcp.annotation.McpPrompt; import org.springframework.stereotype.Service; import java.util.List; diff --git a/src/main/java/com/jobtracker/mcp/audit/McpAuditAspect.java b/src/main/java/com/jobtracker/mcp/audit/McpAuditAspect.java index 4d36f37..b3c33aa 100644 --- a/src/main/java/com/jobtracker/mcp/audit/McpAuditAspect.java +++ b/src/main/java/com/jobtracker/mcp/audit/McpAuditAspect.java @@ -11,7 +11,7 @@ import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/jobtracker/mcp/resources/McpApplicationCreationRulesResource.java b/src/main/java/com/jobtracker/mcp/resources/McpApplicationCreationRulesResource.java index 72936aa..cecc2d5 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpApplicationCreationRulesResource.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpApplicationCreationRulesResource.java @@ -4,8 +4,8 @@ import com.jobtracker.mcp.audit.AuditMcpOperation; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.stereotype.Service; @Service diff --git a/src/main/java/com/jobtracker/mcp/resources/McpApplicationLifecycleRulesResource.java b/src/main/java/com/jobtracker/mcp/resources/McpApplicationLifecycleRulesResource.java index 33f4741..735ecbe 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpApplicationLifecycleRulesResource.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpApplicationLifecycleRulesResource.java @@ -4,8 +4,8 @@ import com.jobtracker.mcp.audit.AuditMcpOperation; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.stereotype.Service; @Service diff --git a/src/main/java/com/jobtracker/mcp/resources/McpApplicationStatusesResource.java b/src/main/java/com/jobtracker/mcp/resources/McpApplicationStatusesResource.java index 3926ae9..159429f 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpApplicationStatusesResource.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpApplicationStatusesResource.java @@ -6,8 +6,8 @@ import com.jobtracker.repository.ApplicationStatusRepository; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.stereotype.Service; @Service diff --git a/src/main/java/com/jobtracker/mcp/resources/McpBaseInformationContentResource.java b/src/main/java/com/jobtracker/mcp/resources/McpBaseInformationContentResource.java index 0045e33..cf9563a 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpBaseInformationContentResource.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpBaseInformationContentResource.java @@ -6,8 +6,8 @@ import com.jobtracker.service.BaseInformationService; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/jobtracker/mcp/resources/McpBaseResumeContentResource.java b/src/main/java/com/jobtracker/mcp/resources/McpBaseResumeContentResource.java index 86c8428..61830e7 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpBaseResumeContentResource.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpBaseResumeContentResource.java @@ -6,8 +6,8 @@ import com.jobtracker.service.ResumeGenerationService; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/jobtracker/mcp/resources/McpGeneratedResumeContentResource.java b/src/main/java/com/jobtracker/mcp/resources/McpGeneratedResumeContentResource.java index 01fd461..e3487ec 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpGeneratedResumeContentResource.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpGeneratedResumeContentResource.java @@ -6,8 +6,8 @@ import com.jobtracker.service.ResumeGenerationService.GeneratedResumeContentResponse; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/jobtracker/mcp/resources/McpReadOnlySnapshotResources.java b/src/main/java/com/jobtracker/mcp/resources/McpReadOnlySnapshotResources.java index a757dcf..17f2b57 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpReadOnlySnapshotResources.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpReadOnlySnapshotResources.java @@ -1,7 +1,7 @@ package com.jobtracker.mcp.resources; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.UserResponse; import com.jobtracker.mapper.AuthMapper; import com.jobtracker.mcp.McpResourcesConfig; @@ -13,8 +13,8 @@ import com.jobtracker.util.SecurityUtils; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; @@ -162,7 +162,7 @@ public String currentUser(McpSyncServerExchange exchange) { private String toJson(Object value) { try { return objectMapper.writeValueAsString(value); - } catch (JsonProcessingException ex) { + } catch (JacksonException ex) { throw new IllegalStateException("Failed to serialize MCP resource", ex); } } diff --git a/src/main/java/com/jobtracker/mcp/resources/McpResumeWorkflowRulesResource.java b/src/main/java/com/jobtracker/mcp/resources/McpResumeWorkflowRulesResource.java index a2b50fd..671fc11 100644 --- a/src/main/java/com/jobtracker/mcp/resources/McpResumeWorkflowRulesResource.java +++ b/src/main/java/com/jobtracker/mcp/resources/McpResumeWorkflowRulesResource.java @@ -4,8 +4,8 @@ import com.jobtracker.mcp.audit.AuditMcpOperation; import io.modelcontextprotocol.server.McpSyncServerExchange; import io.modelcontextprotocol.spec.McpSchema.Role; -import org.springaicommunity.mcp.annotation.McpResource; -import org.springaicommunity.mcp.annotation.McpResource.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpResource; +import org.springframework.ai.mcp.annotation.McpResource.McpAnnotations; import org.springframework.stereotype.Service; @Service diff --git a/src/main/java/com/jobtracker/mcp/tools/McpAnalyticsTools.java b/src/main/java/com/jobtracker/mcp/tools/McpAnalyticsTools.java index 015d153..4ccb38d 100644 --- a/src/main/java/com/jobtracker/mcp/tools/McpAnalyticsTools.java +++ b/src/main/java/com/jobtracker/mcp/tools/McpAnalyticsTools.java @@ -10,10 +10,10 @@ import com.jobtracker.repository.ApplicationRepository; import com.jobtracker.service.ApplicationService; import com.jobtracker.util.SecurityUtils; -import org.springaicommunity.mcp.annotation.McpTool; -import org.springaicommunity.mcp.annotation.McpTool.McpAnnotations; -import org.springaicommunity.mcp.annotation.McpToolParam; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.ai.mcp.annotation.McpTool.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpToolParam; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/jobtracker/mcp/tools/McpApplicationTools.java b/src/main/java/com/jobtracker/mcp/tools/McpApplicationTools.java index aecf2a2..f4dea75 100644 --- a/src/main/java/com/jobtracker/mcp/tools/McpApplicationTools.java +++ b/src/main/java/com/jobtracker/mcp/tools/McpApplicationTools.java @@ -11,10 +11,10 @@ import com.jobtracker.mcp.audit.AuditMcpOperation; import com.jobtracker.service.ApplicationService; import java.util.List; -import org.springaicommunity.mcp.annotation.McpTool; -import org.springaicommunity.mcp.annotation.McpTool.McpAnnotations; -import org.springaicommunity.mcp.annotation.McpToolParam; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.ai.mcp.annotation.McpTool.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpToolParam; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import org.springframework.stereotype.Component; import java.time.LocalDate; diff --git a/src/main/java/com/jobtracker/mcp/tools/McpBaseInformationTools.java b/src/main/java/com/jobtracker/mcp/tools/McpBaseInformationTools.java index 8abbd61..3972a63 100644 --- a/src/main/java/com/jobtracker/mcp/tools/McpBaseInformationTools.java +++ b/src/main/java/com/jobtracker/mcp/tools/McpBaseInformationTools.java @@ -4,10 +4,10 @@ import com.jobtracker.dto.gdrive.BaseInformationResponse; import com.jobtracker.mcp.audit.AuditMcpOperation; import com.jobtracker.service.BaseInformationService; -import org.springaicommunity.mcp.annotation.McpTool; -import org.springaicommunity.mcp.annotation.McpTool.McpAnnotations; -import org.springaicommunity.mcp.annotation.McpToolParam; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.ai.mcp.annotation.McpTool.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpToolParam; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/jobtracker/mcp/tools/McpGamificationTools.java b/src/main/java/com/jobtracker/mcp/tools/McpGamificationTools.java index f8bd900..02e76f4 100644 --- a/src/main/java/com/jobtracker/mcp/tools/McpGamificationTools.java +++ b/src/main/java/com/jobtracker/mcp/tools/McpGamificationTools.java @@ -6,10 +6,10 @@ import com.jobtracker.gamification.GamificationProgressCallback; import com.jobtracker.mcp.audit.AuditMcpOperation; import com.jobtracker.service.GamificationService; -import org.springaicommunity.mcp.annotation.McpTool; -import org.springaicommunity.mcp.annotation.McpTool.McpAnnotations; -import org.springaicommunity.mcp.annotation.McpToolParam; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.ai.mcp.annotation.McpTool.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpToolParam; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import org.springframework.stereotype.Component; import java.time.LocalDateTime; diff --git a/src/main/java/com/jobtracker/mcp/tools/McpGoogleDriveTools.java b/src/main/java/com/jobtracker/mcp/tools/McpGoogleDriveTools.java index 7640441..9f66fe0 100644 --- a/src/main/java/com/jobtracker/mcp/tools/McpGoogleDriveTools.java +++ b/src/main/java/com/jobtracker/mcp/tools/McpGoogleDriveTools.java @@ -11,10 +11,10 @@ import com.jobtracker.service.GoogleDriveGeneratedResumeDownloadService.DownloadedFile; import com.jobtracker.service.GoogleDriveService; import com.jobtracker.service.ResumeGenerationService; -import org.springaicommunity.mcp.annotation.McpTool; -import org.springaicommunity.mcp.annotation.McpTool.McpAnnotations; -import org.springaicommunity.mcp.annotation.McpToolParam; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.ai.mcp.annotation.McpTool.McpAnnotations; +import org.springframework.ai.mcp.annotation.McpToolParam; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/jobtracker/service/PasskeyAuthService.java b/src/main/java/com/jobtracker/service/PasskeyAuthService.java index 0a2fe82..98ddeba 100644 --- a/src/main/java/com/jobtracker/service/PasskeyAuthService.java +++ b/src/main/java/com/jobtracker/service/PasskeyAuthService.java @@ -1,8 +1,8 @@ package com.jobtracker.service; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.config.WebAuthnProperties; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.MessageResponse; @@ -259,7 +259,7 @@ private WebAuthnChallenge resolveUsableChallenge(UUID challengeId, WebAuthnChall private JsonNode readJson(String json) { try { return objectMapper.readTree(json); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { throw new IllegalStateException("Failed to serialize WebAuthn options", e); } } @@ -275,7 +275,7 @@ private JsonNode readCredentialPublicKey(String credentialsJson) { private String toJsonSafely(PublicKeyCredentialCreationOptions options) { try { return options.toJson(); - } catch (JsonProcessingException e) { + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { throw new IllegalStateException("Failed to serialize WebAuthn registration request", e); } } @@ -283,7 +283,7 @@ private String toJsonSafely(PublicKeyCredentialCreationOptions options) { private String toJsonSafely(AssertionRequest assertionRequest) { try { return assertionRequest.toJson(); - } catch (JsonProcessingException e) { + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { throw new IllegalStateException("Failed to serialize WebAuthn assertion request", e); } } @@ -291,7 +291,7 @@ private String toJsonSafely(AssertionRequest assertionRequest) { private String toCredentialsCreateJsonSafely(PublicKeyCredentialCreationOptions options) { try { return options.toCredentialsCreateJson(); - } catch (JsonProcessingException e) { + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { throw new IllegalStateException("Failed to serialize WebAuthn registration options", e); } } @@ -299,7 +299,7 @@ private String toCredentialsCreateJsonSafely(PublicKeyCredentialCreationOptions private String toCredentialsGetJsonSafely(AssertionRequest assertionRequest) { try { return assertionRequest.toCredentialsGetJson(); - } catch (JsonProcessingException e) { + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { throw new IllegalStateException("Failed to serialize WebAuthn authentication options", e); } } @@ -307,7 +307,7 @@ private String toCredentialsGetJsonSafely(AssertionRequest assertionRequest) { private PublicKeyCredentialCreationOptions parseRegistrationOptions(String json) { try { return PublicKeyCredentialCreationOptions.fromJson(json); - } catch (JsonProcessingException e) { + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { throw new BadRequestException("Invalid registration request payload"); } } @@ -315,7 +315,7 @@ private PublicKeyCredentialCreationOptions parseRegistrationOptions(String json) private AssertionRequest parseAssertionRequest(String json) { try { return AssertionRequest.fromJson(json); - } catch (JsonProcessingException e) { + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { throw new BadRequestException("Invalid authentication request payload"); } } diff --git a/src/main/java/com/jobtracker/service/TokenEstimatorService.java b/src/main/java/com/jobtracker/service/TokenEstimatorService.java index 488f643..f72076c 100644 --- a/src/main/java/com/jobtracker/service/TokenEstimatorService.java +++ b/src/main/java/com/jobtracker/service/TokenEstimatorService.java @@ -1,6 +1,6 @@ package com.jobtracker.service; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.knuddels.jtokkit.Encodings; import com.knuddels.jtokkit.api.Encoding; import com.knuddels.jtokkit.api.EncodingRegistry; diff --git a/src/main/java/com/jobtracker/service/export/ExportConfigCodec.java b/src/main/java/com/jobtracker/service/export/ExportConfigCodec.java index fa0903e..f581e7e 100644 --- a/src/main/java/com/jobtracker/service/export/ExportConfigCodec.java +++ b/src/main/java/com/jobtracker/service/export/ExportConfigCodec.java @@ -1,8 +1,8 @@ package com.jobtracker.service.export; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.core.JacksonException; +import tools.jackson.core.type.TypeReference; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.export.ExportFilters; import com.jobtracker.exception.BadRequestException; import org.springframework.stereotype.Component; @@ -31,7 +31,7 @@ public String write(Object value) { } try { return objectMapper.writeValueAsString(value); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { throw new BadRequestException("Could not store the export configuration"); } } @@ -43,7 +43,7 @@ public ExportFilters readFilters(String json) { } try { return objectMapper.readValue(json, ExportFilters.class); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { return ExportFilters.empty(); } } @@ -54,7 +54,7 @@ public List readColumns(String json) { } try { return objectMapper.readValue(json, new TypeReference>() {}); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { return List.of(); } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 26d0e9b..aa3580a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,7 +36,7 @@ spring: resource://job-apply-tracker/application-lifecycle-rules for the full lifecycle policy. # Claude.ai (and other modern MCP connectors) speak the Streamable HTTP # transport: a single endpoint that handles both POST (JSON-RPC) and GET - # (SSE stream). Requires Spring AI 1.1+. The endpoint defaults to /mcp, + # (SSE stream). Requires Spring AI 2.0+. The endpoint defaults to /mcp, # which is already covered by SecurityConfig's /mcp/** rule and the # OAuth protected-resource metadata controller. protocol: STREAMABLE diff --git a/src/test/java/com/jobtracker/JobTrackerApplicationTests.java b/src/test/java/com/jobtracker/JobTrackerApplicationTests.java index c5a51af..cf35d67 100644 --- a/src/test/java/com/jobtracker/JobTrackerApplicationTests.java +++ b/src/test/java/com/jobtracker/JobTrackerApplicationTests.java @@ -1,7 +1,7 @@ package com.jobtracker; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import org.springframework.ai.tool.definition.ToolDefinition; import org.springframework.ai.tool.execution.ToolExecutionException; diff --git a/src/test/java/com/jobtracker/e2e/ChatGptConnectorOAuthE2ETest.java b/src/test/java/com/jobtracker/e2e/ChatGptConnectorOAuthE2ETest.java index 87c1552..24001d7 100644 --- a/src/test/java/com/jobtracker/e2e/ChatGptConnectorOAuthE2ETest.java +++ b/src/test/java/com/jobtracker/e2e/ChatGptConnectorOAuthE2ETest.java @@ -367,8 +367,8 @@ void fullChatGptConnectorFlow_dcrToAuthenticatedMcpCall() throws Exception { private static Map decodeJwtPayload(String jwt) throws Exception { String payload = jwt.split("\\.")[1]; byte[] json = Base64.getUrlDecoder().decode(payload); - return new com.fasterxml.jackson.databind.ObjectMapper() - .readValue(json, new com.fasterxml.jackson.core.type.TypeReference>() {}); + return new tools.jackson.databind.ObjectMapper() + .readValue(json, new tools.jackson.core.type.TypeReference>() {}); } /** diff --git a/src/test/java/com/jobtracker/integration/AbstractIntegrationTest.java b/src/test/java/com/jobtracker/integration/AbstractIntegrationTest.java index 17ac475..d7f9b1c 100644 --- a/src/test/java/com/jobtracker/integration/AbstractIntegrationTest.java +++ b/src/test/java/com/jobtracker/integration/AbstractIntegrationTest.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; diff --git a/src/test/java/com/jobtracker/integration/ApplicationControllerIT.java b/src/test/java/com/jobtracker/integration/ApplicationControllerIT.java index 6450957..ad951fc 100644 --- a/src/test/java/com/jobtracker/integration/ApplicationControllerIT.java +++ b/src/test/java/com/jobtracker/integration/ApplicationControllerIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.application.ApplicationRequest; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; diff --git a/src/test/java/com/jobtracker/integration/AuthControllerIT.java b/src/test/java/com/jobtracker/integration/AuthControllerIT.java index 59a2f6f..0b8d706 100644 --- a/src/test/java/com/jobtracker/integration/AuthControllerIT.java +++ b/src/test/java/com/jobtracker/integration/AuthControllerIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.config.JwtService; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.LoginRequest; diff --git a/src/test/java/com/jobtracker/integration/AuthRateLimiterIT.java b/src/test/java/com/jobtracker/integration/AuthRateLimiterIT.java index bfdbe3c..4e0b3c6 100644 --- a/src/test/java/com/jobtracker/integration/AuthRateLimiterIT.java +++ b/src/test/java/com/jobtracker/integration/AuthRateLimiterIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.LoginRequest; import com.jobtracker.dto.auth.RegisterRequest; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/jobtracker/integration/DcrDisabledIT.java b/src/test/java/com/jobtracker/integration/DcrDisabledIT.java index 37baa53..c90d1e7 100644 --- a/src/test/java/com/jobtracker/integration/DcrDisabledIT.java +++ b/src/test/java/com/jobtracker/integration/DcrDisabledIT.java @@ -2,7 +2,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; diff --git a/src/test/java/com/jobtracker/integration/DynamicClientRegistrationIT.java b/src/test/java/com/jobtracker/integration/DynamicClientRegistrationIT.java index 5c0c27d..105e737 100644 --- a/src/test/java/com/jobtracker/integration/DynamicClientRegistrationIT.java +++ b/src/test/java/com/jobtracker/integration/DynamicClientRegistrationIT.java @@ -1,7 +1,7 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.config.DynamicClientRegistrationController; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/jobtracker/integration/ExportControllerIT.java b/src/test/java/com/jobtracker/integration/ExportControllerIT.java index 64bad77..fda5f62 100644 --- a/src/test/java/com/jobtracker/integration/ExportControllerIT.java +++ b/src/test/java/com/jobtracker/integration/ExportControllerIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.application.ApplicationRequest; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; diff --git a/src/test/java/com/jobtracker/integration/ExportRateLimitIT.java b/src/test/java/com/jobtracker/integration/ExportRateLimitIT.java index 3e76054..0630da2 100644 --- a/src/test/java/com/jobtracker/integration/ExportRateLimitIT.java +++ b/src/test/java/com/jobtracker/integration/ExportRateLimitIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/jobtracker/integration/ExportScheduleControllerIT.java b/src/test/java/com/jobtracker/integration/ExportScheduleControllerIT.java index 4c1d4d8..04b3d04 100644 --- a/src/test/java/com/jobtracker/integration/ExportScheduleControllerIT.java +++ b/src/test/java/com/jobtracker/integration/ExportScheduleControllerIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.application.ApplicationRequest; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; diff --git a/src/test/java/com/jobtracker/integration/ExportSchedulerIT.java b/src/test/java/com/jobtracker/integration/ExportSchedulerIT.java index d7b34c7..ab3d19f 100644 --- a/src/test/java/com/jobtracker/integration/ExportSchedulerIT.java +++ b/src/test/java/com/jobtracker/integration/ExportSchedulerIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.application.ApplicationRequest; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; diff --git a/src/test/java/com/jobtracker/integration/GamificationControllerIT.java b/src/test/java/com/jobtracker/integration/GamificationControllerIT.java index a8fafe8..6fed1b4 100644 --- a/src/test/java/com/jobtracker/integration/GamificationControllerIT.java +++ b/src/test/java/com/jobtracker/integration/GamificationControllerIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; import com.jobtracker.dto.gamification.GamificationEventRequest; diff --git a/src/test/java/com/jobtracker/integration/GitHubControllerIT.java b/src/test/java/com/jobtracker/integration/GitHubControllerIT.java index e9c3916..d87ccca 100644 --- a/src/test/java/com/jobtracker/integration/GitHubControllerIT.java +++ b/src/test/java/com/jobtracker/integration/GitHubControllerIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; import com.jobtracker.repository.RefreshTokenRepository; diff --git a/src/test/java/com/jobtracker/integration/GoogleDriveControllerIT.java b/src/test/java/com/jobtracker/integration/GoogleDriveControllerIT.java index 13f7861..dfe30e9 100644 --- a/src/test/java/com/jobtracker/integration/GoogleDriveControllerIT.java +++ b/src/test/java/com/jobtracker/integration/GoogleDriveControllerIT.java @@ -1,7 +1,7 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; import com.jobtracker.entity.GoogleDriveBaseResume; diff --git a/src/test/java/com/jobtracker/integration/GptOAuthFlowIT.java b/src/test/java/com/jobtracker/integration/GptOAuthFlowIT.java index caa6916..619ee59 100644 --- a/src/test/java/com/jobtracker/integration/GptOAuthFlowIT.java +++ b/src/test/java/com/jobtracker/integration/GptOAuthFlowIT.java @@ -1,7 +1,7 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; import com.jobtracker.repository.ApplicationRepository; @@ -19,6 +19,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.authority.FactorGrantedAuthority; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.security.oauth2.jwt.Jwt; @@ -234,7 +235,10 @@ private AuthResponse registerUser(String email, String password) throws Exceptio private String authorizeWithPkce(String email, String scope, PkcePair pkcePair) throws Exception { MvcResult result = mockMvc.perform(get("/oauth2/authorize") - .with(user(email).roles("USER")) + .with(user(email).roles("USER").authorities( + FactorGrantedAuthority.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY) + .issuedAt(java.time.Instant.now()) + .build())) .queryParam("response_type", "code") .queryParam("client_id", CLIENT_ID) .queryParam("redirect_uri", REDIRECT_URI) diff --git a/src/test/java/com/jobtracker/integration/OpenApiDocumentationIT.java b/src/test/java/com/jobtracker/integration/OpenApiDocumentationIT.java index 9fc9579..ff08aea 100644 --- a/src/test/java/com/jobtracker/integration/OpenApiDocumentationIT.java +++ b/src/test/java/com/jobtracker/integration/OpenApiDocumentationIT.java @@ -1,7 +1,7 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.MockMvc; diff --git a/src/test/java/com/jobtracker/integration/PasskeyRegistrationOptionsIT.java b/src/test/java/com/jobtracker/integration/PasskeyRegistrationOptionsIT.java index 39ca0a4..e1fc021 100644 --- a/src/test/java/com/jobtracker/integration/PasskeyRegistrationOptionsIT.java +++ b/src/test/java/com/jobtracker/integration/PasskeyRegistrationOptionsIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/jobtracker/integration/UserDeletionCascadeIT.java b/src/test/java/com/jobtracker/integration/UserDeletionCascadeIT.java index a6769e4..3976ffb 100644 --- a/src/test/java/com/jobtracker/integration/UserDeletionCascadeIT.java +++ b/src/test/java/com/jobtracker/integration/UserDeletionCascadeIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.RegisterRequest; import com.jobtracker.entity.ExportExecution; import com.jobtracker.entity.ExportSchedule; diff --git a/src/test/java/com/jobtracker/integration/mcp/McpAuthIT.java b/src/test/java/com/jobtracker/integration/mcp/McpAuthIT.java index 122b865..c655a65 100644 --- a/src/test/java/com/jobtracker/integration/mcp/McpAuthIT.java +++ b/src/test/java/com/jobtracker/integration/mcp/McpAuthIT.java @@ -1,6 +1,6 @@ package com.jobtracker.integration.mcp; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.AuthResponse; import com.jobtracker.dto.auth.RegisterRequest; import com.jobtracker.integration.AbstractIntegrationTest; diff --git a/src/test/java/com/jobtracker/unit/ApplicationConfigTest.java b/src/test/java/com/jobtracker/unit/ApplicationConfigTest.java index e86230a..6eee1bd 100644 --- a/src/test/java/com/jobtracker/unit/ApplicationConfigTest.java +++ b/src/test/java/com/jobtracker/unit/ApplicationConfigTest.java @@ -39,6 +39,6 @@ void userDetailsService_shouldMapPersistedRolesToGrantedAuthorities() { assertThat(userDetails.getAuthorities()) .extracting("authority") - .containsExactlyInAnyOrder("ROLE_USER", "ROLE_BETA"); + .containsExactlyInAnyOrder("ROLE_USER", "ROLE_BETA", "FACTOR_PASSWORD"); } } diff --git a/src/test/java/com/jobtracker/unit/ApplicationPatchRequestTest.java b/src/test/java/com/jobtracker/unit/ApplicationPatchRequestTest.java index 673aee6..cc9b080 100644 --- a/src/test/java/com/jobtracker/unit/ApplicationPatchRequestTest.java +++ b/src/test/java/com/jobtracker/unit/ApplicationPatchRequestTest.java @@ -1,7 +1,6 @@ package com.jobtracker.unit; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.application.ApplicationPatchRequest; import org.junit.jupiter.api.Test; @@ -15,7 +14,7 @@ */ class ApplicationPatchRequestTest { - private final ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()); + private final ObjectMapper objectMapper = new ObjectMapper(); @Test void omittedProperties_areNotMarkedAsProvided() throws Exception { diff --git a/src/test/java/com/jobtracker/unit/AssistantConversationMemoryTest.java b/src/test/java/com/jobtracker/unit/AssistantConversationMemoryTest.java index be50c7e..21e4573 100644 --- a/src/test/java/com/jobtracker/unit/AssistantConversationMemoryTest.java +++ b/src/test/java/com/jobtracker/unit/AssistantConversationMemoryTest.java @@ -13,6 +13,7 @@ import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.model.Generation; import org.springframework.ai.chat.prompt.Prompt; @@ -138,6 +139,7 @@ void systemPromptPreservesRelevantFiltersForFollowUps() throws Exception { private ChatModel recordingModel(List prompts) { ChatModel model = mock(ChatModel.class); + when(model.getOptions()).thenReturn(ChatOptions.builder().build()); when(model.stream(any(Prompt.class))).thenAnswer(invocation -> { Prompt prompt = invocation.getArgument(0); prompts.add(prompt); diff --git a/src/test/java/com/jobtracker/unit/mcp/McpApplicationToolsTest.java b/src/test/java/com/jobtracker/unit/mcp/McpApplicationToolsTest.java index 1ad98c8..65d31c4 100644 --- a/src/test/java/com/jobtracker/unit/mcp/McpApplicationToolsTest.java +++ b/src/test/java/com/jobtracker/unit/mcp/McpApplicationToolsTest.java @@ -16,8 +16,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springaicommunity.mcp.annotation.McpTool; -import org.springaicommunity.mcp.annotation.McpToolParam; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.ai.mcp.annotation.McpToolParam; import java.lang.reflect.Method; import java.lang.reflect.Parameter; diff --git a/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectProxyTest.java b/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectProxyTest.java index c3781f4..ffdb945 100644 --- a/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectProxyTest.java +++ b/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectProxyTest.java @@ -1,6 +1,6 @@ package com.jobtracker.unit.mcp; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.mcp.audit.AuditMcpOperation; import com.jobtracker.mcp.audit.McpAuditAspect; import com.jobtracker.service.McpAuditService; diff --git a/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectTest.java b/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectTest.java index acf1fa6..a542a94 100644 --- a/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectTest.java +++ b/src/test/java/com/jobtracker/unit/mcp/McpAuditAspectTest.java @@ -1,6 +1,6 @@ package com.jobtracker.unit.mcp; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.mcp.audit.AuditMcpOperation; import com.jobtracker.mcp.audit.McpAuditAspect; import com.jobtracker.service.McpAuditService; @@ -16,7 +16,7 @@ import org.aspectj.lang.reflect.MethodSignature; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import java.lang.reflect.Method; diff --git a/src/test/java/com/jobtracker/unit/mcp/McpDashboardToolsTest.java b/src/test/java/com/jobtracker/unit/mcp/McpDashboardToolsTest.java index d1fbd9a..28338ef 100644 --- a/src/test/java/com/jobtracker/unit/mcp/McpDashboardToolsTest.java +++ b/src/test/java/com/jobtracker/unit/mcp/McpDashboardToolsTest.java @@ -1,6 +1,6 @@ package com.jobtracker.unit.mcp; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.dashboard.DashboardSummaryResponse; import com.jobtracker.dto.gamification.AchievementResponse; import com.jobtracker.dto.gamification.GamificationProfileResponse; @@ -50,7 +50,7 @@ class McpDashboardToolsTest { @BeforeEach void setUp() { - objectMapper = new ObjectMapper().findAndRegisterModules(); + objectMapper = new ObjectMapper(); resources = new McpReadOnlySnapshotResources( dashboardService, gamificationService, diff --git a/src/test/java/com/jobtracker/unit/mcp/McpGamificationToolsTest.java b/src/test/java/com/jobtracker/unit/mcp/McpGamificationToolsTest.java index 8352ae8..8ee84f7 100644 --- a/src/test/java/com/jobtracker/unit/mcp/McpGamificationToolsTest.java +++ b/src/test/java/com/jobtracker/unit/mcp/McpGamificationToolsTest.java @@ -13,7 +13,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springaicommunity.mcp.context.McpSyncRequestContext; +import org.springframework.ai.mcp.annotation.context.McpSyncRequestContext; import java.util.ArrayList; import java.util.List; @@ -110,7 +110,7 @@ void applyGamificationEvent_emitsProgressNotificationsViaContext() { }).when(gamificationService).applyEventWithProgress(any(), any()); doAnswer(inv -> { - Consumer specConsumer = inv.getArgument(0); + Consumer specConsumer = inv.getArgument(0); // record the message by using a recording spec capturedMessages.add("step"); return null; diff --git a/src/test/java/com/jobtracker/unit/mcp/McpProfileToolsTest.java b/src/test/java/com/jobtracker/unit/mcp/McpProfileToolsTest.java index 6d8dfd8..7389be7 100644 --- a/src/test/java/com/jobtracker/unit/mcp/McpProfileToolsTest.java +++ b/src/test/java/com/jobtracker/unit/mcp/McpProfileToolsTest.java @@ -1,6 +1,6 @@ package com.jobtracker.unit.mcp; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import com.jobtracker.dto.auth.UserResponse; import com.jobtracker.entity.User; import com.jobtracker.mapper.AuthMapper; @@ -47,7 +47,7 @@ class McpProfileToolsTest { @BeforeEach void setUp() { - objectMapper = new ObjectMapper().findAndRegisterModules(); + objectMapper = new ObjectMapper(); resources = new McpReadOnlySnapshotResources( dashboardService, gamificationService, diff --git a/src/test/java/com/jobtracker/unit/mcp/McpPromptsConfigTest.java b/src/test/java/com/jobtracker/unit/mcp/McpPromptsConfigTest.java index 68195c5..34746a4 100644 --- a/src/test/java/com/jobtracker/unit/mcp/McpPromptsConfigTest.java +++ b/src/test/java/com/jobtracker/unit/mcp/McpPromptsConfigTest.java @@ -4,8 +4,8 @@ import io.modelcontextprotocol.spec.McpSchema.GetPromptResult; import io.modelcontextprotocol.spec.McpSchema.TextContent; import org.junit.jupiter.api.Test; -import org.springaicommunity.mcp.annotation.McpComplete; -import org.springaicommunity.mcp.annotation.McpPrompt; +import org.springframework.ai.mcp.annotation.McpComplete; +import org.springframework.ai.mcp.annotation.McpPrompt; import java.lang.reflect.Method; import java.util.Set;