Download Diseño de Conectores JDBC para Bases de Datos en
Document related concepts
no text concepts found
Transcript
Diseño de Conectores JDBC para Bases de Datos en Tiempo Real Autor: Miguel Ángel Oliva Gutiérrez DNI: 28627618R Indice Reflexión Inicial.............................................................................................................................3 1. Introducción ...............................................................................................................................4 2. Herramientas existentes. .............................................................................................................5 2.1 Com2Java .........................................................................................................................5 2.2 Bridge2Java ......................................................................................................................5 3. La BDTR....................................................................................................................................7 3.1 Arquitectura......................................................................................................................7 4. Arquitectura del puente...............................................................................................................8 4.1 Arquitectura global ...........................................................................................................8 4.2 BDTRBridge.dll................................................................................................................9 4.3 BDTRBridge.java ...........................................................................................................10 5. El Proxy ..................................................................................................................................11 5. 1 La capa proxy ................................................................................................................11 6. El Cliente .................................................................................................................................13 6.1 El Cliente de la BDTR ....................................................................................................13 Referencias...................................................................................................................................13 Reflexión Inicial No todas las bases de datos son iguales pero hay que admitir que se han convertido en un producto estratégico de primer orden, al constituir el fundamento de los sistemas de información, especialmente en lo relativo a la toma de decisiones. Las bases de datos en tiempo real (BDTR), debido al volumen de operaciones a las que suelen estar sometidas en cortos intervalos de tiempo y a la criticidad del tiempo de respuesta, no realizan las operaciones sobre disco duro, sino directamente sobre memoria. Es decir, la BDTR reside permanentemente en memoria y sólo se llevan a cabo copias a disco en contadas ocasiones para no perjudicar el rendimiento de las aplicaciones que usan esta base de datos. Por este mismo motivo, las BDTR generlamente se diseñan e implementan en función de las señales a controlar, y se utilizan lenguajes de programación no interpretados, que se compilan en la máquina en la que residirá la BDTR. El resultado suele ser una librería del sistema y por tanto no son accesibles directamente desde una aplicación Java. Este tipo de bases de datos se usan principalmente en sistemas de control y adquisición de datos (SCADA) que guardan los valores obtenidos de campo en esta base de datos. En este trabajo mostramos la estrategia a seguir a la hora de diseñar un puente entre una BDTR y una aplición en Java, de forma que el resultado final sea un conector JDBC, garantizando así la conexión con este tipo de bases de datos. 1. Introducción La evolución de los sistemas de información ha tenido una considerable repercusión en la gestión de los datos, desde que se empezó a automatizar la gestión de las empresas en la década de los sesenta, adquiriendo vital importancia la estructuración de los datos. Surge así, a finales de los sesenta y principios de los setenta, la primera generación de productos de bases de datos en red. En 1970, el Dr. Codd propuso el modelo relacional, que pasó a convertirse en los años ochenta, en la segunda generación de productos de bases de datos, que actualmente domina el mercado. En los últimos años venimos asistiendo a un avance espectacular en la tecnología de bases de datos: multimedia, activas, deductivas, orientadas a objetos, seguras, temporales, móviles, paralelas, con restricciones, etc. Esta nueva generación de bases de datos (la «tercera»), se caracteriza por proporcionar capacidades de gestión de datos, objetos y gestión de conocimiento y pretende responder a las necesidades de aplicaciones tales como: CASE (Ingeniería del software asistida por ordenador), CAD/CAM/CIM, SIG (sistemas de información geográfica), información textual, aplicaciones científicas, sistemas médicos, publicación digital, educación y formación, sistemas estadísticos, comercio electrónico, etc. [1] El acceso a la información vía web implica que las bases de datos que sean accesibles desde Internet deben estar preparadas, si no tienen ningún mecanismo de restricción de acceso, para soportar un número muy elevado de accesos simultáneos realizados por distintos clientes repartidos por todo el mundo. Las BDTRs cumplen este requisito, no en vano están diseñadas para eso. Pero aunque si se pretende acceder a BDTR vía web, las restricciones de respuesta temporal se suavizan, debido al impacto que supone el retraso introducido por la red, el inconveniente que supone la comunicación entre objetos de distinta tecnología: C++ y Java, por ejemplo, es un inconveniente importante que hay que salvar. 2. Herramientas existentes. Existen herramientas muy potentes en el mercado que permiten obtener código fuente Java a partir de otros lenguajes. A continuación enumeramos algunas de ellas: 2.1 Com2Java Com2Java es una herramienta desarrollada por Jintegra [2] que está diseñada para leer la información de una librería de tipos (.olb, .tlb) y generar ficheros Java que puedan usarse para tener acceso a las clases e interfaces COM definidas en dicha librería. Estas librerías de tipos pueden haberse construido con Visual C++ o Visual Basic por ejemplo y pueden encontrarse en otras librerías (.DLL) o en ficheros ejecutables (.EXE). Además de la interfaz en línea de comandos, incorpora una interfaz gráfica de usuario que facilita su manejo. Es capaz de convertir los componentes gráficos de una aplicación implementada en Visual Basic o C++ a componentes equivalentes Java. El inconveniente es que sólo genera los componentes equivalentes del AWT pero no los convierte a componentes de las JFC (Swing), por lo que si necesitamos esta opción tendremos que buscar otra herramienta, retocar el código generado por com2java o generar las clases Java completamente por nuestros propios medios. 2.2 Bridge2Java Bridge2Java es una herramienta desarrollada por IBM [3] que permite a los programas Java comunicarse con objetos ActiveX, facilitando su integración en entornos Java. Haciendo uso de las tecnologías JNI y COM permite que un objeto ActiveX sea tratado como cualquier objeto Java.. El inconveniente principal de esta herramienta es que no genera correctamente los objetos de tipo Variant. Para estos objetos, Bridge2Java genera una clase denominada Jvariant, pero no ha tenido correctamente en cuenta el tamaño de ciertos tipos y su conversion de C++ a Java. Determinados, subclases de Variant, como OleVariant, ni siquiera son generados. Otro problema, que presenta es la irregular liberación de memoria que lleva a cabo, pues mantiene algunas referencias en el objeto Java, de forma que el garbage collector nunca las libera, por lo que se hace un uso extra memoria innecesaria. Estas herramientas tienen un comportamiento bastante bueno cuando se trata de objetos simples, pero como hemos comentado, no siempre generan el código Java correctamente e incluso nos introducen problemas de consumo de memoria en nuestra aplicación. Es por eso que exponemos a continuación los pasos necesarios para constuirnos nuestro propio puente entre Java y COM, a medida, asegurándonos que hasta el más mínimo detalle que necesitemos del objeto COM está correctamente soportado y resuelto en nuestro puente 3. La BDTR Vamos a presentar una arquitectura ejemplo para una BDTR ficticia que nos ilustre el proceso de creación del puente Java-COM. 3.1 Arquitectura La arquitectura de la BDTR se corresponde con un entorno de utilización Cliente-Servidor. La BDTR es un motor de base de datos NO relacional, con optimizaciones de su rendimiento basadas en caché de datos en memoria física. El servidor de base de datos de tiempo real es una aplicación (.EXE) que utiliza una serie de objetos COM para su funcionamiento. La principal función del servidor es manejar las posibles bases de datos registradas y facilitar el enlace entre las bases de datos y los clientes que acceden a ellas. El servidor de la BDTR expone una interfaz, IApplication, para la autentificación del usuario y obtener un objeto DataBase que representa una base de datos. Cada elemento del diagrama anterior está relacionado con una interfaz externa: IApplication, IAppDataBases, IAppTables, IAppIndexes, IAppTriggers y IappFields. IApplication representa la raíz a partir de la cual podemos acceder a todos los demás objetos. Partiendo de un objeto DataBase, como se puede apreciar en el diagrama, es posible acceder a sus tablas, y a partir de éstas a los campos de cada una, y por consecuente al valor concreto de cada campo. Para la consulta y modificación de datos desde clientes se deben establecer unos mecanismos que permitan un flujo de información rápido y sencillo por parte de los distintos módulos del sistema. 4. Arquitectura del puente 4.1 Arquitectura global El motivo principal por el que se hace necesaria la creación del puente es la incompatibilidad directa entre la plataforma Java y la los objetos COM. Para poder hacer uso directamente de la funcionalidad de estos componentes COM es necesario que las clases Java, puedan acceder a los métodos de la BDTR. Estos pueden accederse a través de la librería AppClient.dll a los métodos de la interfaz Iapplication. Para hacer uso de los métodos de AppClient.dll es necesario poder acceder a métodos no escritos en Java. Para ello hacemos uso de JNI, implementando una nueva librería con un conjunto de métodos que serán reflejo de los contenidos en AppClient pero cumpliendo la especificación para métodos nativos indicada en JNI y que estarán definidos en una interfaz Java, tal y como se muestra en la siguiente figura: En la clase BDTRBridge.java se definen todos los métodos nativos que se implementarán en C++ en la librería BDTRBridge.dll. Esta libería será la que se comunique con AppClient.dll. En BDTRBridge.java se definen todos los métodos nativos necesarios, independientemente de que estos estén relacionados con la interfaz IApplication, IAppDataBases, IAppTables, o con cualquier otra, la idea es tener en esta única clase el acceso a todos. La clase BDTRBridge no es sino un conjunto de los métodos que dan funcionalidad a la BDTR. 4.2 BDTRBridge.dll Esta librería constituye la parte nativa (C++) del puente y es la encargada de comunicarse con la librería de la BDTR. Para llevar el control de los clientes que operan con ella simultáneamente, mantiene un vector de IApplication, cuyos índices serán los identificadores de cada cliente, garantizando así la independencia de las operaciones entre clientes distintos. Además, esto mejora el rendimiento de memoria, puesto que cuando un cliente necesite abrir una segunda base de datos u otra tabla, no se creará un objeto IAplication nuevo sino que se usará el que ya se había creado para él. Esta misma filosofía de “cacheo” se repite para los objetos IAppDataBase, IAppIndex, IAppTable e IAppField. Durante el desarrollo del puente se ha observado que es más rápido que un método nativo obtenga el elemento i-ésimo del vector, y construir luego el vector en la parte Java, antes que obtener todos los elementos y construir el vector en el método nativo para posteriormente devolver el objeto Vector a la parte Java. Por eso este tipo de procesos se ha implementado en Java mediante métodos que llaman repetidamente (tantas como elementos tenga el vector) a otros métodos nativos que obtienen un elemento del vector dada su posición (a la que llamamos comúnmente identificador). Obviamente también es necesario disponer de un método nativo que nos informe del número de elementos de que dispone el vector. Esta es la filosofía principal bajo la que se ha construido el puente. Es importante también hacer notar la existencia de unos métodos de inicialización en BDTRBridge.dll (en el código de Bridge.cpp). Puesto que, según la especificación de JNI, las instrucciones que más negativamente influyen en la rapidez de la comunicación entre la parte Java y la parte nativa, son aquellas en las que se ha de averiguar los identificadores de los atributos y métodos de la clase Java para interactuar con ellos desde la parte nativa (por ejemplo lanzar una excepción, obtener el valor de un objeto, comprobar tipos...), estos identificadores se han hallado en la inicialización, por lo que sólo se efectúan al cargar la librería desde la clase java y nunca más después. ¿Como conseguimos la interacción entre objetos genéricos java (clase java.lang.Object) y la BDTR? Esto se ha conseguido mediante la elaboración de una clase proxy del tipo Variant, que hemos llamado JVariant y que puede contener cualquier objeto. Para ello se ha definido también una clase, COMConstants que define las constantes empleadas en COM para algunos tipos y que da soporte a la clase JVariant. Como ya hemos dicho, la librería BDTRBridge.dll, mantiene una serie de vectores que guardan los punteros a los objetos creados por AppClient.dll. De esta forma no se crean excesivos objetos en memoria. Cuando un cliente termina de usar un objeto, el puntero ya no es necesario que siga siendo almacenado y se elimina del vector. Así tenemos vectores para almacenar los punteros a objetos IApplication, IAppDataBase, IAppIndex, IAppTable e IAppField. 4.2.1 Ejemplo de funcionamiento Queremos abrir una base de datos de la BDTR. • Si no se había creado un cliente previamente para nosotros, primero se crea nuesto cliente. Este cliente se insertará en el vector de clientes (punteros a IApplication) y se devolverá como identificador para el mismo al posición que ocupa en el vector. • Después con el identificador de este cliente indicaremos que se abra la base de datos cuyo nombre indicamos. Para ello se cogerá el puntero a IApplication que ocupa la posición indicada por el identificador de nuestro cliente y se obtendrá el puntero a la base de datos (IappDataBase*) de éste cuyo nombre se ha indicado. Esta puntero a la base de datos se insertará a su vez en el vector de punteros a bases de datos, devolviéndose la posición que ocupa en el vector como identificador. Para los demás casos, índices, tablas, y campos, el procedimiento es el mismo, por lo que como podemos apreciar siempre se trabaja en la parte Java con identificadores, números al fin y al cabo, y nunca con objetos o referencias. El trabajo con punteros se realiza en BDTRBridge.dll y el verdadero trabajo con los objetos es realizado en la propia librería de la BDTR, AppClient.dll. 4.3 BDTRBridge.java Esta clase constituye la parte Java del puente. En ella se definen todos los métodos nativos que se implementan en BDTRBridge.dll y que se carga en el bloque estático de la clase, en el que se inicializa dicha dll también mediante una llamada al método nativo initialize. 5. El Proxy 5. 1 La capa proxy La capa proxy tiene por objetivo la abstracción del puente y a capas superiores. Para ello se crean objetos similares a los existentes en la BDTR, con una funcionalidad similar, consiguiendo objetos Client, DataBase, Table, Index y Field. Client : Permite logarse en la BDTR, abrir y cerrar bases de datos, así como obtener el nombre de todas las bases de datos de la BDTR. DataBase: Representa un proxy de la interfaz IAppDataBase definida e implementada en AppClient.dll. Permite realizar las operaciones típicas de una base de datos: abrir una tabla, consultar las tablas que tiene, el nombre de la base de datos... Table: Representa un proxy de la interfaz IAppTable definida e implementada en AppClient.dll. Permite realizar las operaciones necesarias con una Tabla de una base de datos de la BDTR: Obtener su nombre, el numero de registros que tiene, obtener el nombre de todos los índices que tiene, la posición del registro seleccionado actualmente, moverse directamente a un registro, abrir un índice... Index: Representa un proxy de la interfaz IAppIndex definida e implementada en AppClient.dll. Permite realizar las operaciones necesarias con un índice de una tabla, tales como buscar el registro cuyos campos del índice coincidan con unos dados, obtener los campos que indexan la tabla, obtener la posición actual... Field: Representa un proxy de la interfaz IAppField definida e implementada en AppClient.dll. Permite realizar las operaciones necesarias con un campo de un indice o tabla de la base de datos. Estas operaciones permiten obtener y modificar el valor del campo, obtener su nombrey descripción, comprobar si es o no nulo,... Tanto un índice como una tabla poseen además una serie de operaciones comunes definidas en una clase abstracta: DataSet. Estas operaciones permiten entre otras cosas comprobar si se ha llegado al final o principio, establecer y obtener un filtro, y moverse al siguiente, anterior, primer o último registro, tanto para una tabla como para un índice. Todas estas clases se comunican con su clase origen de la BDTR, y a la cual representan, mediante los métodos definidos en BDTRBridge.java, que mediante JNI consiguen la comunicación, como hemos explicado, con la dll. Estos objetos pueden crearse en el orden en que hemos descrito, a partir del Client. Para crear el client, deberemos hacerlo mediante alguno de los métodos createClient de la clase BDTRProxy que constituye el punto de acceso a la capa desde el cliente de la BDTR. 6. El Cliente 6.1 El Cliente de la BDTR El cliente de la BDTR nos facilita, haciendo uso de la capa proxy, crear y ejecutar consultas. Nos permite incluso crear consultas parametrizadas, dónde los parámetros serán cadenas entre entre signos de tanto por ciento (%). El cliente nos permite obtener mediante una única instrucción (executeAll) en la consulta, todo el conjunto de registros que cumplen una determinada condición en una tabla o índice de una determinada base de datos en BDTR, aumentando así la potencia de la misma. Igualmente nos permite obtener un registro de resultado cada vez mediante el método execute. El cliente de la BDTR se crea a con la clase BDTRProxy de la capa Proxy, anterioremente comentada. En este submódulo se dispone de una factoría de creación de clientes, BDTRClientFactory, para el caso de existencia de más de una clase que cree el cliente, poder indicarlo explícitamente. En este submódulo disponemos de dos interfaces que nos definen dos comportamientos ligeramentediferentes según nuestra consulta sea por filtro (ParametrizedFilterQuery) o por valor (ParametrizedValuesQuery), que heredan de la interfaz Query y cuyas implementaciones heredan ambas de AbstractParametrizedQuery. Los resultados de las ejecuciones de las consultas son recogidos en un objeto definido por la interfaz Result. Referencias [1] Mario Piattini, (2000). La evolución de las bases de datos. NOVATICA / may.-jun. 2000 / Especial 25 aniversario. pp 100-101 [2] Fedora User Interface Projects: http://www.fedora-commons.org/confluence/display/DEV/Fedora+User+Interface+Projects [3] University of Meriland. Java IU Tools http://otal.umd.edu/guse/uijava.html