Expose ObjectMapper used by JsonSerializer (#1132)

Closes #1130.

Co-authored-by: mikereiche <michael.reiche@couchbase.com>
This commit is contained in:
Michael Reiche
2021-05-05 15:16:38 -04:00
committed by mikereiche
parent e7553fc3a2
commit 0930e5b5fe
3 changed files with 56 additions and 10 deletions

View File

@@ -16,12 +16,13 @@
package org.springframework.data.couchbase.config;
import static com.couchbase.client.java.ClusterOptions.*;
import static com.couchbase.client.java.ClusterOptions.clusterOptions;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
@@ -48,11 +49,19 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.DeserializationFeature;
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.Module;
import com.couchbase.client.core.encryption.CryptoManager;
import com.couchbase.client.core.env.Authenticator;
import com.couchbase.client.core.env.PasswordAuthenticator;
import com.couchbase.client.core.error.CouchbaseException;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.codec.JacksonJsonSerializer;
import com.couchbase.client.java.encryption.databind.jackson.EncryptionModule;
import com.couchbase.client.java.env.ClusterEnvironment;
import com.couchbase.client.java.json.JacksonTransformers;
import com.couchbase.client.java.json.JsonValueModule;
import com.couchbase.client.java.json.RepackagedJsonValueModule;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Base class for Spring Data Couchbase configuration using JavaConfig.
@@ -65,12 +74,13 @@ import com.couchbase.client.java.json.JacksonTransformers;
@Configuration
public abstract class AbstractCouchbaseConfiguration {
@Autowired ObjectMapper couchbaseObjectMapper;
/**
* The connection string which allows the SDK to connect to the cluster.
* <p>
* Note that the connection string can take many forms, in its simplest it is just a single hostname
* like "127.0.0.1". Please refer to the couchbase Java SDK documentation for all the different
* possibilities and options.
* Note that the connection string can take many forms, in its simplest it is just a single hostname like "127.0.0.1".
* Please refer to the couchbase Java SDK documentation for all the different possibilities and options.
*/
public abstract String getConnectionString();
@@ -130,6 +140,10 @@ public abstract class AbstractCouchbaseConfiguration {
@Bean(destroyMethod = "shutdown")
public ClusterEnvironment couchbaseClusterEnvironment() {
ClusterEnvironment.Builder builder = ClusterEnvironment.builder();
if (!nonShadowedJacksonPresent()) {
throw new CouchbaseException("non-shadowed Jackson not present");
}
builder.jsonSerializer(JacksonJsonSerializer.create(couchbaseObjectMapper));
configureEnvironment(builder);
return builder.build();
}
@@ -273,6 +287,25 @@ public abstract class AbstractCouchbaseConfiguration {
return mappingContext;
}
/**
* Creates a {@link ObjectMapper} for the jsonSerializer of the ClusterEnvironment
*
* @throws Exception on Bean construction failure.
* @return ObjectMapper
*/
@Bean
public ObjectMapper couchbaseObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.registerModule(new JsonValueModule());
CryptoManager cryptoManager = null;
if (cryptoManager != null) {
mapper.registerModule(new EncryptionModule(cryptoManager));
}
return mapper;
}
/**
* Configure whether to automatically create indices for domain types by deriving the from the entity or not.
*/
@@ -327,4 +360,14 @@ public abstract class AbstractCouchbaseConfiguration {
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
: PropertyNameFieldNamingStrategy.INSTANCE;
}
private boolean nonShadowedJacksonPresent() {
try {
JacksonJsonSerializer.preflightCheck();
return true;
} catch (Throwable t) {
return false;
}
}
}

View File

@@ -184,6 +184,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
vie = new Airport("airports::vie", "vie", "loww");
vie = airportRepository.save(vie);
List<Airport> airports = couchbaseTemplate.findByQuery(Airport.class)
.withConsistency(QueryScanConsistency.REQUEST_PLUS)
.matching(new Query(QueryCriteria.where(N1QLExpression.x("_class")).is("airport"))).all();
assertFalse(airports.isEmpty(), "should have found aiport");
} finally {

View File

@@ -16,11 +16,13 @@
package org.springframework.data.couchbase.repository;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -64,13 +66,13 @@ public class ReactiveCouchbaseRepositoryKeyValueIntegrationTests extends Cluster
}
@Test
void findBySimplePropertyAudited() {
void findByIdAudited() {
Airport vie = null;
try {
vie = new Airport("airports::vie", "vie", "low2");
Airport saved = airportRepository.save(vie).block();
List<Airport> airports1 = airportRepository.findAllByIata("vie").collectList().block();
assertEquals(saved, airports1.get(0));
Airport airport1 = airportRepository.findById(saved.getId()).block();
assertEquals(airport1, saved);
assertEquals(saved.getCreatedBy(), "auditor"); // NaiveAuditorAware will provide this
} finally {
airportRepository.delete(vie).block();
@@ -79,7 +81,7 @@ public class ReactiveCouchbaseRepositoryKeyValueIntegrationTests extends Cluster
@Configuration
@EnableReactiveCouchbaseRepositories("org.springframework.data.couchbase")
@EnableReactiveCouchbaseAuditing
@EnableReactiveCouchbaseAuditing
static class Config extends AbstractCouchbaseConfiguration {
@Override