Skip to content

Commit 716da74

Browse files
committed
Codec improvements
Ensure DecoderContext null checks the decoder PojoCodec improve error message if the cached codec is null Remove creation race condition when creating automatic PojoCodecs JAVA-3606
1 parent ab73b78 commit 716da74

File tree

4 files changed

+21
-7
lines changed

4 files changed

+21
-7
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import org.bson.BsonReader;
2020

21+
import static org.bson.assertions.Assertions.notNull;
22+
2123
/**
2224
* The context for decoding values to BSON.
2325
*
@@ -90,6 +92,7 @@ public DecoderContext build() {
9092
* @since 3.5
9193
*/
9294
public <T> T decodeWithChildContext(final Decoder<T> decoder, final BsonReader reader) {
95+
notNull("decoder", decoder);
9396
return decoder.decode(reader, DEFAULT_CONTEXT);
9497
}
9598

bson/src/main/org/bson/codecs/pojo/PojoCodecImpl.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,17 @@ private <S> void decodePropertyModel(final BsonReader reader, final DecoderConte
210210
if (reader.getCurrentBsonType() == BsonType.NULL) {
211211
reader.readNull();
212212
} else {
213-
value = decoderContext.decodeWithChildContext(propertyModel.getCachedCodec(), reader);
213+
Codec<S> codec = propertyModel.getCachedCodec();
214+
if (codec == null) {
215+
throw new CodecConfigurationException(format("Missing codec in '%s' for '%s'",
216+
classModel.getName(), propertyModel.getName()));
217+
}
218+
value = decoderContext.decodeWithChildContext(codec, reader);
214219
}
215220
if (propertyModel.isWritable()) {
216221
instanceCreator.set(value, propertyModel);
217222
}
218-
} catch (BsonInvalidOperationException e) {
219-
throw new CodecConfigurationException(format("Failed to decode '%s'. Decoding '%s' errored with: %s",
220-
classModel.getName(), name, e.getMessage()), e);
221-
} catch (CodecConfigurationException e) {
223+
} catch (BsonInvalidOperationException | CodecConfigurationException e) {
222224
throw new CodecConfigurationException(format("Failed to decode '%s'. Decoding '%s' errored with: %s",
223225
classModel.getName(), name, e.getMessage()), e);
224226
}

bson/src/main/org/bson/internal/CodecCache.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ public void put(final Class<?> clazz, final Codec<?> codec){
3636
codecCache.put(clazz, Optional.of(codec));
3737
}
3838

39+
@SuppressWarnings("unchecked")
40+
public synchronized <T> Codec<T> putIfMissing(final Class<T> clazz, final Codec<T> codec){
41+
if (codecCache.containsKey(clazz)) {
42+
return (Codec<T>) codecCache.get(clazz).get();
43+
} else {
44+
codecCache.put(clazz, Optional.of(codec));
45+
return codec;
46+
}
47+
}
48+
3949
@SuppressWarnings("unchecked")
4050
public <T> Codec<T> getOrThrow(final Class<T> clazz) {
4151
if (codecCache.containsKey(clazz)) {

bson/src/main/org/bson/internal/ProvidersCodecRegistry.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ public <T> Codec<T> get(final ChildCodecRegistry<T> context) {
5656
for (CodecProvider provider : codecProviders) {
5757
Codec<T> codec = provider.get(context.getCodecClass(), context);
5858
if (codec != null) {
59-
codecCache.put(context.getCodecClass(), codec);
60-
return codec;
59+
return codecCache.putIfMissing(context.getCodecClass(), codec);
6160
}
6261
}
6362
codecCache.put(context.getCodecClass(), null);

0 commit comments

Comments
 (0)