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

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -