java - MongoDB BSON codec not being used while encoding object -
i'm attempting store object in mongodb database (using mongodb 3.0.2) , getting codecconfigurationexception
when attempting encode object error message
can't find codec class java.time.localdate.
i have written , included codec localdate
objects. details follow.
the object, dutyblock
, i'm attempting store has these member variables:
public class dutyblock { private localdate startdate; private localdate enddate; //inclusive private int blocklength; private double pointvalue; private arraylist<ra> assigned; }
i wrote following codec encode dutyblock
objects within database:
public class dutyblockcodec implements codec<dutyblock> { @override public void encode(bsonwriter writer, dutyblock t, encodercontext ec) { document document = new document(); document.append("startdate", t.getstartdate()); document.append("enddate", t.getenddate()); document.append("blocklength", t.getblocklength()); document.append("pointvalue", t.getpointvalue()); document.append("assigned", t.getrasonduty()); writer.writestring(document.tojson()); //line 27 in error message. } @override public class<dutyblock> getencoderclass() { return dutyblock.class; } @override public dutyblock decode(bsonreader reader, decodercontext dc) { string json = reader.readstring(); return new dutyblock(document.parse(json)); } }
since mongodb not support java.time.localdate class
, i've written following codec encode localdate
objects within database:
public class localdatecodec implements codec<localdate> { @override public void encode(bsonwriter writer, localdate t, encodercontext ec) { writer.writestring(t.tostring()); } @override public class<localdate> getencoderclass() { return localdate.class; } @override public localdate decode(bsonreader reader, decodercontext dc) { string date = reader.readstring(); return localdate.parse(date); } }
i've added 2 codec
's (along 1 ra
type) codecregistry
@ mongoclient level while instantiating mongoclient.
public class dutyscheduledb { private mongoclient mongoclient; private mongodatabase db; public dutyscheduledb() { codecregistry codecregistry = codecregistries.fromregistries( codecregistries.fromcodecs(new localdatecodec(), new dutyblockcodec(), new racodec()), mongoclient.getdefaultcodecregistry()); mongoclientoptions options = mongoclientoptions.builder() .codecregistry(codecregistry).build(); mongoclient = new mongoclient(new serveraddress(), options); db = mongoclient.getdatabase("dutyschedulerdb"); } . (more code not shown) . . }
i attempt store arraylist
of dutyblock
objects part of org.bson.document
within mongodb database.
public void storescheduledcalendar(string id, string calendarname, arraylist<dutyblock> cal) { //access collection of scheduled calendars. mongocollection collection = db.getcollection("scheduledcalendars"); //query parameter uuid + calendarname. document doc = new document("name", id + calendarname); doc.append("dutyblocks", cal); //insert doc collection. collection.insertone(doc); //line 59 in error message. }
however, i'm running error message:
exception in thread "main" org.bson.codecs.configuration.codecconfigurationexception: can't find codec class java.time.localdate. @ org.bson.codecs.configuration.codeccache.getorthrow(codeccache.java:46) @ org.bson.codecs.configuration.providerscodecregistry.get(providerscodecregistry.java:63) @ org.bson.codecs.configuration.providerscodecregistry.get(providerscodecregistry.java:37) @ org.bson.codecs.documentcodec.writevalue(documentcodec.java:174) @ org.bson.codecs.documentcodec.writemap(documentcodec.java:189) @ org.bson.codecs.documentcodec.encode(documentcodec.java:131) @ org.bson.codecs.documentcodec.encode(documentcodec.java:45) @ org.bson.document.tojson(document.java:294) @ org.bson.document.tojson(document.java:268) @ org.bson.document.tojson(document.java:255) @ schedulingheuristic.dutyblockcodec.encode(dutyblockcodec.java:27) @ schedulingheuristic.dutyblockcodec.encode(dutyblockcodec.java:16) @ org.bson.codecs.encodercontext.encodewithchildcontext(encodercontext.java:91) @ org.bson.codecs.documentcodec.writevalue(documentcodec.java:175) @ org.bson.codecs.documentcodec.writeiterable(documentcodec.java:197) @ org.bson.codecs.documentcodec.writevalue(documentcodec.java:170) @ org.bson.codecs.documentcodec.writemap(documentcodec.java:189) @ org.bson.codecs.documentcodec.encode(documentcodec.java:131) @ org.bson.codecs.documentcodec.encode(documentcodec.java:45) @ org.bson.codecs.bsondocumentwrappercodec.encode(bsondocumentwrappercodec.java:63) @ org.bson.codecs.bsondocumentwrappercodec.encode(bsondocumentwrappercodec.java:29) @ com.mongodb.connection.insertcommandmessage.writethewrites(insertcommandmessage.java:99) @ com.mongodb.connection.insertcommandmessage.writethewrites(insertcommandmessage.java:43) @ com.mongodb.connection.basewritecommandmessage.encodemessagebody(basewritecommandmessage.java:112) @ com.mongodb.connection.basewritecommandmessage.encodemessagebody(basewritecommandmessage.java:35) @ com.mongodb.connection.requestmessage.encode(requestmessage.java:132) @ com.mongodb.connection.basewritecommandmessage.encode(basewritecommandmessage.java:89) @ com.mongodb.connection.writecommandprotocol.sendmessage(writecommandprotocol.java:170) @ com.mongodb.connection.writecommandprotocol.execute(writecommandprotocol.java:73) @ com.mongodb.connection.insertcommandprotocol.execute(insertcommandprotocol.java:66) @ com.mongodb.connection.insertcommandprotocol.execute(insertcommandprotocol.java:37) @ com.mongodb.connection.defaultserver$defaultserverprotocolexecutor.execute(defaultserver.java:155) @ com.mongodb.connection.defaultserverconnection.executeprotocol(defaultserverconnection.java:219) @ com.mongodb.connection.defaultserverconnection.insertcommand(defaultserverconnection.java:108) @ com.mongodb.operation.mixedbulkwriteoperation$run$2.executewritecommandprotocol(mixedbulkwriteoperation.java:416) @ com.mongodb.operation.mixedbulkwriteoperation$run$runexecutor.execute(mixedbulkwriteoperation.java:604) @ com.mongodb.operation.mixedbulkwriteoperation$run.execute(mixedbulkwriteoperation.java:363) @ com.mongodb.operation.mixedbulkwriteoperation$1.call(mixedbulkwriteoperation.java:148) @ com.mongodb.operation.mixedbulkwriteoperation$1.call(mixedbulkwriteoperation.java:141) @ com.mongodb.operation.operationhelper.withconnectionsource(operationhelper.java:186) @ com.mongodb.operation.operationhelper.withconnection(operationhelper.java:177) @ com.mongodb.operation.mixedbulkwriteoperation.execute(mixedbulkwriteoperation.java:141) @ com.mongodb.operation.mixedbulkwriteoperation.execute(mixedbulkwriteoperation.java:72) @ com.mongodb.mongo.execute(mongo.java:747) @ com.mongodb.mongo$2.execute(mongo.java:730) @ com.mongodb.mongocollectionimpl.executesinglewriterequest(mongocollectionimpl.java:482) @ com.mongodb.mongocollectionimpl.insertone(mongocollectionimpl.java:277) @ dutyscheduledb.storescheduledcalendar(dutyscheduledb.java:59) @ dutyscheduledb.main(dutyscheduledb.java:106)
it seems codec localdate
isn't being used when attempting encode dutyblock
objects, though i've verified collection attempting store org.bson.document
in indeed contain localdatecodec
via
system.out.println(collection.getcodecregistry().get(localdate.class));
can can provide insight on why happening?
after several days of research, i've figured out solution.
the dutyblockcodec
depends on localdatecodec
(which created) in order encode/decode. dependency isn't satisfied adding 2 codecs same codec registry. solution pass codecregistry
object containing codecs dutyblockcodec
depends on (e.g. codecregistry
containing within localdatecodec
) dutyblockcodec
's constructor, stored member variable. in order use localdatecodec
encode, use encodercontext.encodewithchildcontext()
method, passing in codec, writer, , element encode. additionally, write individual fields rather writing document
string
(as in original code). dutyblock
codec ends looking this:
public class dutyblockcodec implements codec<dutyblock> { private final codecregistry codecregistry; public dutyblockcodec(final codecregistry codecregistry) { this.codecregistry = codecregistry; } @override public void encode(bsonwriter writer, dutyblock t, encodercontext ec) { writer.writestartdocument(); codec datecodec = codecregistry.get(localdate.class); writer.writename("startdate"); ec.encodewithchildcontext(datecodec, writer, t.getstartdate()); writer.writename("enddate"); ec.encodewithchildcontext(datecodec, writer, t.getenddate()); writer.writename("blocklength"); writer.writeint32(t.getblocklength()); writer.writename("pointvalue"); writer.writedouble(t.getpointvalue()); //writing arraylist of ras writer.writename("assigned"); writer.writestartarray(); (ra ra : t.getrasonduty()) { codec racodec = codecregistry.get(ra.class); ec.encodewithchildcontext(racodec, writer, ra); } writer.writeendarray(); writer.writeenddocument(); } @override public class<dutyblock> getencoderclass() { return dutyblock.class; } @override public dutyblock decode(bsonreader reader, decodercontext dc) { reader.readstartdocument(); codec<localdate> datecodec = codecregistry.get(localdate.class); reader.readname(); localdate startdate = datecodec.decode(reader, dc); reader.readname(); localdate enddate = datecodec.decode(reader, dc); reader.readname(); int blocklength = reader.readint32(); reader.readname(); double pointvalue = reader.readdouble(); //reading arraylist of ras reader.readname(); codec<ra> racodec = codecregistry.get(ra.class); arraylist<ra> rasonduty = new arraylist<>(); reader.readstartarray(); while (reader.readbsontype() != bsontype.end_of_document) { rasonduty.add(racodec.decode(reader, dc)); } reader.readendarray(); reader.readenddocument(); return new dutyblock(startdate, enddate, blocklength, pointvalue, rasonduty); } }
dutyblockcodec
depends on codec, , requires codecregistry
passed in on constructor. while believe possible create codecregistry
localdatecodec
, pass argument dutyblockcodec
's constructor, create codecregistry
containing both localdatecodec
, dutyblockcodec
, rather confusing, , mongodb provides functionality, codecprovider
facilitate process.
using codecprovider
interface, wrote dutyblockcodecprovider
public class dutyblockcodecprovider implements codecprovider { @override public <t> codec<t> get(class<t> type, codecregistry cr) { if (type == dutyblock.class) { return (codec<t>) new dutyblockcodec(cr); } return null; } }
i added these codecproviders
mongodb client using codecregistries.fromproviders()
method.
codecregistry codecregistry = codecregistries.fromregistries( codecregistries.fromcodecs(new localdatecodec()), codecregistries.fromproviders( new racodecprovider(), new dutyblockcodecprovider(), new scheduleddutycodecprovider()), mongoclient.getdefaultcodecregistry()); mongoclientoptions options = mongoclientoptions.builder() .codecregistry(codecregistry).build(); mongoclient = new mongoclient(new serveraddress(), options); db = mongoclient.getdatabase("dutyschedulerdb");
my source code project can found @ https://github.com/desrepair/dutyscheduler i'm open answering questions people may have.
Comments
Post a Comment