Skip to content

Commit 992a428

Browse files
authored
Migrate to Jackson mapper builder pattern (#3269)
Mappers and factories are fully immutable objects in Jackson 3. This change is rather a no-op, but migrates the code to use the builder-pattern. This is only a little building-block for "real" Jackson 3 support, there's more to do and more that's required from other frameworks.
1 parent d4bd5d6 commit 992a428

File tree

33 files changed

+143
-72
lines changed

33 files changed

+143
-72
lines changed

api/management-model/src/test/java/org/apache/polaris/core/admin/model/CatalogSerializationTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import com.fasterxml.jackson.core.JsonProcessingException;
2424
import com.fasterxml.jackson.databind.ObjectMapper;
25+
import com.fasterxml.jackson.databind.json.JsonMapper;
2526
import java.util.stream.Stream;
2627
import org.junit.jupiter.api.BeforeEach;
2728
import org.junit.jupiter.api.Test;
@@ -39,7 +40,7 @@ public class CatalogSerializationTest {
3940

4041
@BeforeEach
4142
public void setUp() {
42-
mapper = new ObjectMapper();
43+
mapper = JsonMapper.builder().build();
4344
}
4445

4546
@ParameterizedTest(name = "{0}")

extensions/auth/opa/impl/src/jsonSchemaGenerator/java/org/apache/polaris/extension/auth/opa/model/OpaSchemaGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.fasterxml.jackson.databind.ObjectMapper;
2222
import com.fasterxml.jackson.databind.SerializationFeature;
23+
import com.fasterxml.jackson.databind.json.JsonMapper;
2324
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
2425
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;
2526
import java.io.IOException;
@@ -44,8 +45,7 @@ public class OpaSchemaGenerator {
4445
* @throws IOException if schema generation fails
4546
*/
4647
public static String generateSchema() throws IOException {
47-
ObjectMapper mapper = new ObjectMapper();
48-
mapper.enable(SerializationFeature.INDENT_OUTPUT);
48+
ObjectMapper mapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
4949

5050
JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
5151
JsonSchema schema = schemaGen.generateSchema(OpaAuthorizationInput.class);

extensions/auth/opa/impl/src/main/java/org/apache/polaris/extension/auth/opa/OpaPolarisAuthorizerFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.polaris.extension.auth.opa;
2020

2121
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import com.fasterxml.jackson.databind.json.JsonMapper;
2223
import io.smallrye.common.annotation.Identifier;
2324
import jakarta.annotation.PostConstruct;
2425
import jakarta.annotation.PreDestroy;
@@ -60,7 +61,7 @@ public OpaPolarisAuthorizerFactory(
6061
this.opaConfig = opaConfig;
6162
this.clock = clock;
6263
this.asyncExec = asyncExec;
63-
this.objectMapper = new ObjectMapper();
64+
this.objectMapper = JsonMapper.builder().build();
6465
}
6566

6667
/**

extensions/auth/opa/impl/src/test/java/org/apache/polaris/extension/auth/opa/OpaPolarisAuthorizerTest.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import com.fasterxml.jackson.databind.JsonNode;
2626
import com.fasterxml.jackson.databind.ObjectMapper;
27+
import com.fasterxml.jackson.databind.json.JsonMapper;
2728
import com.sun.net.httpserver.HttpExchange;
2829
import com.sun.net.httpserver.HttpHandler;
2930
import com.sun.net.httpserver.HttpServer;
@@ -75,7 +76,7 @@ void testOpaInputJsonFormat() throws Exception {
7576
"http://localhost:" + server.getAddress().getPort() + "/v1/data/polaris/allow");
7677
OpaPolarisAuthorizer authorizer =
7778
new OpaPolarisAuthorizer(
78-
policyUri, HttpClients.createDefault(), new ObjectMapper(), null);
79+
policyUri, HttpClients.createDefault(), JsonMapper.builder().build(), null);
7980

8081
PolarisPrincipal principal =
8182
PolarisPrincipal.of("eve", Map.of("department", "finance"), Set.of("auditor"));
@@ -95,7 +96,7 @@ void testOpaInputJsonFormat() throws Exception {
9596
secondary));
9697

9798
// Parse and verify JSON structure from captured request
98-
ObjectMapper mapper = new ObjectMapper();
99+
ObjectMapper mapper = JsonMapper.builder().build();
99100
JsonNode root = mapper.readTree(capturedRequestBody[0]);
100101
assertThat(root.has("input")).as("Root should have 'input' field").isTrue();
101102
var input = root.get("input");
@@ -120,7 +121,7 @@ void testOpaRequestJsonWithHierarchicalResource() throws Exception {
120121
"http://localhost:" + server.getAddress().getPort() + "/v1/data/polaris/allow");
121122
OpaPolarisAuthorizer authorizer =
122123
new OpaPolarisAuthorizer(
123-
policyUri, HttpClients.createDefault(), new ObjectMapper(), null);
124+
policyUri, HttpClients.createDefault(), JsonMapper.builder().build(), null);
124125

125126
// Set up a realistic principal
126127
PolarisPrincipal principal =
@@ -185,7 +186,7 @@ void testOpaRequestJsonWithHierarchicalResource() throws Exception {
185186
null));
186187

187188
// Parse and verify the complete JSON structure
188-
ObjectMapper mapper = new ObjectMapper();
189+
ObjectMapper mapper = JsonMapper.builder().build();
189190
JsonNode root = mapper.readTree(capturedRequestBody[0]);
190191

191192
// Verify top-level structure
@@ -273,7 +274,7 @@ void testOpaRequestJsonWithMultiLevelNamespace() throws Exception {
273274
"http://localhost:" + server.getAddress().getPort() + "/v1/data/polaris/allow");
274275
OpaPolarisAuthorizer authorizer =
275276
new OpaPolarisAuthorizer(
276-
policyUri, HttpClients.createDefault(), new ObjectMapper(), null);
277+
policyUri, HttpClients.createDefault(), JsonMapper.builder().build(), null);
277278

278279
// Set up a realistic principal
279280
PolarisPrincipal principal =
@@ -350,7 +351,7 @@ void testOpaRequestJsonWithMultiLevelNamespace() throws Exception {
350351
null));
351352

352353
// Parse and verify the complete JSON structure
353-
ObjectMapper mapper = new ObjectMapper();
354+
ObjectMapper mapper = JsonMapper.builder().build();
354355
JsonNode root = mapper.readTree(capturedRequestBody[0]);
355356

356357
// Verify top-level structure
@@ -437,7 +438,7 @@ void testAuthorizeOrThrowWithEmptyTargetsAndSecondaries() throws Exception {
437438
"http://localhost:" + server.getAddress().getPort() + "/v1/data/polaris/allow");
438439
OpaPolarisAuthorizer authorizer =
439440
new OpaPolarisAuthorizer(
440-
policyUri, HttpClients.createDefault(), new ObjectMapper(), null);
441+
policyUri, HttpClients.createDefault(), JsonMapper.builder().build(), null);
441442

442443
PolarisPrincipal principal = PolarisPrincipal.of("alice", Map.of(), Set.of("admin"));
443444

@@ -483,7 +484,7 @@ public void testCreateWithHttpsAndBearerToken() {
483484
URI policyUri = URI.create("http://opa.example.com:8181/v1/data/polaris/allow");
484485
OpaPolarisAuthorizer authorizer =
485486
new OpaPolarisAuthorizer(
486-
policyUri, HttpClients.createDefault(), new ObjectMapper(), tokenProvider);
487+
policyUri, HttpClients.createDefault(), JsonMapper.builder().build(), tokenProvider);
487488

488489
assertThat(authorizer).isNotNull();
489490
}
@@ -499,7 +500,10 @@ public void testBearerTokenIsAddedToHttpRequest() {
499500
BearerTokenProvider tokenProvider = new StaticBearerTokenProvider("test-bearer-token");
500501
OpaPolarisAuthorizer authorizer =
501502
new OpaPolarisAuthorizer(
502-
policyUri, mock(CloseableHttpClient.class), new ObjectMapper(), tokenProvider) {
503+
policyUri,
504+
mock(CloseableHttpClient.class),
505+
JsonMapper.builder().build(),
506+
tokenProvider) {
503507
@Override
504508
<T> T httpClientExecute(
505509
ClassicHttpRequest request, HttpClientResponseHandler<? extends T> responseHandler)
@@ -541,7 +545,10 @@ public void testBearerTokenFromBearerTokenProvider() {
541545
// Create authorizer with the token provider instead of static token
542546
OpaPolarisAuthorizer authorizer =
543547
new OpaPolarisAuthorizer(
544-
policyUri, mock(CloseableHttpClient.class), new ObjectMapper(), tokenProvider) {
548+
policyUri,
549+
mock(CloseableHttpClient.class),
550+
JsonMapper.builder().build(),
551+
tokenProvider) {
545552
@Override
546553
<T> T httpClientExecute(
547554
ClassicHttpRequest request, HttpClientResponseHandler<? extends T> responseHandler)

extensions/auth/opa/impl/src/test/java/org/apache/polaris/extension/auth/opa/token/FileBearerTokenProviderTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2424

2525
import com.fasterxml.jackson.databind.ObjectMapper;
26+
import com.fasterxml.jackson.databind.json.JsonMapper;
2627
import java.io.IOException;
2728
import java.nio.charset.StandardCharsets;
2829
import java.nio.file.Files;
@@ -401,7 +402,7 @@ public void testJwtWithoutExpirationClaim() throws IOException {
401402
/** Helper method to create a JWT with a specific expiration time. */
402403
private String createJwtWithExpiration(Instant expiration) {
403404
try {
404-
ObjectMapper mapper = new ObjectMapper();
405+
ObjectMapper mapper = JsonMapper.builder().build();
405406

406407
// Create header
407408
Map<String, Object> header = new HashMap<>();
@@ -438,7 +439,7 @@ private String createJwtWithExpiration(Instant expiration) {
438439
/** Helper method to create a JWT without an expiration claim. */
439440
private String createJwtWithoutExpiration() {
440441
try {
441-
ObjectMapper mapper = new ObjectMapper();
442+
ObjectMapper mapper = JsonMapper.builder().build();
442443

443444
// Create header
444445
Map<String, Object> header = new HashMap<>();

integration-tests/src/main/java/org/apache/polaris/service/it/env/PolarisClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.fasterxml.jackson.databind.DeserializationFeature;
2626
import com.fasterxml.jackson.databind.ObjectMapper;
2727
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
28+
import com.fasterxml.jackson.databind.json.JsonMapper;
2829
import jakarta.ws.rs.client.Client;
2930
import java.net.URI;
3031
import java.util.Map;
@@ -64,7 +65,7 @@ public static PolarisClient polarisClient(PolarisApiEndpoints endpoints) {
6465
* ObjectMapper} if the make custom {@link PolarisServerManager#createClient() clients}.
6566
*/
6667
public static ObjectMapper buildObjectMapper() {
67-
ObjectMapper mapper = new ObjectMapper();
68+
ObjectMapper mapper = JsonMapper.builder().build();
6869
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
6970
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
7071
mapper.setPropertyNamingStrategy(new PropertyNamingStrategies.KebabCaseStrategy());

integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisManagementServiceIntegrationTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.auth0.jwt.algorithms.Algorithm;
3030
import com.fasterxml.jackson.databind.JsonNode;
3131
import com.fasterxml.jackson.databind.ObjectMapper;
32+
import com.fasterxml.jackson.databind.json.JsonMapper;
3233
import com.fasterxml.jackson.databind.node.ObjectNode;
3334
import com.google.common.collect.ImmutableMap;
3435
import jakarta.ws.rs.client.Entity;
@@ -159,7 +160,7 @@ public void testCatalogSerializing() throws IOException {
159160
.build())
160161
.build();
161162

162-
ObjectMapper mapper = new ObjectMapper();
163+
ObjectMapper mapper = JsonMapper.builder().build();
163164
String json = mapper.writeValueAsString(catalog);
164165
System.out.println(json);
165166
Catalog deserialized = mapper.readValue(json, Catalog.class);
@@ -334,7 +335,7 @@ public void testCreateCatalogWithNullBaseLocation() {
334335
.setStorageType(StorageConfigInfo.StorageTypeEnum.S3)
335336
.setAllowedLocations(List.of("s3://my-old-bucket/path/to/data"))
336337
.build();
337-
ObjectMapper mapper = new ObjectMapper();
338+
ObjectMapper mapper = JsonMapper.builder().build();
338339
JsonNode storageConfig = mapper.valueToTree(awsConfigModel);
339340
ObjectNode catalogNode = mapper.createObjectNode();
340341
catalogNode.set("storageConfigInfo", storageConfig);
@@ -359,7 +360,7 @@ public void testCreateCatalogWithoutProperties() {
359360
.setStorageType(StorageConfigInfo.StorageTypeEnum.S3)
360361
.setAllowedLocations(List.of("s3://my-old-bucket/path/to/data"))
361362
.build();
362-
ObjectMapper mapper = new ObjectMapper();
363+
ObjectMapper mapper = JsonMapper.builder().build();
363364
JsonNode storageConfig = mapper.valueToTree(awsConfigModel);
364365
ObjectNode catalogNode = mapper.createObjectNode();
365366
catalogNode.set("storageConfigInfo", storageConfig);
@@ -513,7 +514,7 @@ public void testCreateCatalogWithoutDefaultLocation() {
513514
.setStorageType(StorageConfigInfo.StorageTypeEnum.S3)
514515
.setAllowedLocations(List.of("s3://my-old-bucket/path/to/data"))
515516
.build();
516-
ObjectMapper mapper = new ObjectMapper();
517+
ObjectMapper mapper = JsonMapper.builder().build();
517518
JsonNode storageConfig = mapper.valueToTree(awsConfigModel);
518519
ObjectNode catalogNode = mapper.createObjectNode();
519520
catalogNode.set("storageConfigInfo", storageConfig);
@@ -534,7 +535,7 @@ public void testCreateCatalogWithoutDefaultLocation() {
534535
@Test
535536
public void serialization() {
536537
CatalogProperties properties = new CatalogProperties("s3://my-bucket/path/to/data");
537-
ObjectMapper mapper = new ObjectMapper();
538+
ObjectMapper mapper = JsonMapper.builder().build();
538539
CatalogProperties translated = mapper.convertValue(properties, CatalogProperties.class);
539540
assertThat(translated.toMap())
540541
.containsEntry("default-base-location", "s3://my-bucket/path/to/data");

persistence/nosql/authz/impl/src/test/java/org/apache/polaris/persistence/nosql/authz/impl/TestAclEntryImpl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
*/
1919
package org.apache.polaris.persistence.nosql.authz.impl;
2020

21+
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
22+
import static com.fasterxml.jackson.databind.MapperFeature.DEFAULT_VIEW_INCLUSION;
23+
2124
import com.fasterxml.jackson.databind.ObjectMapper;
25+
import com.fasterxml.jackson.databind.json.JsonMapper;
2226
import java.util.stream.Stream;
2327
import org.apache.polaris.persistence.nosql.authz.api.AclEntry;
2428
import org.apache.polaris.persistence.nosql.authz.api.Privilege;
@@ -39,7 +43,12 @@ public class TestAclEntryImpl {
3943

4044
@BeforeAll
4145
static void setUp() {
42-
mapper = new ObjectMapper().findAndRegisterModules();
46+
mapper =
47+
JsonMapper.builder()
48+
.findAndAddModules()
49+
.disable(FAIL_ON_UNKNOWN_PROPERTIES)
50+
.enable(DEFAULT_VIEW_INCLUSION)
51+
.build();
4352
privileges =
4453
new PrivilegesImpl(Stream.of(new PrivilegesTestProvider()), new PrivilegesTestRepository());
4554
JacksonPrivilegesModule.CDIResolver.setResolver(x -> privileges);

persistence/nosql/authz/impl/src/test/java/org/apache/polaris/persistence/nosql/authz/impl/TestAclImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.polaris.persistence.nosql.authz.impl;
2020

2121
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import com.fasterxml.jackson.databind.json.JsonMapper;
2223
import java.util.stream.Stream;
2324
import org.apache.polaris.persistence.nosql.authz.api.Acl;
2425
import org.apache.polaris.persistence.nosql.authz.api.Privilege;
@@ -41,7 +42,7 @@ public class TestAclImpl {
4142

4243
@BeforeAll
4344
static void setUp() {
44-
mapper = new ObjectMapper().findAndRegisterModules();
45+
mapper = JsonMapper.builder().findAndAddModules().build();
4546
privileges =
4647
new PrivilegesImpl(Stream.of(new PrivilegesTestProvider()), new PrivilegesTestRepository());
4748
JacksonPrivilegesModule.CDIResolver.setResolver(x -> privileges);

persistence/nosql/authz/impl/src/test/java/org/apache/polaris/persistence/nosql/authz/impl/TestPrivilegeSetImpl.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
*/
1919
package org.apache.polaris.persistence.nosql.authz.impl;
2020

21+
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
22+
import static com.fasterxml.jackson.databind.MapperFeature.DEFAULT_VIEW_INCLUSION;
2123
import static java.util.Collections.singleton;
2224
import static org.junit.jupiter.params.provider.Arguments.arguments;
2325

2426
import com.fasterxml.jackson.databind.JsonNode;
2527
import com.fasterxml.jackson.databind.ObjectMapper;
28+
import com.fasterxml.jackson.databind.json.JsonMapper;
2629
import com.fasterxml.jackson.databind.node.ArrayNode;
2730
import java.util.ArrayList;
2831
import java.util.Set;
@@ -54,7 +57,12 @@ static final class StorageView {}
5457

5558
@BeforeAll
5659
static void setUp() {
57-
mapper = new ObjectMapper().findAndRegisterModules();
60+
mapper =
61+
JsonMapper.builder()
62+
.findAndAddModules()
63+
.disable(FAIL_ON_UNKNOWN_PROPERTIES)
64+
.enable(DEFAULT_VIEW_INCLUSION)
65+
.build();
5866
privileges =
5967
new PrivilegesImpl(Stream.of(new PrivilegesTestProvider()), new PrivilegesTestRepository());
6068
JacksonPrivilegesModule.CDIResolver.setResolver(x -> privileges);

0 commit comments

Comments
 (0)