Skip to content

Upgrade sdk/spring to Jackson 3 to align with Spring Boot 4#49550

Open
rujche wants to merge 10 commits into
mainfrom
rujche/main/upgrade-jackson-major-version
Open

Upgrade sdk/spring to Jackson 3 to align with Spring Boot 4#49550
rujche wants to merge 10 commits into
mainfrom
rujche/main/upgrade-jackson-major-version

Conversation

@rujche

@rujche rujche commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

Migrate Jackson 2 (com.fasterxml.jackson.databind/com.fasterxml.jackson.core) to Jackson 3 (tools.jackson) across 10 sdk/spring modules to align with Spring Boot 4.

Changes

  • Swapped com.fasterxml.jackson.core:jackson-databind dependency (and Maven enforcer <includes> allowlist entries) to tools.jackson.core:jackson-databind:3.1.4 in affected POMs.
  • Migrated source/test code: com.fasterxml.jackson.databind.* -> tools.jackson.databind.*, com.fasterxml.jackson.core.* -> tools.jackson.core.*; new ObjectMapper() -> JsonMapper.builder().build(); asText()/isTextual()/textValue() -> asString()/isString()/stringValue(); checked Jackson exceptions -> unchecked tools.jackson.core.JacksonException; JsonDeserializer -> ValueDeserializer; setMixInAnnotations -> setMixIn.
  • Simplified Spring Security OAuth2 serialization support in spring-cloud-azure-autoconfigure: removed the now-redundant custom AadOAuth2ClientJacksonModule / AadClientRegistration* helpers after validating upstream Jackson 3 Spring Security support; retained OAuth2ClientJacksonModule as the required module for the OAuth2AuthorizedClient serialization path.
  • spring-boot-jackson (Jackson 3 autoconfig) added alongside the retained spring-boot-jackson2 compat module.
  • Jackson 2 annotations (com.fasterxml.jackson.annotation.*) are intentionally retained (unchanged in Jackson 3).
  • Added explicit jackson-annotations alignment where needed to avoid test classpath conflicts (2.18.7 vs 2.21) causing NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonSerializeAs.
  • Added RevApi allowlist entry for intentional beta API break: TargetingFilter.OBJECT_MAPPER field type change (com.fasterxml.jackson.databind.ObjectMapper -> tools.jackson.databind.ObjectMapper).
  • Tightened messaging auto-config tests to use explicit, behavior-aligned assertions and clarified method names.
  • Updated sdk/spring/CHANGELOG.md for all 10 affected modules.

Out of scope

Cosmos (azure-spring-data-cosmos and the Spring Cloud Azure Cosmos starter) is not migrated to Jackson 3 in this PR. It cannot be migrated in isolation because:

  • azure-spring-data-cosmos depends on azure-cosmos, and azure-cosmos exposes Jackson 2 types (e.g. com.fasterxml.jackson.databind.JsonNode in CosmosItemSerializer, CosmosItemResponse, and most com.azure.cosmos.models.* classes) as part of its public API. About 65 public classes import com.fasterxml.jackson.
  • Because JsonNode is part of the public contract, moving azure-cosmos to Jackson 3 is a breaking API change that cascades to every dependent module under sdk/cosmos (azure-cosmos-encryption, azure-cosmos-spark_3 and variants, azure-cosmos-kafka-connect, azure-cosmos-benchmark, azure-cosmos-tests, ...) — roughly 440+ source files reference Jackson 2 across the tree.
  • azure-cosmos is a GA data-plane library, so such a breaking change requires separate API review and a coordinated, multi-module effort.

This follow-up work is tracked in #49551.

Verification

  • Affected modules build and unit tests pass; no banned-dependency enforcer failures.
  • Targeted regression tests pass for spring-cloud-azure-autoconfigure messaging auto-config suites (storage queue / service bus / event hubs).
  • Focused serializer regression tests pass for SerializerUtilsTests and JacksonHttpSessionOAuth2AuthorizedClientRepositoryTest, including the cleanup that removed the custom Aad Jackson helper classes and CoreJacksonModule.

Resolves #49538

