Make sure the Couchbase's Jackson module is available

When we customize Couchbase's JacksonJsonSerializer with the
auto-configured ObjectMapper, Couchbase's JsonValueModule is lost.
This prevents the storage and retrieval of JSON objects.

This commit updates the Couchbase auto-configuration to use a copy
of the auto-configured ObjectMapper with the JsonValueModule added
to it.

Fixes gh-26363
This commit is contained in:
Andy Wilkinson 2021-05-06 16:22:47 +01:00
parent cc702ede7e
commit b1f3d91f7d
3 changed files with 30 additions and 5 deletions

View File

@ -31,6 +31,7 @@ import com.couchbase.client.java.ClusterOptions;
import com.couchbase.client.java.codec.JacksonJsonSerializer;
import com.couchbase.client.java.env.ClusterEnvironment;
import com.couchbase.client.java.env.ClusterEnvironment.Builder;
import com.couchbase.client.java.json.JsonValueModule;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.ObjectProvider;
@ -128,7 +129,8 @@ public class CouchbaseAutoConfiguration {
@Bean
@ConditionalOnSingleCandidate(ObjectMapper.class)
ClusterEnvironmentBuilderCustomizer jacksonClusterEnvironmentBuilderCustomizer(ObjectMapper objectMapper) {
return new JacksonClusterEnvironmentBuilderCustomizer(objectMapper);
return new JacksonClusterEnvironmentBuilderCustomizer(
objectMapper.copy().registerModule(new JsonValueModule()));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,7 +22,10 @@ import com.couchbase.client.core.diagnostics.ClusterState;
import com.couchbase.client.core.diagnostics.DiagnosticsResult;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.Collection;
import com.couchbase.client.java.env.ClusterEnvironment;
import com.couchbase.client.java.json.JsonObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.testcontainers.couchbase.BucketDefinition;
import org.testcontainers.couchbase.CouchbaseContainer;
@ -69,4 +72,16 @@ class CouchbaseAutoConfigurationIntegrationTests {
});
}
@Test
void whenCouchbaseIsUsingCustomObjectMapperThenJsonCanBeRoundTripped() {
this.contextRunner.withBean(ObjectMapper.class, ObjectMapper::new).run((context) -> {
Cluster cluster = context.getBean(Cluster.class);
Bucket bucket = cluster.bucket(BUCKET_NAME);
bucket.waitUntilReady(Duration.ofMinutes(5));
Collection collection = bucket.defaultCollection();
collection.insert("test-document", JsonObject.create().put("a", "alpha"));
assertThat(collection.get("test-document").contentAsObject().get("a")).isEqualTo("alpha");
});
}
}

View File

@ -17,6 +17,8 @@
package org.springframework.boot.autoconfigure.couchbase;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import com.couchbase.client.core.env.IoConfig;
@ -26,7 +28,9 @@ import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.codec.JacksonJsonSerializer;
import com.couchbase.client.java.codec.JsonSerializer;
import com.couchbase.client.java.env.ClusterEnvironment;
import com.couchbase.client.java.json.JsonValueModule;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -66,14 +70,18 @@ class CouchbaseAutoConfigurationTests {
}
@Test
void environmentUseObjectMapperByDefault() {
void whenObjectMapperBeanIsDefinedThenClusterEnvironmentObjectMapperIsDerivedFromIt() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class))
.withPropertyValues("spring.couchbase.connection-string=localhost").run((context) -> {
ClusterEnvironment env = context.getBean(ClusterEnvironment.class);
Set<Object> expectedModuleIds = new HashSet<>(
context.getBean(ObjectMapper.class).getRegisteredModuleIds());
expectedModuleIds.add(new JsonValueModule().getTypeId());
JsonSerializer serializer = env.jsonSerializer();
assertThat(serializer).isInstanceOf(JacksonJsonSerializer.class)
.hasFieldOrPropertyWithValue("mapper", context.getBean(ObjectMapper.class));
assertThat(serializer).isInstanceOf(JacksonJsonSerializer.class).extracting("mapper")
.asInstanceOf(InstanceOfAssertFactories.type(ObjectMapper.class))
.extracting(ObjectMapper::getRegisteredModuleIds).isEqualTo(expectedModuleIds);
});
}