Skip to content

Commit ff0386e

Browse files
committed
UUID specification implementation updates
* Implement required behavior in MapCodec and IterableCodec * Implement required behavior in DBCollection JAVA-3516
1 parent 8d83a00 commit ff0386e

File tree

9 files changed

+212
-26
lines changed

9 files changed

+212
-26
lines changed

bson/src/main/org/bson/LazyBSONObject.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ Object readValue(final BsonBinaryReader reader) {
177177
case BINARY:
178178
byte binarySubType = reader.peekBinarySubType();
179179
if (BsonBinarySubType.isUuid(binarySubType) && reader.peekBinarySize() == 16) {
180-
return new UuidCodec().decode(reader, DecoderContext.builder().build());
180+
return new UuidCodec(UuidRepresentation.JAVA_LEGACY).decode(reader, DecoderContext.builder().build());
181181
}
182182
BsonBinary binary = reader.readBinaryData();
183183
if (binarySubType == BINARY.getValue() || binarySubType == OLD_BINARY.getValue()) {

bson/src/main/org/bson/codecs/IterableCodec.java

+38-6
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
package org.bson.codecs;
1818

19-
import org.bson.BsonBinarySubType;
2019
import org.bson.BsonReader;
2120
import org.bson.BsonType;
2221
import org.bson.BsonWriter;
2322
import org.bson.Transformer;
23+
import org.bson.UuidRepresentation;
2424
import org.bson.codecs.configuration.CodecRegistry;
2525

2626
import java.util.ArrayList;
@@ -35,11 +35,12 @@
3535
* @since 3.3
3636
*/
3737
@SuppressWarnings("rawtypes")
38-
public class IterableCodec implements Codec<Iterable> {
38+
public class IterableCodec implements Codec<Iterable>, OverridableUuidRepresentationCodec<Iterable> {
3939

4040
private final CodecRegistry registry;
4141
private final BsonTypeCodecMap bsonTypeCodecMap;
4242
private final Transformer valueTransformer;
43+
private final UuidRepresentation uuidRepresentation;
4344

4445
/**
4546
* Construct a new instance with the given {@code CodecRegistry} and {@code BsonTypeClassMap}.
@@ -59,14 +60,27 @@ public IterableCodec(final CodecRegistry registry, final BsonTypeClassMap bsonTy
5960
* @param valueTransformer the value Transformer
6061
*/
6162
public IterableCodec(final CodecRegistry registry, final BsonTypeClassMap bsonTypeClassMap, final Transformer valueTransformer) {
63+
this(registry, new BsonTypeCodecMap(notNull("bsonTypeClassMap", bsonTypeClassMap), registry), valueTransformer,
64+
UuidRepresentation.JAVA_LEGACY);
65+
}
66+
67+
private IterableCodec(final CodecRegistry registry, final BsonTypeCodecMap bsonTypeCodecMap, final Transformer valueTransformer,
68+
final UuidRepresentation uuidRepresentation) {
6269
this.registry = notNull("registry", registry);
63-
this.bsonTypeCodecMap = new BsonTypeCodecMap(notNull("bsonTypeClassMap", bsonTypeClassMap), registry);
70+
this.bsonTypeCodecMap = bsonTypeCodecMap;
6471
this.valueTransformer = valueTransformer != null ? valueTransformer : new Transformer() {
6572
@Override
6673
public Object transform(final Object objectToTransform) {
6774
return objectToTransform;
6875
}
6976
};
77+
this.uuidRepresentation = uuidRepresentation;
78+
}
79+
80+
81+
@Override
82+
public Codec<Iterable> withUuidRepresentation(final UuidRepresentation uuidRepresentation) {
83+
return new IterableCodec(registry, bsonTypeCodecMap, valueTransformer, uuidRepresentation);
7084
}
7185

7286
@Override
@@ -112,9 +126,27 @@ private Object readValue(final BsonReader reader, final DecoderContext decoderCo
112126
if (bsonType == BsonType.NULL) {
113127
reader.readNull();
114128
return null;
115-
} else if (bsonType == BsonType.BINARY && BsonBinarySubType.isUuid(reader.peekBinarySubType()) && reader.peekBinarySize() == 16) {
116-
return registry.get(UUID.class).decode(reader, decoderContext);
129+
} else {
130+
Codec<?> codec = bsonTypeCodecMap.get(bsonType);
131+
if (bsonType == BsonType.BINARY && reader.peekBinarySize() == 16) {
132+
switch (reader.peekBinarySubType()) {
133+
case 3:
134+
if (uuidRepresentation == UuidRepresentation.JAVA_LEGACY
135+
|| uuidRepresentation == UuidRepresentation.C_SHARP_LEGACY
136+
|| uuidRepresentation == UuidRepresentation.PYTHON_LEGACY) {
137+
codec = registry.get(UUID.class);
138+
}
139+
break;
140+
case 4:
141+
if (uuidRepresentation == UuidRepresentation.JAVA_LEGACY || uuidRepresentation == UuidRepresentation.STANDARD) {
142+
codec = registry.get(UUID.class);
143+
}
144+
break;
145+
default:
146+
break;
147+
}
148+
}
149+
return valueTransformer.transform(codec.decode(reader, decoderContext));
117150
}
118-
return valueTransformer.transform(bsonTypeCodecMap.get(bsonType).decode(reader, decoderContext));
119151
}
120152
}

bson/src/main/org/bson/codecs/MapCodec.java

+36-5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
package org.bson.codecs;
1818

19-
import org.bson.BsonBinarySubType;
2019
import org.bson.BsonReader;
2120
import org.bson.BsonType;
2221
import org.bson.BsonWriter;
2322
import org.bson.Transformer;
23+
import org.bson.UuidRepresentation;
2424
import org.bson.codecs.configuration.CodecRegistry;
2525

2626
import java.util.HashMap;
@@ -37,14 +37,15 @@
3737
*
3838
* @since 3.5
3939
*/
40-
public class MapCodec implements Codec<Map<String, Object>> {
40+
public class MapCodec implements Codec<Map<String, Object>>, OverridableUuidRepresentationCodec<Map<String, Object>> {
4141

4242
private static final CodecRegistry DEFAULT_REGISTRY = fromProviders(asList(new ValueCodecProvider(), new BsonValueCodecProvider(),
4343
new DocumentCodecProvider(), new IterableCodecProvider(), new MapCodecProvider()));
4444
private static final BsonTypeClassMap DEFAULT_BSON_TYPE_CLASS_MAP = new BsonTypeClassMap();
4545
private final BsonTypeCodecMap bsonTypeCodecMap;
4646
private final CodecRegistry registry;
4747
private final Transformer valueTransformer;
48+
private final UuidRepresentation uuidRepresentation;
4849

4950
/**
5051
* Construct a new instance with a default {@code CodecRegistry}
@@ -82,14 +83,26 @@ public MapCodec(final CodecRegistry registry, final BsonTypeClassMap bsonTypeCla
8283
* @param valueTransformer the value transformer to use as a final step when decoding the value of any field in the map
8384
*/
8485
public MapCodec(final CodecRegistry registry, final BsonTypeClassMap bsonTypeClassMap, final Transformer valueTransformer) {
86+
this(registry, new BsonTypeCodecMap(notNull("bsonTypeClassMap", bsonTypeClassMap), registry), valueTransformer,
87+
UuidRepresentation.JAVA_LEGACY);
88+
}
89+
90+
private MapCodec(final CodecRegistry registry, final BsonTypeCodecMap bsonTypeCodecMap, final Transformer valueTransformer,
91+
final UuidRepresentation uuidRepresentation) {
8592
this.registry = notNull("registry", registry);
86-
this.bsonTypeCodecMap = new BsonTypeCodecMap(notNull("bsonTypeClassMap", bsonTypeClassMap), registry);
93+
this.bsonTypeCodecMap = bsonTypeCodecMap;
8794
this.valueTransformer = valueTransformer != null ? valueTransformer : new Transformer() {
8895
@Override
8996
public Object transform(final Object value) {
9097
return value;
9198
}
9299
};
100+
this.uuidRepresentation = uuidRepresentation;
101+
}
102+
103+
@Override
104+
public Codec<Map<String, Object>> withUuidRepresentation(final UuidRepresentation uuidRepresentation) {
105+
return new MapCodec(registry, bsonTypeCodecMap, valueTransformer, uuidRepresentation);
93106
}
94107

95108
@Override
@@ -129,8 +142,26 @@ private Object readValue(final BsonReader reader, final DecoderContext decoderCo
129142
return null;
130143
} else if (bsonType == BsonType.ARRAY) {
131144
return decoderContext.decodeWithChildContext(registry.get(List.class), reader);
132-
} else if (bsonType == BsonType.BINARY && BsonBinarySubType.isUuid(reader.peekBinarySubType()) && reader.peekBinarySize() == 16) {
133-
return decoderContext.decodeWithChildContext(registry.get(UUID.class), reader);
145+
} else if (bsonType == BsonType.BINARY && reader.peekBinarySize() == 16) {
146+
Codec<?> codec = bsonTypeCodecMap.get(bsonType);
147+
switch (reader.peekBinarySubType()) {
148+
case 3:
149+
if (uuidRepresentation == UuidRepresentation.JAVA_LEGACY
150+
|| uuidRepresentation == UuidRepresentation.C_SHARP_LEGACY
151+
|| uuidRepresentation == UuidRepresentation.PYTHON_LEGACY) {
152+
codec = registry.get(UUID.class);
153+
}
154+
break;
155+
case 4:
156+
if (uuidRepresentation == UuidRepresentation.JAVA_LEGACY || uuidRepresentation == UuidRepresentation.STANDARD) {
157+
codec = registry.get(UUID.class);
158+
}
159+
break;
160+
default:
161+
break;
162+
}
163+
164+
return decoderContext.decodeWithChildContext(codec, reader);
134165
}
135166
return valueTransformer.transform(bsonTypeCodecMap.get(bsonType).decode(reader, decoderContext));
136167
}

bson/src/test/unit/org/bson/codecs/IterableCodecSpecification.groovy

+59
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,21 @@
1616

1717
package org.bson.codecs
1818

19+
1920
import org.bson.BsonDocument
2021
import org.bson.BsonDocumentReader
2122
import org.bson.BsonDocumentWriter
2223
import org.bson.types.Binary
2324
import spock.lang.Specification
25+
import spock.lang.Unroll
2426

2527
import static org.bson.BsonDocument.parse
28+
import static org.bson.UuidRepresentation.C_SHARP_LEGACY
29+
import static org.bson.UuidRepresentation.JAVA_LEGACY
30+
import static org.bson.UuidRepresentation.PYTHON_LEGACY
31+
import static org.bson.UuidRepresentation.STANDARD
32+
import static org.bson.UuidRepresentation.UNSPECIFIED
33+
import static org.bson.codecs.configuration.CodecRegistries.fromCodecs
2634
import static org.bson.codecs.configuration.CodecRegistries.fromProviders
2735

2836
class IterableCodecSpecification extends Specification {
@@ -122,4 +130,55 @@ class IterableCodecSpecification extends Specification {
122130
'{"array": [{ "$binary" : "CAcGBQQDAgEQDw4NDAsKCQ==", "$type" : "3" }]}' | [UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10')]
123131
}
124132

133+
@SuppressWarnings(['LineLength'])
134+
@Unroll
135+
def 'should decode binary subtype 3 for UUID'() {
136+
given:
137+
def reader = new BsonDocumentReader(parse(document))
138+
def codec = new IterableCodec(fromCodecs(new UuidCodec(representation), new BinaryCodec()), new BsonTypeClassMap())
139+
.withUuidRepresentation(representation)
140+
141+
when:
142+
reader.readStartDocument()
143+
reader.readName('array')
144+
def iterable = codec.decode(reader, DecoderContext.builder().build())
145+
reader.readEndDocument()
146+
147+
then:
148+
value == iterable
149+
150+
where:
151+
representation | value | document
152+
JAVA_LEGACY | [UUID.fromString('08070605-0403-0201-100f-0e0d0c0b0a09')] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "3" }]}'
153+
C_SHARP_LEGACY | [UUID.fromString('04030201-0605-0807-090a-0b0c0d0e0f10')] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "3" }]}'
154+
PYTHON_LEGACY | [UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10')] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "3" }]}'
155+
STANDARD | [new Binary((byte) 3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[])] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "3" }]}'
156+
UNSPECIFIED | [new Binary((byte) 3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[])] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "3" }]}'
157+
}
158+
159+
@SuppressWarnings(['LineLength'])
160+
@Unroll
161+
def 'should decode binary subtype 4 for UUID'() {
162+
given:
163+
def reader = new BsonDocumentReader(parse(document))
164+
def codec = new IterableCodec(fromCodecs(new UuidCodec(representation), new BinaryCodec()), new BsonTypeClassMap())
165+
.withUuidRepresentation(representation)
166+
167+
when:
168+
reader.readStartDocument()
169+
reader.readName('array')
170+
def iterable = codec.decode(reader, DecoderContext.builder().build())
171+
reader.readEndDocument()
172+
173+
then:
174+
value == iterable
175+
176+
where:
177+
representation | value | document
178+
STANDARD | [UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10')] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "4" }]}'
179+
JAVA_LEGACY | [UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10')] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "4" }]}'
180+
C_SHARP_LEGACY | [new Binary((byte) 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[])] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "4" }]}'
181+
PYTHON_LEGACY | [new Binary((byte) 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[])] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "4" }]}'
182+
UNSPECIFIED | [new Binary((byte) 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[])] | '{"array": [{ "$binary" : "AQIDBAUGBwgJCgsMDQ4PEA==", "$type" : "4" }]}'
183+
}
125184
}

