Reputation: 446
My problem is to cast MongoDB
document in one type :
The getCollection
javadoc
says :
/**
* Gets a collection, with a specific default document class.
*
* @param collectionName the name of the collection to return
* @param documentClass the default class to cast any documents returned from the database into.
* @param <TDocument> the type of the class to use instead of {@code Document}.
* @return the collection
*/
<TDocument> MongoCollection<TDocument> getCollection(String collectionName, Class<TDocument> documentClass);
Here my implementation :
public class AccountDAO {
public static FindIterable<AccountDTO> accountPersist(AccountDTO accountDTO){
MongoCollection<AccountDTO> accountDataCollection = Utils.getDbCollection();
accountDataCollection.insertOne(accountDTO);
return accountDataCollection.find();
}
}
and the getDbCollection
:
public static MongoCollection<AccountDTO> getDbCollection() {
MongoDatabase db = Utils.getDbConnect();
MongoCollection<AccountDTO> accountDataCollection = null ;
accountDataCollection = db.getCollection(AccountDTO.COLLECTION_NAME,AccountDTO.class);
return accountDataCollection;
}
CodecImplementationProvider :
package utils;
import org.bson.BsonReader;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecRegistry;
import digester.Account;
import digester.Customer;
import dto.AccountDTO;
// the Codec extends two interfaces: Encoder<T>, Decoder<T>
class MyAccountDTOImpCodec implements Codec<AccountDTO> {
private CodecRegistry codecRegistry;
public MyAccountDTOImpCodec(CodecRegistry codecRegistry) {
this.codecRegistry = codecRegistry;
}
public void encode(BsonWriter writer, AccountDTO doc, EncoderContext encoderContext) {
writer.writeStartDocument();
writer.writeName("IBAN");
writer.writeString(doc.getIBAN());
writer.writeName("customerFirstName");
writer.writeString(doc.getCustomerFirstName());
writer.writeName("customerLastName");
writer.writeString(doc.getCustomerLastName());
writer.writeEndDocument();
}
public Class<AccountDTO> getEncoderClass() {
return AccountDTO.class;
}
public AccountDTO decode(BsonReader reader, DecoderContext decoderContext) {
reader.readStartDocument();
String iBAN = reader.readString("IBAN");
String firstName = reader.readString("customerFirstName");
String lastName = reader.readString("customerLastName");
double balance = reader.readDouble("balance");
String currency = reader.readString("currency");
long customerId = reader.readInt64("customerId");
reader.readEndDocument();
Account account = new Account(iBAN, balance, currency);
Customer customer = new Customer(firstName, lastName, customerId, account);
AccountDTO doc = new AccountDTO(account, customer);
return doc;
}
}
CodecProvider :
package utils;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecProvider;
import org.bson.codecs.configuration.CodecRegistry;
import dto.AccountDTO;
class MyCodecProvider implements CodecProvider {
public <T> Codec<T> get(Class<T> myClass, CodecRegistry codecRegistry) {
if (myClass== AccountDTO.class) {
return (Codec<T>) new MyAccountDTOImpCodec(codecRegistry);
}
return null;
}
}
When running my test with JUnit
I got this stack :
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class dto.AccountDTO.
I think it's a bad implementation, in Node.js
I would have send my json
object, seems weird to send a java
object to MongoDB
.
Is it just a bad interpretation of javadoc
or kind of lack in my code ?
Upvotes: 0
Views: 5831
Reputation: 926
You have to implement a Codec for your Java class and then MongoDB will be able to decoding a BSON value into a Java object and encoding a Java object into a BSON value. Take a look this Mongo Java Driver Doc: http://mongodb.github.io/mongo-java-driver/3.0/bson/codecs/
This would be your the POJO class representing the documents in the MongoDB collection:
class MyDocument {
private String id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "MyDocument [id=" + id + ", name=" + name + "]";
}
}
We need to create a class that implements the Codec interface, which, in addition is extending the interfaces: Encoder<T>
and Decoder<T>
. This class will provide the methods require to encode and decode our MyDocument Java objects to BSON documents.
class MyDocumentImpCodec implements Codec<MyDocument> {
private CodecRegistry codecRegistry;
public MyDocumentImpCodec(CodecRegistry codecRegistry) {
this.codecRegistry = codecRegistry;
}
public void encode(BsonWriter writer, MyDocument doc, EncoderContext encoderContext) {
writer.writeStartDocument();
writer.writeName("_id");
writer.writeString(doc.getId());
writer.writeName("name");
writer.writeString(doc.getName());
writer.writeEndDocument();
}
public MyDocument decode(BsonReader reader, DecoderContext decoderContext) {
reader.readStartDocument();
String id = reader.readString("_id");
String name = reader.readString("name");
reader.readEndDocument();
MyDocument doc = new MyDocument();
doc.setId(id);
doc.setName(name);
return doc;
}
public Class<MyDocument> getEncoderClass() {
return MyDocument.class;
}
}
A CodecProvider is a factory for Codec instances.
class MyCodecProvider implements CodecProvider {
public <T> Codec<T> get(Class<T> myClass, CodecRegistry codecRegistry) {
if (myClass == MyDocument.class) {
return (Codec<T>) new MyDocumentImpCodec(codecRegistry);
}
return null;
}
}
CodecRegistry class contains a set of Codec instances that are accessed according to the Java classes that they encode from and decode to. In our example, CodecRegistry instance is only getting the MyCodecProvider that we defined previously and the default codec registries.
public static MongoCollection<AccountDTO> getDbCollection() {
// ...................................................
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromProviders(new MyCodecProvider()),
MongoClient.getDefaultCodecRegistry());
MongoClientOptions options = MongoClientOptions
.builder()
.codecRegistry(codecRegistry)
.build();
// ...................................................
MongoClient mongoClient = new MongoClient(MONGODB_SERVER_IP, options);
MongoDatabase = db = mongoClient.getDatabase(MONGODB_SERVER_DATABASE_NAME);
MongoCollection<MyDocument> collection = db.getCollection(
MONGODB_SERVER_COLLECTION_NAME,
MyDocument.class);
return collection;
}
Example of implementation DAO methods:
public static void getDocument() {
FindIterable<MyDocument> iterator = collection.find();
for (MyDocument doc : iterator) {
System.out.println(doc);
}
}
public static void insertDocument() {
MyDocument doc = new MyDocument();
doc.setId("1001");
doc.setName("myName");
collection.insertOne(doc);
}
Upvotes: 4