Almacenar objetos java en Base 64 en una base de datos - Más allá de lo que ves

martes, 13 de noviembre de 2012

Almacenar objetos java en Base 64 en una base de datos


Con el objetivo de almacenar objetos Java por ejemplo que representan en una herramienta de reporting el formulario de filtro para que los usuarios puedan obtener sus propios listados, así como guardarlos y poder reutilizarlos he echado un vistazo al código de SugarCRM para ver como lo hacen ellos.

Por lo que he podido comprobar, guardan en la tabla de consultas guardadas (saved_search para los curiosos) el propietario de la consulta, el módulo sobre el cual esta disponible, clientes, oportunidades... y un String como el que podeis ver al final del correo. Algo parecido ya había visto en Asp.Net si no recuerdo mal.

El caso es que ese chorizo no es otra cosa que un array en php con todos los parametros necesarios para montar el formulario de la consulta, serializado y luego codificado en Base 64.

Para utilizarlo a la hora de mostrar el formulario de consulta descodifican en Base 64 la cadena y posteriormente la deserializan.

Siguiendo un patrón como este para Java he construido un pequeño código que hace lo mismo pero con un objeto Java que puede representar nuestro ConsultaEntidadForm del dominio, pero tenemos un pequeño problema. Si almacenamos el String y posteriormente sobre ConsultaEntidadForma hago un cambio compilo y actualizo, nos saltará una excepción cuando intentemos recuperar el objeto de la base de datos, el motivo no es otro que las versiones de la clase Java almacenada en la base de datos mediante el String en Base 64 y la versión de la clase Java cargada en la aplicaicón serán diferentes.

Así pues en lugar de serializar y codificar en Base 64 lo que he hecho es pasar Java a JSON y codificar a Base 64 con esto cuando debemos recuperar el proceso es descodificar Base 64 y pasar a JSON y mapear el JSON a nuestro objeto Java de modo que ya no habrá Excepción.

Dejo un pequeño ejemplo de lo sencillo que es el proceso en ambos sentidos, las únicas librerías necesarias son Commons Codec y Jackson Mapper:

import java.io.IOException;

import org.apache.commons.codec.binary.Base64;
import org.codehaus.jackson.map.ObjectMapper;

public class SaveJsonSavedSearch {

    public static void main(String args[]) throws IOException {    
        // Instanciar el objeto que vamos a usar.
        SavedSearch m = new SavedSearch(1, "javi", "montesinos");                    
        m.getCursos().add(1);
        m.getCursos().add(222);
     
        // Instanciar el helper para convertir Java a JSON y JSON a Java
        ObjectMapper mapper = new ObjectMapper();            
     
        // Pasar Java a un JSON como array de Bytes para codificar en base 64
        byte[] jsonBytes = mapper.writeValueAsBytes(m);
        // Codificar json en bytes a una cadena base64
        String s = Base64.encodeBase64String(jsonBytes);
        // Guardar el objeto en un campo de la base de datos.
        System.out.println("Guadar formulario de consulta en la base de datos : " + s);  

        // Recuperar objeto en base 64 de la base de datos y decodificar a un array de bytes
        String savedSearchValue = "eyJpZCI6MSwiY3Vyc29zIjpbMSwyMjJdLCJhcGVsbGlkbyI6ImphdmkiLCJub21icmUiOiJtb250ZXNpbm9zIn0=";
        byte[] dataDos = Base64.decodeBase64(savedSearchValue);
     
        // Mapear el array de bytes a un objeto SavedSearch
        SavedSearch o = mapper.readValue(dataDos, 0, dataDos.length, SavedSearch.class);
        if(o instanceof SavedSearch){
            System.out.println(o.toString());
        } else {
            System.out.println("Noooooooooooooooop !");
        }                      
    }
}

Veré la forma de poder guardar directamente el objeto Java serializado, si la hay.

String en Base 64 que representa el objeto que deseamos guardar:

