Estoy jugueteando y publicando una serie de artículos de MongoDB con Java. Y en uno de ellos, me he puesto a mirar cómo utilizar POJOs de Java con MongoDB. La utilización es fácil, o al menos, eso parece con un «Hola Mundo». Pero la cofiguración para que pueda utilizar POJOs es tan fea como la siguiente
PojoCodecProvider pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build();
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
MongoClientSettings.getDefaultCodecRegistry(), CodecRegistries.fromProviders(pojoCodecProvider));
Ni más ni menos que todo eso. Y explicarlo es, si no complejo, al menos largo.
Primero obtener una intancia de un PojoCodecProvider. Eso se hace con el método estático builder(), concatenando algo de configuración automatic(true) para que sea capaz de tratar automáticamente cualquier POJO y finalmente llamando a build(). Nada complicado de momento. Solo explicar que es un CodecProvier en MongoDB y ya de paso, que es un Codec.
Un Codec es una clase que es capaz de convertir una clase nuestra de Java en un documento bson u obtener nuestra clase Java a partir de un documento bson. bson es como json, pero codifcado en binario en vez de texto. Esto hace que no sea legible para un humano, pero sí ocupa menos espacio y es más eficiente para almacenar o transmitir un documento json.
Y un CodecProvider es una clase capaz de crear Codec específicos para clases concretas. En este caso, nuestro PojoCodecProvider será capaz de crear Codec para cualquier clase Java que sea un POJO. Es decir, que tenga un constructor sin parámetros y que tenga atributos con métodos getter y setter
Vale, nada especialmente raro hasta aquí. Ahora toca decirle a MongoDB que utilice este CodecProvider. Para ello, cuando ya tenemos la conexión con MongoDB establecida y queremos obtener una base de datos, le decimos qué CodecRegistry debe usar llamando a withCodecRegistry()
MongoDatabase database = mongoClient.getDatabase("My_Data_Base").withCodecRegistry(pojoCodecRegistry);
Bueno, un nuevo concepto. Tenemos un CodecProvider, pero necesitamos un CodecRegistry. ¿Qué es un CodecRegistry?. Un CodecRegistry es un registro o alamacén de Codec. Ahí guardamos instancias de Codec, todas las que queramos. MongoDB preguntará ahí cuando tenga que convertir una clase Java a un bson o al revés para buscar el Codec adecuado para esa clase concreta.
Pues vaya, hemos creado un CodecProvider pero necesitamos un CodecRegistry. La única diferencia es que el primero crea un Codec nuevo cada vez que se le pide y el segundo sólo te devuelve los que tiene almacenados.
Para obtener un CodecRegistry a partir del CodecProvider, tenemos la siguiente llamada
CodecRegistries.fromProviders(pojoCodecProvider);
Esto devuelve un CodecRegistry a partir del CodecProvider. Una vez hecho esto, parece fácil, sería pasar el CodecRegistry así obtenido a nuestra llamada a withCodecRegistry(). Pero no es tan fácil.
withCodecRegistry() sólo admite un CodecRegistry. Y por defecto, MongoDB tiene ya uno instalado, con otras cosas que no son POJOs y que necesitamos mantener. Este CodecRegistry por defecto se puede obtener con
MongoClientSettings.getDefaultCodecRegistry()
Así que necesitamos construir un CodecRegistry que tenga todos los Codec por defecto más los Codec de POJOs que hemos creado a partir de nuestro PojoCodecProvider
Menos mal que viene en nuestra ayuda CodecRegistries.fromRegistries(). Esta llamada recibe como parámetros varios CodecRegistry y te devuelve un CodecRegistry con todos los Codec de los CodecRegistry que hemos pasado como parámetros
Así que la llamada chorizo
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
MongoClientSettings.getDefaultCodecRegistry(), CodecRegistries.fromProviders(pojoCodecProvider));
nos devuelve el CodecRegistry que queremos, que tiene todos los Codec por defecto de MongoDB más el nuestro de POJOs. Y ese que obtenemos es el que debemos usar en nuestra llamada a withCodecRegistry().
Pues no sé si es complicado o no, retorcido o no, pero sí sé que he echado un rato en entender esa línea críptica rebuscando por la documentación de MongoDB. Y estoy casi seguro que hay formas más fáciles de obtener un registro de Codec con los de defecto más los que queramos sin involucrar de por medio un CodecProvider.