[JAVA-4832] Default CodecRegistry isn't able to handle custom implementation of Number Created: 23/Dec/22  Updated: 27/Oct/23  Resolved: 16/Jan/23

Status: Closed
Project: Java Driver
Component/s: Codecs
Affects Version/s: None
Fix Version/s: None

Type: Question Priority: Minor - P4
Reporter: ich mag Assignee: Jeffrey Yemin
Resolution: Gone away Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Summary

I am trying to load a JsonObject (part of the GSON library) that includes numbers. Gson outputs the numbers with the type "com.google.gson.internal.LazilyParsedNumber". Basically a class that extends Java's general Number class, that stores the loaded number as a String and parses it when needed. Now I am trying to execute an update with Gson's Number, however this leads to an error:

 


_[23:52:26 WARN]: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for CodecCacheKey{clazz=class com.google.gson.internal.LazilyParsedNumber, types=null}.
[23:52:31 WARN]:        at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:74)
[23:52:31 WARN]:        at org.bson.internal.ChildCodecRegistry.get(ChildCodecRegistry.java:67)
[23:52:31 WARN]:        at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:248)
[23:52:31 WARN]:        at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:159)
[23:52:31 WARN]:        at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:67)
[23:52:31 WARN]:        at org.bson.BsonDocumentWrapper.getUnwrapped(BsonDocumentWrapper.java:199)
[23:52:31 WARN]:        at org.bson.BsonDocumentWrapper.entrySet(BsonDocumentWrapper.java:169)
[23:52:31 WARN]:        at com.mongodb.client.model.Updates$CompositeUpdate.toBsonDocument(Updates.java:785)
[23:52:31 WARN]:        at com.mongodb.client.model.BuildersHelper.encodeValue(BuildersHelper.java:34)
[23:52:31 WARN]:        at com.mongodb.client.model.Updates$SimpleUpdate.toBsonDocument(Updates.java:511)
[23:52:31 WARN]:        at com.mongodb.internal.operation.Operations.toBsonDocument(Operations.java:620)
[23:52:31 WARN]:        at com.mongodb.internal.operation.Operations.bulkWrite(Operations.java:463)
[23:52:31 WARN]:        at com.mongodb.internal.operation.Operations.updateOne(Operations.java:396)
[23:52:31 WARN]:        at com.mongodb.internal.operation.SyncOperations.updateOne(SyncOperations.java:184)
[23:52:31 WARN]:        at com.mongodb.client.internal.MongoCollectionImpl.executeUpdate(MongoCollectionImpl.java:1010)
[23:52:31 WARN]:        at com.mongodb.client.internal.MongoCollectionImpl.updateOne(MongoCollectionImpl.java:584)
[23:52:31 WARN]:        at storage.MongoDBStorage.lambda$savePlayerStats$2(MongoDBStorage.java:216)
[23:52:31 WARN]:        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
[23:52:31 WARN]:        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
[23:52:31 WARN]:        at storage.StorageConnector$1.run(StorageConnector.java:46)_

 

 

Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

Sync 4.8.1. Doesn't seem to be present with the latest (3.12.11) normal driver.

How to Reproduce

 

MongoCollection<Document> doc = ...;
Number number = new Gson().fromJson("5", JsonPrimitive.class).getaAsNumber();
// alternatively: directly initiating the type using new LazilyParsedNumber(5)
 
// do some random operations with the given number
doc.updateOne(Filters.eq("a", "b"), Updates.combine(new BasicDBObject("number", number));

 

 

Additional Background

Please provide any additional background information that may be helpful in diagnosing the bug.



 Comments   
Comment by PM Bot [ 16/Jan/23 ]

There hasn't been any recent activity on this ticket, so we're resolving it. Thanks for reaching out! Please feel free to comment on this if you're able to provide more information.

Comment by Jeffrey Yemin [ 31/Dec/22 ]

Hi marcely1199@gmail.com,

This is by design, as your hot fix demonstrates that some logic is required to properly serialize instances of this class. If you want to handle this more seamlessly, the best way to is to create an implementation of Codec< LazilyParsedNumber> and register is with the MongoClient instance used by the application. See here for documentation on how to do that.

Comment by ich mag [ 23/Dec/22 ]

That's the hotfix that I am using

if(!number.getClass().getName().startsWith("java")){ // likely a "LazilyParsedNumber" from Gson; Not supported / broken
    if(number.doubleValue()%1D == 0D)
        number = number.longValue();
    else
        number = number.doubleValue();
} 

Not a decent solution

Generated at Thu Feb 08 09:03:05 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.