bson/src/test/unit/org/bson/codecs/MapCodecSpecification.groovy

+41-8
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,20 @@ import org.bson.types.ObjectId
4242
import org.bson.types.Symbol
4343
import spock.lang.Shared
4444
import spock.lang.Specification
45+
import spock.lang.Unroll
4546

4647
import java.nio.ByteBuffer
4748
import java.util.concurrent.atomic.AtomicBoolean
4849
import java.util.concurrent.atomic.AtomicInteger
4950
import java.util.concurrent.atomic.AtomicLong
5051

5152
import static java.util.Arrays.asList
53+
import static org.bson.UuidRepresentation.C_SHARP_LEGACY
54+
import static org.bson.UuidRepresentation.JAVA_LEGACY
55+
import static org.bson.UuidRepresentation.PYTHON_LEGACY
56+
import static org.bson.UuidRepresentation.STANDARD
57+
import static org.bson.UuidRepresentation.UNSPECIFIED
58+
import static org.bson.codecs.configuration.CodecRegistries.fromCodecs
5259
import static org.bson.codecs.configuration.CodecRegistries.fromProviders
5360

5461
class MapCodecSpecification extends Specification {
@@ -139,22 +146,48 @@ class MapCodecSpecification extends Specification {
139146
}
140147

141148
@SuppressWarnings(['LineLength'])
142-
def 'should decode binary subtypes for UUID'() {
149+
@Unroll
150+
def 'should decode binary subtype 3 for UUID'() {
143151
given:
144152
def reader = new BsonBinaryReader(ByteBuffer.wrap(bytes as byte[]))
145153

146154
when:
147-
def document = new MapCodec().decode(reader, DecoderContext.builder().build())
155+
def map = new MapCodec(fromCodecs(new UuidCodec(representation), new BinaryCodec()))
156+
.withUuidRepresentation(representation)
157+
.decode(reader, DecoderContext.builder().build())
148158

149159
then:
150-
value == document.get('f')
160+
value == map.get('f')
151161

152162
where:
153-
value | bytes
154-
new Binary((byte) 0x03, (byte[]) [115, 116, 11]) | [16, 0, 0, 0, 5, 102, 0, 3, 0, 0, 0, 3, 115, 116, 11, 0]
155-
new Binary((byte) 0x04, (byte[]) [115, 116, 11]) | [16, 0, 0, 0, 5, 102, 0, 3, 0, 0, 0, 4, 115, 116, 11, 0]
156-
UUID.fromString('08070605-0403-0201-100f-0e0d0c0b0a09') | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
157-
UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10') | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
163+
representation | value | bytes
164+
JAVA_LEGACY | UUID.fromString('08070605-0403-0201-100f-0e0d0c0b0a09') | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
165+
C_SHARP_LEGACY | UUID.fromString('04030201-0605-0807-090a-0b0c0d0e0f10') | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
166+
PYTHON_LEGACY | UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10') | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
167+
STANDARD | new Binary((byte) 3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[]) | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
168+
UNSPECIFIED | new Binary((byte) 3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[]) | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
169+
}
170+
171+
@SuppressWarnings(['LineLength'])
172+
@Unroll
173+
def 'should decode binary subtype 4 for UUID'() {
174+
given:
175+
def reader = new BsonBinaryReader(ByteBuffer.wrap(bytes as byte[]))
176+
177+
when:
178+
def map = new MapCodec().withUuidRepresentation(representation)
179+
.decode(reader, DecoderContext.builder().build())
180+
181+
then:
182+
value == map.get('f')
183+
184+
where:
185+
representation | value | bytes
186+
STANDARD | UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10') | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
187+
JAVA_LEGACY | UUID.fromString('01020304-0506-0708-090a-0b0c0d0e0f10') | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
188+
C_SHARP_LEGACY | new Binary((byte) 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[]) | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
189+
PYTHON_LEGACY | new Binary((byte) 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[]) | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
190+
UNSPECIFIED | new Binary((byte) 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as byte[]) | [29, 0, 0, 0, 5, 102, 0, 16, 0, 0, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0]
158191
}
159192

160193
def 'should apply transformer to decoded values'() {

driver-legacy/src/main/com/mongodb/DBCollection.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -2447,10 +2447,11 @@ private List<com.mongodb.bulk.WriteRequest> translateWriteRequestsToNew(final Li
24472447
return retVal;
24482448
}
24492449

2450-
DBObjectCodec getDefaultDBObjectCodec() {
2451-
return new DBObjectCodec(MongoClient.getDefaultCodecRegistry(),
2450+
Codec<DBObject> getDefaultDBObjectCodec() {
2451+
return new DBObjectCodec(getDB().getMongoClient().getCodecRegistry(),
24522452
DBObjectCodec.getDefaultBsonTypeClassMap(),
2453-
getObjectFactory());
2453+
getObjectFactory())
2454+
.withUuidRepresentation(getDB().getMongoClient().getMongoClientOptions().getUuidRepresentation());
24542455
}
24552456

24562457
private <T> T convertOptionsToType(final DBObject options, final String field, final Class<T> clazz) {

driver-legacy/src/main/com/mongodb/GroupCommand.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.mongodb.operation.GroupOperation;
2222
import org.bson.BsonDocumentWrapper;
2323
import org.bson.BsonJavaScript;
24+
import org.bson.codecs.Codec;
2425

2526
import static com.mongodb.assertions.Assertions.notNull;
2627

@@ -149,7 +150,7 @@ public DBObject toDBObject() {
149150
return new BasicDBObject("group", args);
150151
}
151152

152-
GroupOperation<DBObject> toOperation(final MongoNamespace namespace, final DBObjectCodec codec, final boolean retryReads) {
153+
GroupOperation<DBObject> toOperation(final MongoNamespace namespace, final Codec<DBObject> codec, final boolean retryReads) {
153154
if (initial == null) {
154155
throw new IllegalArgumentException("Group command requires an initial document for the aggregate result");
155156
}

0 commit comments

Comments
 (0)