Migrate Jackson 2 (com.fasterxml.jackson.databind/core) to Jackson 3 (tools.jackson) across 10 sdk/spring modules: poms, source, and tests. Jackson 2 annotations are intentionally retained. Cosmos is out of scope.
Copilot AI review requested due to automatic review settings June 18, 2026 07:24
@github-actions github-actions Bot added the azure-spring All azure-spring related issues label Jun 18, 2026
@rujche rujche self-assigned this Jun 18, 2026
@rujche rujche moved this to In Progress in Spring Cloud Azure Jun 18, 2026
@rujche rujche added this to the 2026-07 milestone Jun 18, 2026
Drop springboot4_com.fasterxml.jackson.core:jackson-databind and springboot4_tools.jackson.core:jackson-core, which are no longer referenced after the Jackson 3 migration.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the Spring libraries under sdk/spring from Jackson 2 (com.fasterxml.jackson.*) to Jackson 3 (tools.jackson.*) to align with the Spring Boot 4 dependency stack and avoid Jackson 2/3 classpath conflicts (per #49538).

Changes:

  • Updated multiple Spring module POMs to depend on tools.jackson.core:jackson-databind:3.1.4 (and updated related enforcer rules / version pins).
  • Migrated production and test code imports and APIs from com.fasterxml.jackson.* to tools.jackson.* (including JSON node string APIs and exception types).
  • Updated Spring Boot auto-configuration tests to use Jackson 3 auto-config (JacksonAutoConfiguration) and JsonMapper-based mapper creation where needed.

Reviewed changes

Copilot reviewed 45 out of 45 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
sdk/spring/spring-messaging-azure/src/main/java/com/azure/spring/messaging/implementation/converter/ObjectMapperHolder.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-messaging-azure/src/main/java/com/azure/spring/messaging/implementation/converter/AbstractJacksonAzureMessageConverter.java Updates Jackson exception/import usage to Jackson 3 types.
sdk/spring/spring-messaging-azure/pom.xml Replaces Jackson 2 databind dependency/enforcer entry with Jackson 3 coordinates.
sdk/spring/spring-messaging-azure-storage-queue/src/main/java/com/azure/spring/messaging/storage/queue/implementation/support/converter/StorageQueueMessageConverter.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-messaging-azure-servicebus/src/main/java/com/azure/spring/messaging/servicebus/implementation/support/converter/ServiceBusMessageConverter.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-messaging-azure-eventhubs/src/test/java/com/azure/spring/messaging/eventhubs/implementation/support/converter/EventHubsBatchMessageConverterTests.java Migrates test imports/exceptions to Jackson 3.
sdk/spring/spring-messaging-azure-eventhubs/src/main/java/com/azure/spring/messaging/eventhubs/implementation/support/converter/EventHubsMessageConverter.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-messaging-azure-eventhubs/src/main/java/com/azure/spring/messaging/eventhubs/implementation/support/converter/EventHubsBatchMessageConverter.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-feature-management/src/main/java/com/azure/spring/cloud/feature/management/implementation/FeatureManagementProperties.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-feature-management/src/main/java/com/azure/spring/cloud/feature/management/filters/TimeWindowFilter.java Migrates mapper/node APIs and adds Jackson 3 databind exception handling.
sdk/spring/spring-cloud-azure-feature-management/src/main/java/com/azure/spring/cloud/feature/management/filters/TargetingFilter.java Switches Jackson imports to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-feature-management/pom.xml Replaces Jackson 2 databind dependency/enforcer entry with Jackson 3 coordinates.
sdk/spring/spring-cloud-azure-docker-compose/pom.xml Replaces Jackson 2 databind dependency/enforcer entry with Jackson 3 coordinates.
sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/storage/AzureStorageQueueMessagingAutoConfigurationTests.java Moves tests to Jackson 3 auto-config and JsonMapper creation.
sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusMessagingAutoConfigurationTests.java Moves tests to Jackson 3 auto-config and JsonMapper creation.
sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfigurationTests.java Moves tests to Jackson 3 auto-config and JsonMapper creation.
sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/graph/GraphClientTest.java Updates JSON serialization in tests to use Jackson 3 JsonMapper.
sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/aad/filter/UserPrincipalMicrosoftGraphTests.java Migrates test Jackson imports/exceptions to Jackson 3.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/storage/queue/AzureStorageQueueMessagingAutoConfiguration.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusMessagingAutoConfiguration.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfiguration.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/utils/JacksonObjectMapperFactory.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/serde/jackson/StdConverters.java Migrates Jackson node/converter imports to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/serde/jackson/SerializerUtils.java Migrates Spring Security Jackson modules and mapper usage to Jackson 3.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/serde/jackson/JsonNodeUtils.java Updates JsonNode APIs and refactors value conversion to use DeserializationContext.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/serde/jackson/AadOAuth2ClientJacksonModule.java Replaces Jackson 2 module implementation with Jackson 3 module API usage.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/serde/jackson/AadClientRegistrationMixin.java Switches @JsonDeserialize annotation import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/serde/jackson/AadClientRegistrationDeserializer.java Migrates deserializer to Jackson 3 deserializer base type and parsing APIs.
sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/filter/AadGraphClient.java Switches ObjectMapper import to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-autoconfigure/pom.xml Adds Spring Boot Jackson 3 autoconfig artifact and Jackson 3 databind dependency/enforcer entry.
sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/TestUtils.java Updates test JSON node APIs and exception type to Jackson 3.
sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/JsonConfigurationParserTest.java Switches Jackson imports in tests to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceTest.java Removes Jackson 2 mapper usage in tests (imports/strategy).
sdk/spring/spring-cloud-azure-appconfiguration-config/src/test/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationApplicationSettingPropertySourceSnapshotTest.java Removes Jackson 2 mapper usage in tests (imports/strategy).
sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/JsonConfigurationParser.java Migrates JSON parsing/iteration APIs and exception types to Jackson 3.
sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/FeatureFlagClient.java Migrates JSON parsing APIs and exception types to Jackson 3.
sdk/spring/spring-cloud-azure-appconfiguration-config/src/main/java/com/azure/spring/cloud/appconfiguration/config/implementation/AppConfigurationFeatureManagementPropertySource.java Switches ObjectMapper/JsonMapper imports to Jackson 3 namespace.
sdk/spring/spring-cloud-azure-appconfiguration-config/pom.xml Adds Jackson 3 databind dependency and updates enforcer entry for Jackson 3.
sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/test/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationEndpointTest.java Migrates tests to Jackson 3 mapper/node types and removes checked Jackson 2 exceptions.
sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushrefresh/AppConfigurationRefreshEndpoint.java Migrates JsonNode import and string accessor API to Jackson 3.
sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/pushbusrefresh/AppConfigurationBusRefreshEndpoint.java Migrates JsonNode import and string accessor API to Jackson 3.
sdk/spring/spring-cloud-azure-appconfiguration-config-web/src/main/java/com/azure/spring/cloud/appconfiguration/config/web/implementation/AppConfigurationEndpoint.java Migrates to Jackson 3 JsonMapper and string accessor API updates.
sdk/spring/spring-cloud-azure-actuator-autoconfigure/pom.xml Replaces Jackson 2 databind dependency/enforcer entry with Jackson 3 coordinates.
sdk/spring/CHANGELOG.md Adds release notes entries for the Jackson 3 migration across affected Spring modules.
eng/versioning/external_dependencies.txt Adds Spring Boot 4 spring-boot-jackson and Jackson 3 dependency pins for version management.

…erterTests

JacksonException is unchecked in Jackson 3, so the throws clauses (and the now-unused import) are redundant. Addresses Copilot review feedback.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 45 out of 45 changed files in this pull request and generated no new comments.

@rujche

rujche commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

/azp run java - spring - tests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

…ebus

Exclude the Jackson 2.18 jackson-annotations brought transitively by the azure-core-serializer-json-jackson test dependency. It lacks com.fasterxml.jackson.annotation.JsonSerializeAs (required by tools.jackson.databind 3.x) and won dependency mediation on the test classpath, breaking ObjectMapperHolder/ServiceBusTemplate initialization. After exclusion, the Jackson 3-compatible jackson-annotations 2.21 from spring-messaging-azure is used.
@rujche rujche requested a review from Copilot June 18, 2026 08:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 46 out of 46 changed files in this pull request and generated no new comments.

The protected static OBJECT_MAPPER field type changed from com.fasterxml.jackson.databind.ObjectMapper to tools.jackson.databind.ObjectMapper as part of the Jackson 2->3 migration for Spring Boot 4. Add a RevApi difference allowlist entry with justification for this intentional breaking change.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated no new comments.

@rujche

rujche commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

/azp run java - spring - tests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated 6 comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated 3 comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated no new comments.

@rujche

rujche commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

/azp run java - spring - tests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@BeforeEach
public void init() {
session = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.KEBAB_CASE);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why removing this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This was removed because it had become dead test code in this class. The local MAPPER field and the KEBAB_CASE setup were no longer referenced by any assertion or test path after the Jackson 3 migration, so keeping them only added unused imports/state without affecting behavior.

// TODO(rujche) Delete this after OAuth2ClientJackson2Module support self-defined ClientRegistration type.
OBJECT_MAPPER.registerModule(new AadOAuth2ClientJackson2Module());
OBJECT_MAPPER.registerModule(new CoreJackson2Module());
OBJECT_MAPPER.registerModule(new JavaTimeModule());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why removing JavaTimeModule?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I verified this before keeping the removal. SerializerUtilsTests.serializeAndDeserializeTest() round-trips OAuth2AuthorizedClient, including the OAuth2AccessToken issuedAt and expiresAt Instant fields, and it passes without explicitly registering JavaTimeModule. In this mapper setup, the Spring Security Jackson modules cover the types we serialize here, so the extra module was redundant for this code path.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Follow-up after validating the full SerializerUtils path: I was also able to remove the now-redundant custom AadOAuth2ClientJacksonModule/AadClientRegistration* helpers, and then verified that CoreJacksonModule is not required for this code path either. OAuth2ClientJacksonModule remains required, but the serializer and session repository tests still pass after removing the custom helpers and CoreJacksonModule. Updated in 9c7f63c.

@@ -89,15 +89,17 @@ void connectionInfoAndCheckpointStoreProvidedShouldConfigure() {

@Test
@SuppressWarnings("removal")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please help confirm if this annotation is still needed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, the remaining @SuppressWarnings("removal") annotations in these messaging converter tests were stale Jackson 2 migration leftovers. I removed them in 7d92a42 and re-ran the targeted storage/servicebus/eventhubs auto-config tests successfully after the cleanup.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated 1 comment.

Comment on lines +15 to 17
private static final JsonMapper OBJECT_MAPPER;
private static final TypeReference<Map<String, OAuth2AuthorizedClient>> TYPE_REFERENCE = new TypeReference<>() { };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

azure-spring All azure-spring related issues

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Use Jackson 3 in Spring Cloud Azure 7.x to align with Spring Boot 4

3 participants