WEBSERVICE Y ACCESO A BASE DE DATOS

Cuando hablamos o estudiamos WebServices nos aparece una infinidad de métodos y tecnologías desde los benditos WSDL, pasando por JSON, AXIS, SOAP, RPC y un largo etcétera. Si le sumamos a ello el acceso a base de datos y sus respectivas transacciones, la cosa se complica mas. Para ello, benévolamente, las grandes empresas tecnológicas nos ofrecen una y otra y otra más abstracción para que el desarrollo sea mas intuitivo y fácil de actualizar. Pero la pregunta del millón es: de verdad es más intuitivo y fácil de actualizar, además de rápido? Si ya todo esto tiene su problemática y su discusión aparece en la escena de esta tragicomedia tecnológica las aplicaciones móviles. Vemos todo tipo de aplicaciones móviles, miles, millones. Sin embargo, muy pocas apps son herramientas transaccionales/administrativas. Tenemos apps sociales, de multimedia, juegos, herramientas de productividad, editores, información, etc.. Muy pocas consideran las transacciones Multi usuario, Multi nivel en tiempo real, es decir: crear una orden de compra, que la reciba el proveedor, que el proveedor envíe la orden, que la empresa lo reciba, que el inventario crezca, que la orden de venta se abastezca, que la venta se realice, que el cliente vea el avance de su pedido y que finalmente el cliente tenga su pedido. Muy pocas aplicaciones móviles lo hacen. Por qué? La respuesta que todo escuchamos es que las aplicaciones móviles no nacieron para reemplazar una laptop o pc y que son siempre un soporte de un sistema central y no una terminal de un sistema central. Pero la verdad es que no es tan fácil y sencillo crear aplicaciones de este tipo, regresando, porque tanto los webservices y las tecnologías de acceso a base de datos son rudimentarias, lentas e inseguras.

Deseo aportar y exponer al grupo de JAVA Mexico, lo que aún no he leído en los blogs y que puede servir como guía para desarrollar WebServices y acceso a base de datos de forma sencilla, fácil de actualizar y múltiple plataforma, es decir accediendo desde un dispositivo
móvil o desde una laptop o desktop. Para ello vamos a hacer todo, absolutamente todo con la técnica POJO (Plain Old Java Object) en lo posible evitaremos librerías de terceros y vamos a pasar por alto los WebService para ir a los ServLets y hasta allí llegará nuestro "dogmatismo" tecnológico. Todo lo demás se hará con clases y colecciones JAVA sin ninguna capa, abstracción o seguridad encriptada, la cual no tiene ningún sentido cuando tenemos la "serialización" de los objetos.

Receta? Nada del otro mundo: un servidor que acepte Servlets y JAVA eso es todo. Si queremos por el momento olvidarnos del manejo de las conexiones a base datos, utilizaremos, sólo por ahora y hasta que lleguemos a ese punto la librería UCP (Universal Connection Pool) de Oracle.

Base de datos? la que deseen. Obviamente accederemos a través de JDBC. Y no hay más niveles de abstracción, necesarios para esta primera
parte.

Olvidemonos por un momento de scrum sprint jboss jsp, jsf, hibernate, firebase y centremonos solo en JAVA.

Lo primero que deberemos desarrollar desde CERO es un RowSet que pueda transaccional, paginar, enviar y recibir archivos, sentencias y datos desde y hacia el Servelets (WebService). Luego, crear nuestro WebService lo más sencillo, fácil, rápido y práctico. Finalmente, crearemos una interface o Device que irá y vendrá desde el cliente al servidor y viceversa sin ningún "esqueleto" ni sincronización RPC de los métodos ni nada parecido. Sólo una interface o Device que hará de transporte entre el cliente y el servidor llevando y trayendo un RowSet con datos y/o directivas transaccionales.