YToyNzp7czoxMzoic2VhcmNoRm9ybVRhYiI7czoxNToiYWR2YW5jZWRfc2VhcmNoIjtzOjU6InF1ZXJ5IjtzOjQ6InRydWUiO3M6MjI6ImN1c3RvbUVuaGFuY2V
kUXVlcnlTZXQiO3M6MDoiIjtzOjI3OiJjYW1wYW5hX2FjdGl2YV8xX2NfYWR2YW5jZWQiO2E6MTp7aTowO3M6MjoiVEQiO31zOjI1OiJjYW1wYW5hX3Npbl92c
19jX2FkdmFuY2VkIjtzOjA6IiI7czoyOToiYmxhbnF1ZW9fY2FwaXRhbGVzX2NfYWR2YW5jZWQiO3M6MDoiIjtzOjMzOiJjYW1wYW5hX3Npbl92aWdpbGFuY2lh
X2NfYWR2YW5jZWQiO3M6MDoiIjtzOjI3OiJjYW1wYW5hX2RlX2JhamFzX2NfYWR2YW5jZWQiO3M6MDoiIjtzOjI5OiJjYW1wYW5hX3ByZXZlbnB5bWVfY19hZ
HZhbmNlZCI7czowOiIiO3M6MjA6ImxpbmVhXzkwMF9jX2FkdmFuY2VkIjtzOjA6IiI7czoyNjoidmlhX3dlYl9wcmV2aW5nX2NfYWR2YW5jZWQiO3M6MDoiIjtzOj
I3OiJ2aWFfd2ViX3ByZXZlbmlyX2NfYWR2YW5jZWQiO3M6MDoiIjtzOjQ6IkVTT3AiO2E6Mzp7aTowO3M6MjoiT1IiO2k6MTtzOjI6Ik9SIjtpOjI7czozOiJBTkQiO3
1zOjg6IkVTT3BQb3N0IjthOjM6e2k6MDthOjE6e2k6MDtzOjA6IiI7fWk6MTthOjE6e2k6MDtzOjA6IiI7fWk6MjthOjE6e2k6MDtzOjA6IiI7fX1zOjExOiJFU0FkZE1v
ZHVsZSI7YTozOntpOjA7czo4OiJBY2NvdW50cyI7aToxO3M6ODoiQWNjb3VudHMiO2k6MjtzOjg6IkFjY291bnRzIjt9czoxMDoiRVNBZGRGaWVsZCI7YTozOntp
OjA7czoxNjoiYWN0aXZpZGFkX2MtdGV4dCI7aToxO3M6MTY6InNpY19jb2RlLXZhcmNoYXIiO2k6MjtzOjE2OiJjZW50cm9zX3ZzX2MtaW50Ijt9czoxMzoiRVNB
ZGRPcGVyYXRvciI7YTozOntpOjA7czo0OiJMSUtFIjtpOjE7czo2OiJFTkRJTkciO2k6MjtzOjI6IkVRIjt9czoxMToiRVNBZGRTZWFyY2giO2E6Mzp7aTowO3M6Mjo
iNDMiO2k6MTtzOjI6IjEyIjtpOjI7czoxOiIyIjt9czo3OiJFU09wUHJlIjthOjM6e2k6MDtzOjA6IiI7aToxO3M6MDoiIjtpOjI7czowOiIiO31zOjk6InNob3dTU0RJViI7czo
yOiJubyI7czoxMzoic2VhcmNoX21vZHVsZSI7czo4OiJBY2NvdW50cyI7czoxOToic2F2ZWRfc2VhcmNoX2FjdGlvbiI7czo2OiJ1cGRhdGUiO3M6MTQ6ImRpc3Bs
YXlDb2x1bW5zIjtzOjEyMzoiTkFNRXxQUk9WSU5DSUFfQ3xWQUxPUl9DTElFTlRFX0N8UEhPTkVfT0ZGSUNFfENBTVBBTkFfQUNUSVZBXzFfQ3xDQU1QQU5BX
0FDVElWQV8yX0N8RVNUQURPX0RFTF9DTElFTlRFX0N8QVNTSUdORURfVVNFUl9OQU1FIjtzOjg6ImhpZGVUYWJzIjtzOjQ5MzoiQ0FNUEFOQV9ERV9CQUpBU
19DfEVTVEFET19XRUJfUFJFVkVOSVJfQ3xFU1RBRE9fQ0FNUEFOQV9QUkVWRU5QWU1FX0N8Q0lGX05JRl9DfENBTVBBTkFfUFJFVkVOUFlNRV9DfENBTVBBT
kFfU0lOX1ZTX0N8VklBX1dFQl9QUkVWRU5JUl9DfFZJQV9XRUJfUFJFVklOR19DfExJTkVBXzkwMF9DfEVTVEFET19XRUJfUFJFVklOR19DfEJMQU5RVUVPX0NBU
ElUQUxFU19DfEVTVEFET19MSU5FQV85MDBfQ3xFU1RBRE9fQ0FNUEFOQV9UT1RBTERBVF9DfEVTVEFET19DQU1QQU5BX1ZTX0N8RVNUQURPX0NBTVBBT
kFfQkxBTlFVRU9fQ0FQX0N8Qk9OT19QRU5ESUVOVEVfQ3xGRUNIQV9DT05UUkFUT19WU19DfEVTVEFET19DQU1QQU5BX0JBSkFTX0N8RkVDSEFfQ09OVFJ
BVE9fUFRfQ3xQSE9ORV9BTFRFUk5BVEV8Q0FNUEFOQV9TSU5fVklHSUxBTkNJQV9DfFNJQ19DT0RFfEZJQ0hFUk9TX0xPUERfQ3xNRVNfQkFKQV9QVF9DfE1
FU19CQUpBX1ZTX0N8TU9USVZPX0JBSkFfUFRfQyI7czo3OiJvcmRlckJ5IjtzOjQ6Ik5BTUUiO3M6OToic29ydE9yZGVyIjtzOjM6IkFTQyI7czo4OiJhZHZhbmNlZ
CI7YjoxO30="

1 comentario:

  1. Para hacerlo con objetos Java serializados he puesto una nueva entrada:

    http://www.montesinos.org.es/2012/11/serializar-objeto-java-y-almacenar-en.html

    ResponderEliminar