-
Notifications
You must be signed in to change notification settings - Fork 192
Expose ObjectMapper used by JsonSerializer #1132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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.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 @@ | |
@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 Cluster couchbaseCluster(ClusterEnvironment couchbaseClusterEnvironment) | |
@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)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use the couchbaseObjectMapper from the new Bean. |
||
configureEnvironment(builder); | ||
return builder.build(); | ||
} | ||
|
@@ -273,6 +287,25 @@ public CouchbaseMappingContext couchbaseMappingContext(CustomConversions customC | |
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; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the couchbaseObjectMapper that gets used and exposed. Created the same as in ClusterEnvironment.Builder. |
||
/** | ||
* Configure whether to automatically create indices for domain types by deriving the from the entity or not. | ||
*/ | ||
|
@@ -327,4 +360,14 @@ protected FieldNamingStrategy fieldNamingStrategy() { | |
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy() | ||
: PropertyNameFieldNamingStrategy.INSTANCE; | ||
} | ||
|
||
private boolean nonShadowedJacksonPresent() { | ||
try { | ||
JacksonJsonSerializer.preflightCheck(); | ||
return true; | ||
} catch (Throwable t) { | ||
return false; | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -184,6 +184,7 @@ void findByTypeAlias() { | |
vie = new Airport("airports::vie", "vie", "loww"); | ||
vie = airportRepository.save(vie); | ||
List<Airport> airports = couchbaseTemplate.findByQuery(Airport.class) | ||
.withConsistency(QueryScanConsistency.REQUEST_PLUS) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed a test that was sporadically failing. |
||
.matching(new Query(QueryCriteria.where(N1QLExpression.x("_class")).is("airport"))).all(); | ||
assertFalse(airports.isEmpty(), "should have found aiport"); | ||
} finally { | ||
|
@@ -198,7 +199,7 @@ void findByEnum() { | |
vie = new Airport("airports::vie", "vie", "loww"); | ||
vie = airportRepository.save(vie); | ||
Airport airport2 = airportRepository.findByIata(Iata.vie); | ||
assertNotNull(airport2, "should have found "+vie); | ||
assertNotNull(airport2, "should have found " + vie); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. formatting. Nothing to see. |
||
assertEquals(airport2.getId(), vie.getId()); | ||
} finally { | ||
airportRepository.delete(vie); | ||
|
@@ -397,7 +398,6 @@ void findBySimplePropertyAudited() { | |
} | ||
} | ||
|
||
|
||
private void sleep(int millis) { | ||
try { | ||
Thread.sleep(millis); // so they are executed out-of-order | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 @@ void saveAndFindById() { | |
} | ||
|
||
@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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was using a query which requires an index, but if you run this test by itself, there won't be an index. Switch to use kv. |
||
assertEquals(saved.getCreatedBy(), "auditor"); // NaiveAuditorAware will provide this | ||
} finally { | ||
airportRepository.delete(vie).block(); | ||
|
@@ -79,7 +81,7 @@ void findBySimplePropertyAudited() { | |
|
||
@Configuration | ||
@EnableReactiveCouchbaseRepositories("org.springframework.data.couchbase") | ||
@EnableReactiveCouchbaseAuditing | ||
@EnableReactiveCouchbaseAuditing | ||
static class Config extends AbstractCouchbaseConfiguration { | ||
|
||
@Override | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason we need to blow up if it is not present? (or just add the custom serializer if present?) - could log a warning instead if unlikely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. In the SDK, when the non-shadowed jackson classes are not present, a DefaultJsonSerializer is created. DefaultJsonSerializer has no means to use an already-created mapper, or expose the mapper that it creates. I suppose this would only be an issue when the user wants to us couchbaseObjectMapper() and expects it to be the same one used by the serializer. However, David said the not having the non-shadowed classes in Spring is impossible. The alternative would be to issue a warning saying that the serializer was not using couchbaseObjectMapper() and continue.
return nonShadowedJacksonPresent()
? JacksonJsonSerializer.create(cryptoManager)
: DefaultJsonSerializer.create(cryptoManager);