Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
492f09fbdf | ||
|
|
e3e73f5351 | ||
|
|
e5aff2645b | ||
|
|
b3c0fbb02d | ||
|
|
51de522e88 | ||
|
|
d2842b246f |
16
pom.xml
16
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.2.0-M2</version>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>3.2.0-M2</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
@@ -26,7 +26,7 @@
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
<springdata.commons>3.2.0-M2</springdata.commons>
|
||||
<springdata.commons>3.2.0-SNAPSHOT</springdata.commons>
|
||||
<mongo>4.10.2</mongo>
|
||||
<mongo.reactivestreams>${mongo}</mongo.reactivestreams>
|
||||
<jmh.version>1.19</jmh.version>
|
||||
@@ -144,6 +144,16 @@
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshot</id>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.2.0-M2</version>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.2.0-M2</version>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.2.0-M2</version>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ import com.mongodb.DBRef;
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Heesu Jung
|
||||
* @author Divya Srivastava
|
||||
* @author Julia Lee
|
||||
*/
|
||||
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
|
||||
|
||||
@@ -1976,8 +1977,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (property.isDocumentReference()) {
|
||||
return (T) dbRefResolver.resolveReference(property, accessor.get(property), referenceLookupDelegate,
|
||||
context::convert);
|
||||
return (T) dbRefResolver.resolveReference(property,
|
||||
new DocumentReferenceSource(accessor.getDocument(), accessor.get(property)),
|
||||
referenceLookupDelegate, context::convert);
|
||||
}
|
||||
|
||||
return super.getPropertyValue(property);
|
||||
|
||||
@@ -255,6 +255,11 @@ class UnwrappedMongoPersistentProperty implements MongoPersistentProperty {
|
||||
return delegate.isWritable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadable() {
|
||||
return delegate.isReadable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return delegate.isImmutable();
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.observability;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -27,10 +33,6 @@ import com.mongodb.event.CommandListener;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
import com.mongodb.event.CommandSucceededEvent;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
|
||||
|
||||
/**
|
||||
* Implement MongoDB's {@link CommandListener} using Micrometer's {@link Observation} API.
|
||||
*
|
||||
@@ -126,50 +128,54 @@ public class MongoObservationCommandListener implements CommandListener {
|
||||
@Override
|
||||
public void commandSucceeded(CommandSucceededEvent event) {
|
||||
|
||||
RequestContext requestContext = event.getRequestContext();
|
||||
doInObservation(event.getRequestContext(), (observation, context) -> {
|
||||
|
||||
if (requestContext == null) {
|
||||
return;
|
||||
}
|
||||
context.setCommandSucceededEvent(event);
|
||||
|
||||
Observation observation = requestContext.getOrDefault(ObservationThreadLocalAccessor.KEY, null);
|
||||
if (observation == null) {
|
||||
return;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Command succeeded - will stop observation [" + observation + "]");
|
||||
}
|
||||
|
||||
MongoHandlerContext context = (MongoHandlerContext) observation.getContext();
|
||||
context.setCommandSucceededEvent(event);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Command succeeded - will stop observation [" + observation + "]");
|
||||
}
|
||||
|
||||
observation.stop();
|
||||
observation.stop();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandFailed(CommandFailedEvent event) {
|
||||
|
||||
RequestContext requestContext = event.getRequestContext();
|
||||
doInObservation(event.getRequestContext(), (observation, context) -> {
|
||||
|
||||
context.setCommandFailedEvent(event);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Command failed - will stop observation [" + observation + "]");
|
||||
}
|
||||
|
||||
observation.error(event.getThrowable());
|
||||
observation.stop();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the given action for the {@link Observation} and {@link MongoHandlerContext} if there is an ongoing Mongo
|
||||
* Observation. Exceptions thrown by the action are relayed to the caller.
|
||||
*
|
||||
* @param requestContext the context to extract the Observation from.
|
||||
* @param action the action to invoke.
|
||||
*/
|
||||
private void doInObservation(@Nullable RequestContext requestContext,
|
||||
BiConsumer<Observation, MongoHandlerContext> action) {
|
||||
|
||||
if (requestContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Observation observation = requestContext.getOrDefault(ObservationThreadLocalAccessor.KEY, null);
|
||||
if (observation == null) {
|
||||
if (observation == null || !(observation.getContext()instanceof MongoHandlerContext context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MongoHandlerContext context = (MongoHandlerContext) observation.getContext();
|
||||
context.setCommandFailedEvent(event);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Command failed - will stop observation [" + observation + "]");
|
||||
}
|
||||
|
||||
observation.error(event.getThrowable());
|
||||
observation.stop();
|
||||
action.accept(observation, context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,6 +57,7 @@ import com.mongodb.client.model.Filters;
|
||||
* {@link DocumentReference} related integration tests for {@link MongoTemplate}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Julia Lee
|
||||
*/
|
||||
@ExtendWith(MongoClientExtension.class)
|
||||
public class MongoTemplateDocumentReferenceTests {
|
||||
@@ -1265,6 +1266,32 @@ public class MongoTemplateDocumentReferenceTests {
|
||||
.isEqualTo(new ObjectRefHavingStringIdTargetType(id.toHexString(), "me-the-referenced-object"));
|
||||
}
|
||||
|
||||
@Test // GH-4484
|
||||
void resolveReferenceForOneToManyLookupWithSelfVariableWhenUsedInCtorArgument() {
|
||||
|
||||
OneToManyStylePublisherWithRequiredArgsCtor publisher = new OneToManyStylePublisherWithRequiredArgsCtor("p-100", null);
|
||||
template.save(publisher);
|
||||
|
||||
OneToManyStyleBook book1 = new OneToManyStyleBook();
|
||||
book1.id = "id-1";
|
||||
book1.publisherId = publisher.id;
|
||||
|
||||
OneToManyStyleBook book2 = new OneToManyStyleBook();
|
||||
book2.id = "id-2";
|
||||
book2.publisherId = "p-200";
|
||||
|
||||
OneToManyStyleBook book3 = new OneToManyStyleBook();
|
||||
book3.id = "id-3";
|
||||
book3.publisherId = publisher.id;
|
||||
|
||||
template.save(book1);
|
||||
template.save(book2);
|
||||
template.save(book3);
|
||||
|
||||
OneToManyStylePublisherWithRequiredArgsCtor target = template.findOne(query(where("id").is(publisher.id)), OneToManyStylePublisherWithRequiredArgsCtor.class);
|
||||
assertThat(target.books).containsExactlyInAnyOrder(book1, book3);
|
||||
}
|
||||
|
||||
static class SingleRefRoot {
|
||||
|
||||
String id;
|
||||
@@ -2249,4 +2276,40 @@ public class MongoTemplateDocumentReferenceTests {
|
||||
return "MongoTemplateDocumentReferenceTests.WithListOfRefs(id=" + this.getId() + ", refs=" + this.getRefs() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
static class OneToManyStylePublisherWithRequiredArgsCtor {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
@ReadOnlyProperty
|
||||
@DocumentReference(lookup="{'publisherId':?#{#self._id} }")
|
||||
List<OneToManyStyleBook> books;
|
||||
|
||||
public OneToManyStylePublisherWithRequiredArgsCtor(String id, List<OneToManyStyleBook> books) {
|
||||
this.id = id;
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public List<OneToManyStyleBook> getBooks() {
|
||||
return this.books;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setBooks(List<OneToManyStyleBook> books) {
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "MongoTemplateDocumentReferenceTests.OneToManyStylePublisherWithRequiredArgsCtor(id=" + this.getId() + ", book="
|
||||
+ this.getBooks() + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
package org.springframework.data.mongodb.observability;
|
||||
|
||||
import static io.micrometer.core.tck.MeterRegistryAssert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import io.micrometer.common.KeyValues;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
|
||||
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonString;
|
||||
@@ -33,18 +42,12 @@ import com.mongodb.event.CommandFailedEvent;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
import com.mongodb.event.CommandSucceededEvent;
|
||||
|
||||
import io.micrometer.common.KeyValues;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
/**
|
||||
* Series of test cases exercising {@link MongoObservationCommandListener}.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Greg Turnquist
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class MongoObservationCommandListenerTests {
|
||||
|
||||
@@ -176,6 +179,38 @@ class MongoObservationCommandListenerTests {
|
||||
assertThatTimerRegisteredWithTags();
|
||||
}
|
||||
|
||||
@Test // GH-4481
|
||||
void completionShouldIgnoreIncompatibleObservationContext() {
|
||||
|
||||
// given
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
Observation observation = mock(Observation.class);
|
||||
traceRequestContext.put(ObservationThreadLocalAccessor.KEY, observation);
|
||||
|
||||
// when
|
||||
listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, null, "insert", null, 0));
|
||||
|
||||
verify(observation).getContext();
|
||||
verifyNoMoreInteractions(observation);
|
||||
}
|
||||
|
||||
@Test // GH-4481
|
||||
void failureShouldIgnoreIncompatibleObservationContext() {
|
||||
|
||||
// given
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
Observation observation = mock(Observation.class);
|
||||
traceRequestContext.put(ObservationThreadLocalAccessor.KEY, observation);
|
||||
|
||||
// when
|
||||
listener.commandFailed(new CommandFailedEvent(traceRequestContext, 0, null, "insert", 0, null));
|
||||
|
||||
verify(observation).getContext();
|
||||
verifyNoMoreInteractions(observation);
|
||||
}
|
||||
|
||||
private RequestContext getContext() {
|
||||
return ((SynchronousContextProvider) ContextProviderFactory.create(observationRegistry)).getContext();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user