Verán en este Blog muchos conceptos ya aceptados desmitificarse hasta perder todo el sentido de su abundante código, sin ningún sentido práctico. Dirán, de que esta hablando este "chavo" ?.

Les voy a dar un avance. Quien no ha usado y adaptado "CachedRowSetImpl" o a utilizado JPA con Hibernate a una estructura de base de datos relacional u objeto. Sabían ustedes que no es necesario conocer el tipo de objeto?. Sólo es necesario tomar el objeto, modificarlo o agregar un nuevo objeto, enviarlo a la base de datos y se grabará correctamente sin necesidad de haber conocido nunca el tipo de datos ?

Así es y no somos adivinos. Sólo debemos saber cómo preguntar y que recibir a la hora de una transacción. Cuando hacemos un "Select" no decimos cuál campo es y que tipo de valor, sencillamente lo llamamos y tomamos el "ResultSet". Este "ResultSet" nos representa los campos como objetos, sencillamente como objetos, si uno de estos objetos modificamos y lo regresamos para grabar, paradójicamente, se modificara el o los datos que corresponda en la base de datos sin que en ningún momento hayamos conocido el tipo de valor de ese objeto.

Es obvio que si el campo es "IMPORTE" no vamos a ingresar el Nombre. Si el campo es FECHA no vamos a Ingresar el IMPORTE. El imput o let de los datos será "lógicamente" solicitado para que el usuario lo entienda, por lo tanto agregaremos un BEAN que solicitará un valor FECHA, IMPORTE O ALFANUMERICO PARA EL NOMBRE. Si nuestro LABEL dice "Ingrese Importe" y agregamos un BEAN de FECHA obviamente desde el FRONDEND habrá un ERROR MUY EVIDENTE.

Bien, ya el usuario ingreso los valores que corresponde en los BEANS y ahora debemos enviar al servidor o al webservice o servelet para que se grabe. Todos los Beans incluidos los de terceros nos regresa el valor "objeto". Muy bien, solo enviamos ese objeto sin importar de que tipo es y la transacción se hace correctamente.

AHORA BIEN, la pregunta del millón es: De qué nos sirve en la recuperación y en la transacción conocer el "tipo de dato" ? Yo les digo: Ninguno.

Todo esto que puede ser cuestionable, se los demostraré con ejemplos prácticos. Sólo necesitamos como dije: Un servidor que soporte Servlet, JAVA y eso es todo.

Gracias por leer y en la próxima vez comenzaremos con desarrollar nuestro "ecosistema" de RowSet.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de amohr

ROWSET 1 de 100

Primera línea de un ROWSET creado a través de lo que todos conocemos....

