JDBC
Durante la exposición del capítulo 7 Databases del libro JAVA Distributed
Computing en el Seminario de Algoritmos Distribuidos, hicimos una revisión de JDBC, hablamos de algunos patrones de diseño, discutimos dos arquitecturas esenciales que involucran bases de datos:
- Two-tier
- Este tipo de aplicaciones proveen --idealmente-- varias
estaciones de trabajo con una capa de presentación uniforme
que se comunican con una capa de almacenamiento centralizado.
- Three-tier
- Una arquitectura three-tier agrega una capa al modelo
two-tier que aísla el procesamiento de información en una
localización central y maximinza la reutilización de objetos.
Los acetatos completos de la exposición los puedes ver en Exposición.ps.
Para ejemplificar el uso de JDBC creamos (o modificamos)
algunos ejemplos.
- El más sencillo de ellos es basic.java. Este ejemplo,
es tan simple, que ni siquiera es interactivo. Simplemente teclea:
java basic jdbc:postgresql://abulafia.fciencias.unam.mx/testjdbc patito pato123
Y verás algo como (después de unos cuantos segundos):
PostgreSQL basic test v6.3
Algoritmos distribuidos
Connecting to Database URL = jdbc:postgresql://abulafia.fciencias.unam.mx/testjdbc
Connected...Now creating a statement
Running tests:
performing a query
a=1 b=1
a=2 b=1
a=3 b=1
a=4 b=2
a=4 b=3
a=4 b=4
performing another query
a=4 b=2
a=4 b=3
a=4 b=4
Now closing the connection
- El segundo (no aparece en los acetatos) y no fue explicado
en la exposición por cuestiones de tiempo. Pero aquí está el
código fuente: QueryApp.java. Este
ejemplo, es un monitor muy simple que te permite
ejecutar interactivamente enunciados SQL para cualquier base
de datos desde la línea de comandos. No hay ninguna expliación
especial para ejecutarlo, simplemente teclea un comando como:
java QueryApp patito pato123 jdbc:postgresql://abulafia.fciencias.unam.mx/db_bank
Nota que la línea, arriba expresada funcionará (siempre y
cuando tengas el código compilado de QueryApp.java, el
driver postgresql.jar). Te rogamos ser cuidadoso con lo que haces mientras estás conectado
a nuestro servidor, puedes borrar toda la información de la base de datos
y si alguien más quiere probar este ejemplo ya no lo podrá hacer.
A manera de ejemplo, esta es una muy pequeña sesión de comandos utilizando
este monitor:
Connected to the database.
>
> select * from t_accounts;
2> go
4 rows selected.
-----------------------------------------
|account_id|cust_id|account_type|balance|
-----------------------------------------
| 1 | 1 | C | 0.0 |
| 2 | 1 | C | 95.22 |
| 3 | 1 | S |9375.26|
| 4 | 2 | C | 362.0 |
> quit
Connection closed.
(claro que en un browser esto se ve de forma tal que no parece una tabla,
pero en el shell de Unix, verás algo más decente. Html, no es mi
fuerte y me dio mucha flojera investigar cual es el código de un espacio
en blanco e insertar arriba el número de veces apropiado dicho código.) :-)
Por supuesto que puedes probar este monitor con cualqueir otra
base de datos. Para lo cual, debes instalar tu manejador de
bases de datos, instalar un driver y registrarlo con los
drivers de JDBC para ese tipo particular de manejador
de bases de datos, crear tu base de datos de prueba, crear al
usuario con el cual te piensas conectar (el password, es
opcional y depende del tipo de autenticación que soporte tu
manejador de bases de datos). Obvio, esto parece como una
tarea titánica para probar un simple ejemplo, pero es un buen
ejercicio y todo lo que hagas aquí, bien puedes utilizarlo
para tu proyecto final. :-)
- El último ejemplo, es el único NO trivial de la
exposición. Es la aplicación bancaria, de la cual hablamos una
buena parte de la exposición. Aquí es donde desarrollamos todo
un diseño conceptual bastante complejo, que incluye patrones
de diseño y muchos elementos del lenguaje (y de programacón
distribuida) revisados a lo largo de todas las exposiciones,
como RMI, Threads, etc.
Desafortunadamente, hemos tenido varios problemas tratando de
hacer que la aplicación funcione. En primer lugar, JDK
en su versión para linux no estaba bien configurada (sólo
tenía un par de errores a la hora de calcular las trayectorias
absolutas de algunos de los programas que utilizamos en la
aplicación. Sin embargo, corregir esos errores requirió mucho
tiempo). Resolvimos eso, perfecto, ahora RMI se
comporta bien y hace todo lo que le pedimos (al igual que
javac, java, rmic y rmiregistry, que son
programas que necesitamos usar muy seguido).
La triste historia contínua, en esta ocasión es la
implementación de la biblioteca AWT (Abstract Window
Toolkit). Pensamos (inicialmente) eliminar toda la interface
de usuario definida por Reese; pero eso implicaría reescribir
--prácticamente-- toda la aplicación.
El problema con AWT, al igual que muchas otras
secciones de Java, es que de una versión a otra está
cambiando secciones fundamentales. Más aún, incluso entre
revisiones de la misma versión. La versión de JDK que estamos
utilizando es la 1.1-6. Por esto motivo, aún no funciona. :-(
En el directorio que hemos puesto a su disposición (más
adelante ponemos una liga para bajarlo) se encuentran ambas
versiones. La versión original de Reese (los directorios están
marcados por la cadena "-orig") en teoría debería funcionar
para la versión 1.1 de JDK. Los directorios que no tienen al
final "-orig", están actualizados para reconocer los nuevos
nombres de métodos y variables en la versión 1.1 revisión 6
(qué es la que estamos usando).
En abulafia.fciencias.unam.mx, el servidor en el que hemos
acondicionado el servidor de bases de datos (postgreSQL), la
base de datos (db_bank), tenemos un usuario (patito),
etc. también tenemos corriendo (de manera permanente) el
servidor de aplicación, para que ustedes sólo tengan
que encargarse de ejecutar el cliente (o varios clientes), con
una línea de comandos como:
java bank.client.BankClient abulafia.fciencias.unam.mx
Cuando lo ejecuten, deben ver algo como:
Connecting to app server at abulafia.fciencias.unam.mx...
security properties not found. using defaults.
Connected to server...
En este momento (bueno, unos segundos más tarde) verás salir
una linda ventana como esta:
Nótese que los detalles de la ventana (el borde, los botones
sobre el margen, etc.) pueden cambiar, son dependientes del
manejador de ventanas que utilices.
Hasta este punto, todo va bien. Ya que en la pantalla sólo
vemos:
Connecting to app server at abulafia.fciencias.unam.mx...
security properties not found. using defaults.
Connected to server...
Sin embargo, cuando uno quiere abrir una cuenta (pícando con
el mouse sobre el menú "Account" en la ventana mostrada con
anterioridad) y luego en "Open", obtenemos lo siguiente:
Pero en cuanto le damos un número (válido o inválido, debería
poder recibir prácticametne cualquier cosa) de un cliente
("customer ID"), obtenemos el siguiente conjunto de
excepciones.
- En el server:
java.lang.NullPointerException
at bank.server.Customer.restore(Customer.java:108)
at imaginary.persist.DatabasePeer.restore(DatabasePeer.java:126)
at imaginary.persist.Persistent.restore(Persistent.java:404)
at imaginary.persist.Transaction.restore(Transaction.java:123)
at imaginary.persist.DatabaseTransaction.restore(DatabaseTransaction.java:99)
at imaginary.persist.Persistent.restore(Persistent.java:381)
at imaginary.persist.Persistent.getPersistent(Persistent.java:142)
at bank.server.AppServer.getCustomer(AppServer.java:86)
at bank.server.AppServer_Skel.dispatch(AppServer_Skel.java:40)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:164)
at sun.rmi.transport.Transport.serviceCall(Transport.java:161)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:607)
at sun.rmi.transport.tcp.TCPTransport.run(TCPTransport.java:513)
at java.lang.Thread.run(Thread.java)
- En el cliente:
Exception occurred during event dispatching:
java.lang.NullPointerException:
at imaginary.gui.PersistentPanel.(PersistentPanel.java:47)
at bank.client.CustomerPanel.(CustomerPanel.java:28)
at bank.client.BankClient.loadCustomer(BankClient.java:206)
at bank.client.OpenAccountDialog.actionPerformed(OpenAccountDialog.java:64)
at java.awt.Button.processActionEvent(Button.java:257)
at java.awt.Button.processEvent(Button.java:230)
at java.awt.Component.dispatchEventImpl(Component.java:1781)
at java.awt.Component.dispatchEvent(Component.java:1708)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:81)
Pues ese es el estado, en breve, de todo lo que recibes si bajas
todo el material relacionado con la exposición.
Si no planeas modificar el código (o incluso probarlo)
porque no tienes el tiempo, o no cuentas con los elementos
adecuados (una máquina Unix, un compilador decente de java y una
JVM, etc.). Entonces podemos ponernos de acuerdo para revisar el
código entre todos y tal vez mostrar todos estos programas
funcionando. Eso es todo.
{elisa|solsona}@abulafia.fciencias.unam.mx
Last modified: Thu Nov 19 08:34:11 CST 1998