public class JAMRowSet extends com.sun.rowset.CachedRowSetImpl {

Primera línea de un ROWSET creado a través de lo que deseamos hacer....

public class SMXRowSet implements java.io.Serializable, Cloneable {

La clave es que toda clase que viaje hacia y desde el servidor debe ser Serializable y Clonable.
Las colecciones de JAVA serán nuestras únicas herramientas para crear nuestra matriz de datos. (Serializables y Clonables por Defecto)

Imagen de amohr

ROWSET 2 de 100

Crearemos una clase que representará el campo/fila de nuestra matiz, no se preocupen, una vez que entendamos que va esto, les entrego el código completo que podrán modificarlo y mejorarlo de acuerdo a sus necesidades.

public class SMXRowSetField implements java.io.Serializable, Cloneable {

Luego crearemos 2 colecciones una será LAS COLUMNAS Y CONFIGURACION DE LAS MISMA.
La otra colección almacenará las filas recuperadas......

COLUMNAS
private LinkedHashMap htbHeader = new LinkedHashMap();

FILAS
private LinkedHashMap> htbDatos = new LinkedHashMap>();

Deliberadamente dejare que vean bien estas dos colecciones y "adivinen" o "intuyan" algo importante que se ven en ellas.................

Por qué usamos LinkedHashMap, simplemente para eliminar el tema del ORDEN de las Columnas, esta es una colección que mantiene el orden de entrada,
este orden de entrada se da por como hayamos diseñado la tabla o la vista. Lo mismo sucede con las FILAS se mantiene el ORDEN con que fue recuperado los datos.

Si vemos en la COLECCION de las COLUMNAS hay una ENTRADA DE CLAVE que representa el Nombre de la Columna y luego la CLASE que hemos creado de la Columna.....

En la segunda COLECCION donde recuperaremos los datos en FILAS, tenemos como CLAVE la CLASE DE LA COLUMNA que representa EL PRIMERY KEY, obviamente no podemos recuperar ningún dato que no tenga un ID, bien, esa columna que nos indica el ID es quien nos identifica la FILA de los datos.
En esta segunda COLECCION vemos que se almacena un VECTOR de objetos que representa la FILA de la base de datos recuperada.

Finalmente tenemos otra colección mucho más simple que es la siguiente

private Vector vctFindDatos = new Vector();

Esta colección es un Colección CLONADA que se sincroniza con el CAMPO O COLUMNA DE LA PRIMARY KEY para poder buscar en la COLECCION DE LAS FILAS.... Esto sirve para que la búsqueda de las filas sea más rápida y no tengamos que manipular una MATIZ muy cargada con datos.... con esta COLECCION posicionamos el ID, la buscamos y luego solo por referencia sin ningún FOR WHILE, tomamos los datos de esa fila.

Sólo con estas 3 colecciones formaremos nuestro propio ROWSET que irá y vendrá del servidor sin ninguna capa de abstracción.

Imagen de amohr

ROWSET 3 de 100

Antes de seguir es importante resaltar dos aspecto, que es obviamente de conocimiento general para los desarrolladores de JAVA. Sin embargo, lo sabemos pero no lo aplicamos en forma profesional y de análisis. TODAS LAS CLASES O VALORES EN JAVA SON REFERENCIALES. Es decir son byRef y NO byVal. Hacer una clase o asignar un objeto como VALOR, es necesario clonar el Objeto y tiene su costo de tiempo y programación Y NO SIEMPRE ES ACONSEJABLE. Sin embargo si vamos a trabajar con un Objecto que irá al Servidor, es necesario ROMPER esa referencia para que pueda llegar al servidor sin ERROR. Ahora, la pregunta es cómo mantenemos una REFERENCIA que no existe con nuestro objeto?. Lo podemos hacer recibiendo y enviando el mismo objeto hacia el CLIENTE. Con esto, cada vez que el Cliente envíe un OBJECTO CLONADO y SERIALIZADO para enviar al servidor, recibirá el Mismo objeto que envió, más los datos que haya agregado el servidor. Huala.... volvemos a tener un objeto relacionado. Lo único que tenemos que tener en cuenta que cuando recibimos el Objeto del Servidor, no debemos nunca hacer copia o clonar y siempre debemos manipular ese objeto con bloques "synchronized" lo cual debemos regresar al cliente el mismo objeto, manteniendo el mismo "serialVersionUID" con que se inicio en el cliente.

Considerando este principio y que como dije, todo será Colecciones, el punto en las colecciones MAP o con claves, es que esas claves siempre deben ser un objeto instanciado por una clase nuestra. NUNCA agreguemos una Clave que sea un objeto propietario de JAVA como un String o un Integer.

Por ejemplo, creamos una clase Key para subir y bajar archivos

public class SMXFilesKey implements java.io.Serializable, Cloneable {

Luego creamos una colección....

private LinkedHashMap SMXFilesKey, byte mapFiles = new LinkedHashMap SMXFilesKey, byte"

Instanciamos la clase SMXFilesKey allí le pasamos el nombre, el tipo de archivo, etc... cualquier otro dato y como valor
el archivo serialiado obviamente como byte[].

Estos principios son los mismos que vamos a usar con nuestro ROWSET.