28 marzo 2008

El objeto Application

Todas las aplicaciones Win32 que se crean con Delphi tienen definido un objeto global accesible desde cualquier formulario o unidad llamado Application, de la clase TApplication, el cual esta definido dentro de la unidad Forms. Este objeto se encarga de encapsular todo lo referente a nuestra aplicación, evitando el tener que procesar el envío y recepción de mensajes como ocurre cuando se programa en C/C++ mediante las funciones PeekMessage y SendMessage.

De hecho, si miramos la unidad DPR de cualquier proyecto de Delphi podemos ver como el objeto Application se incializa, después llama al formulario principal y posteriormente comienza la ejecución de la aplicación mediante el método Run:

program Project1;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

Este código fuente cambia dependiendo de las preferencias que tengamos a través del menú Project -> Options (pestaña Forms). Todos los formularios que pongamos en la sección Auto-create forms serán los que se creen después de Application.Initialize.

Windows funciona internamente como un buzón donde van llegando mensajes y los va procesando en el orden de llegada, consiguiendo así el efecto de multitarea, aunque internamente sólo puede procesar un mensaje a la vez (menos en los últimos sistemas con procesador de dos o más núcleos).

El objeto Application nos abstrae de toda esta complejidad interna y se encarga de controlar todos los eventos que se producen en nuestra aplicación. Si queremos modificar el comportamiento de nuestra aplicación para ciertos eventos, tenemos en la pestaña Additional el componente ApplicationEvents que podemos colocar en el formulario principal de nuestra aplicación, controlando así eventos tan comunes como OnActivate, OnRestore, OnMessage, etc.

Por ejemplo, se puede utilizar el evento OnIdle para que nuestro programa realice cálculos complejos en segundo plano cuando el procesador esté desocupado, aprovechando al máximo el rendimiento de nuestro PC. También se puede utilizar el evento OnMessage para interceptar mensajes de Windows que incluso Delphi no tiene definidos en el objeto Application.

MOSTRANDO MENSAJES

Esta es una de las funciones que más se suelen utilizar del objeto Application:

function MessageBox( const Text, Caption: PChar; Flags: Longint = MB_OK ): Integer;

Esta función muestra al usuario un mensaje dentro de un cuadro de dialogo. Para mostrar un mensaje informativo sería así:

Application.MessageBox( 'Mensaje informativo.', 'Atención',
MB_ICONINFORMATION );

se vería así:


Otro mensaje sería para informar al usuario que se ha interrumpido un proceso:

Application.MessageBox( 'No ha rellenado el nombre del proveedor.',
'Acceso denegado', MB_ICONSTOP );

este sería el resultado:


También se puede hacer una pregunta al usuario por si desea realizar algo:

if Application.MessageBox( '¿Desea continuar?', 'Guardando factura',
MB_ICONQUESTION OR MB_YESNO ) = ID_YES then
....

este cuadro de diálogo tendría dos botones:

El parámetro flags de esta función permite que aparezcan los siguientes botones:

MB_ABORTRETRYIGNORE Anular, Reintentar y Omitir.
MB_OK Aceptar (por defecto).
MB_OKCANCEL Aceptar y Cancelar.
MB_RETRYCANCEL Reintentar y Cancelar.
MB_YESNO Si y No.
MB_YESNOCANCEL Si, No y Cancelar.

Entre los posibles mensajes que devuelve esta función (según lo que hagamos con flags) tenemos:

Constante Valor numérico Resultado
--------- -------------- ---------
IDOK 1 El usuario ha pulsado Aceptar.
IDCANCEL 2 El usuario ha pulsado Cancelar.
IDABORT 3 El usuario ha pulsado Abortar.
IDRETRY 4 El usuario ha pulsado Reintentar.
IDIGNORE 5 El usuario ha pulsado Ignorar.
IDYES 6 El usuario ha pulsado Si.
IDNO 7 El usuario ha pulsado No.

CONTROLANDO EL ESTADO DE LA APLICACIÓN

Tenemos los siguientes procedimientos disponibles para controlar el estado global de la aplicación:

procedure Minimize;

Este procedimiento minimiza la aplicación en la barra de tareas. Es importante tener bien claro cual es el formulario principal de la aplicación, ya que si minimizamos otra ventana provocará un efecto no deseado: se minimiza en la esquina inferior izquierda del escritorio. Para evitar esto siempre tenemos que procurar que el formulario que se pueda minimizar sea siempre el formulario principal. Si no fuera así, entonces recomiendo que toda la aplicación sea de tipo MDI.

procedure Restore;

Vuelve a mostrar la ventana principal de la aplicación si ha sido minimizada por el usuario o por el propio programa con el método Minimize.

procedure BringToFront;

Este procedimiento enfoca de nuevo nuestra aplicación superponiendo la ventana principal de nuestra aplicación a otras aplicaciones que se estén visualizando en este momento en Windows. Puede ser interesante cuando tenemos que informar al usuario de algún evento que se ha producido en nuestra aplicación (como hacen los antivirus).

procedure CreateForm( FormClass: TFormClass; var Reference );

Este es otro de los procedimientos más utilizados por el objeto Application. Crea el formulario que le pasemos como parámetro. El primer parámetro es la variable de la instancia que se va a crear y el segundo es la clase de la variable. Por ejemplo:

Application.CreateForm( FCliente, TFCliente );

procedure Terminate;

Hay que estar muy seguro para llamar a este procedimiento, ya que cierra toda la aplicación por la fuerza. Si tenemos algún formulario que haya instanciado algunos objetos que no ha liberado de memoria se podría quedar memoria desperdiciada en todo Windows.

procedure ProcessMessages;

Es importante llamar a este procedimiento cuando estamos haciendo un proceso largo que gasta bastante procesador, ya que si no lo hacemos así el usuario tiene la sensación de que la aplicación se ha colgado. Hay que llamar a este procedimiento en cada iteración del bucle.

LEYENDO DATOS DE NUESTRA APLICACION

El objeto Application también es muy útil para obtener información. Veamos que funciones pueden utilizarse para esto:

property Active: Boolean;

Esta propiedad nos dice si la aplicación esta activa y enfocada.

property ExeName: string;

Nos devuelve la ruta y nombre completo de donde se está ejecutando nuestra aplicación. Si nos interesa saber sólo la ruta se podría hacer esto:

ExtractFilePath( Application.ExeName );

property MainForm: TForm;

Nos devuelve la referencia al formulario principal de la aplicación. Si el formulario principal cambiara, no haría falta modificar el código de nuevo.

property ShowMainForm: Boolean;

Si desactivamos esta propiedad, cuando arranque el programa por primera vez no mostrará la ventana principal. Esto puede ser útil para mostrar la típica ventana de presentación antes de mostrar la pantalla principal. También puede utilizarse si vamos a crear un control de usuarios con clave de acceso y necesitamos que no muestre la ventana principal antes de que se haya validado el usuario.

property Title: string;

Modificando esta propiedad podemos cambiar en tiempo de ejecución el título de nuestra aplicación según su estado (se ve sobre todo cuando está minimizada en la barra de tareas).

property Handle: HWND;

Un handle es un identificador único que Windows da a todas las aplicaciones y ventanas que crea. Este handle (que en realidad es un valor numérico) es muy utilizado por funciones de la API de Windows. Por ello, esta propiedad es muy interesante para leer el handle de nuestra aplicación (cada vez que se ejecuta una aplicación Windows le da un handle distinto).

Aunque el objeto Application tiene más funciones y propiedades creo que hemos cubierto aquí las más importantes.


Pruebas realizadas en Delphi 7.

21 marzo 2008

El componente ActionMaganer

Uno de los problemas que suele presentarse a un programador de aplicaciones es cuando tiene que rediseñar de nuevo toda la interfaz del programa. Si tenemos el código vinculado directamente a botones, menús genéricos o menús contextuales nos toca de nuevo trasladar el código que había en los eventos de los componentes viejos a los componentes nuevos (haciendo copy-paste a base de bien).

Supongamos hemos programado un pequeño bloc de notas:




Para cada opción de menú tenemos definido su código correspondiente:

procedure TForm1.NuevoClick( Sender: TObject );
begin
Memo.Lines.Clear;
end;

procedure TForm1.AbrirClick( Sender: TObject );
begin
if OpenDialog.Execute then
Memo.Lines.LoadFromFile( OpenDialog.FileName );
end;

procedure TForm1.GuardarComoClick( Sender: TObject );
begin
if SaveDialog.Execute then
Memo.Lines.SaveToFile( SaveDialog.FileName );
end;

.....

Supongamos que quiero eliminar el componente de la clase TMainMenu y crear el su lugar un componente nuevo. El código que hemos visto anteriormente quedaría abandonado y habría que cortar el código de cada opción para llevárselo al nuevo componente.

Para evitar estos problemas tenemos el componente ActionMaganer que esta situado dentro de la paleta de componentes Aditional. Este componente esta diseñado específicamente para contener acciones de menús o botones pero sin estar vinculados a ningún componentes visual en concreto.

De manera que vamos a centralizar todas las acciones de nuestro formulario dentro de este componente para desvincularlo de la interfaz. Sería algo así como una programación visual dividida en dos capas: capa lógica (la cual contiene el código fuente relacionado con las acciones del usuario) y la capa visual (los componentes con los que va a interactuar el usuario).

Veamos cuales son los pasos para realizar esta tarea:

1. Insertamos un componente ActionManager en nuestro formulario:

2. Hacemos doble clic sobre dicho componente y nos aparecerá esta ventana:

Es esta ventana vamos a definir las acciones genéricas del formulario.

3. Pulsamos el botón New Action:
4. Nos aparecera en la lista Action1. Hacemos doble clic sobre el mismo y guardamos el código asociado al menú (Archivo -> Nuevo):

procedure TForm1.Action1Execute( Sender: TObject );
begin
Memo.Lines.Clear;
end;

Igualmente vamos a crear dos acciones más para guardar los eventos Archivo -> Abrir y Archivo -> Guardar como...

procedure TForm1.Action2Execute( Sender: TObject );
begin
if OpenDialog.Execute then
Memo.Lines.LoadFromFile( OpenDialog.FileName );
end;

procedure TForm1.Action3Execute( Sender: TObject );
begin
if SaveDialog.Execute then
Memo.Lines.SaveToFile( SaveDialog.FileName );
end;

5. Ahora vamos a añadir a nuestro formulario una barra de menús de la clase TActionMainMenuBar situada en la pestaña de componentes Additional:


Esto creará una barra vacía en la parte superior de nuestro formulario:


Para añadir opciones a esta barra vamos a hacer lo siguiente:

6. Hacemos doble clic sobre el componente ActionMaganer.

7. Arrastramos el objeto de la lista Action1 hacia la barra vacía que hemos insertado en el formulario:


8. Copiamos también las acciones 2 y 3.

9. Si queremos cambiar el nombre de las acciones hacemos doble clic en el objeto ActionMaganer, pulsamos Action1 y en el inspector de objetos modificamos la propiedad Caption y ponemos Nuevo. Igual hacemos para las acciones 2 y 3 que vamos a llamarlas Abrir y Guardar como. Como podemos apreciar no sólo cambian los nombres de las acciones en la lista del objeto ActionManager sino que también las situadas en la barra superior del formulario:


10. Por último y no menos importante, sería conveniente cambiar también la propiedad Name de cada una de las acciones, de modo que en el código fuente los procedimientos pasen a llamarse:

procedure TForm1.NuevoExecute( Sender: TObject );
procedure TForm1.AbrirExecute( Sender: TObject );
procedure TForm1.GuardarComoExecute( Sender: TObject );

en vez de:

procedure TForm1.Action1Execute( Sender: TObject );
procedure TForm1.Action2Execute( Sender: TObject );
procedure TForm1.Action3Execute( Sender: TObject );

De este modo tenemos separadas las acciones internas del formulario y su parte visual. Si eliminamos por error la barra superior del formulario seguimos teniendo todos nuestros eventos vinculados al objeto ActionMaganer. Así nuestro programa queda más flexible y elegante.

La mayor parte del código fuente de este artículo puede sustituirse mediante acciones predefinidas que lleva el componente ActionMaganer. Cuando creamos una acción, en vez de pulsar botón New Action tenemos que pulsar la flecha hacia abajo que hay a su derecha y seleccionar New Standar Action. En la ventana que aparece tenemos todas las típicas acciones que suelen realizarse en un bloc de notas, tales como copiar, cortar, abrir archivos, etc. También incorpora algunas funciones para recorrer los registros de las bases de datos, acelerando de este modo la implementación del programa.

Otra ventaja de utilizar este método es que mientras un programador puede dedicarse a la parte visual del formulario (creando menús, botones, iconos, etc), otro programador puede dedicarse a crear el código asociado al formulario distribuyendo de esa manera el trabajo en equipo.

Pruebas realizadas en Delphi 7.

14 marzo 2008

Creando aplicaciones multicapa (y VII)

Voy a finalizar este artículo hablando sobre la creación de aplicaciones multicapa utilizando servicios web a través del protocolo SOAP.

Para ello voy a utilizar el servidor Apache para alojar el ejecutable de mi servidor de aplicaciones.

CREANDO EL SERVIDOR DE APLICACIONES

El servidor de aplicaciones va a ser un ejecutable CGI que vamos a situar en el directorio cgi-bin de Apache. Los pasos para su creación son los siguientes:

1. Selecciona File -> New -> Other. Seleccionamos la pestaña WebServices, elegimos SOAP Server application y pulsamos Ok:


Al pulsar Ok nos preguntará el tipo de servidor que vamos a crear:


2. Como quiero que mi servidor web sea un ejecutable independiente voy a seleccionar la segunda opción: CGI Stand-alone executable. Al pulsar Ok nos creará un proyecto nuevo que incluye el siguiente módulo de datos web:

3. Nos preguntará si deseamos crear una interfaz para el módulo SOAP. Pulsamos No.

4. Cuando pulsemos el botón Save All para guardar todo el proyecto, vamos a poner como nombre el objeto TWebModule1 como UServidorSOAP.pas y el nombre del proyecto como ServidorSoap.dpr. El proyecto creado sólo se compone de dos partes; por un lado el archivo DPR del proyecto:


Y una unidad de la clase TWebModule que es la encargada de recoger las peticiones de los clientes:


5. Ahora vamos a añadir un módulo de datos remoto: File -> New -> Other, pestaña WebServices, seleccionamos SOAP Server Data Module y pulsamos Ok.

6. Nos preguntará el nombre del módulo: ModuloSOAP y pulsamos Ok. Lo guardamos también como UModuloSOAP.pas.

7. En este módulo de datos insertamos los componentes de acceso a nuestra base de datos Firebird, al igual que hicimos en artículos anteriores:


8. Compilamos el proyecto y nos generará el archivo ServidorSoap.exe. Si ejecutamos ese archivo nos devuelve una página web con la descripción de nuestros servicios web disponibles. Puede verse abriendo una ventana de comandos y ejecutando:

ServidorSoap.exe > servicios.html

9. Copiamos el ejecutable ServidorSoap.exe al directorio cgi-bin donde tengamos instalado el servidor web Apache. Para comprobar que nuestro servidor de aplicaciones esta operativo, abrimos un navegador web y escribimos la siguiente dirección:

http://127.0.0.1/cgi-bin/ServidorSoap.exe

Nos mostrará la misma página web que hemos guardado en servicios.html:


Con esto ya tenemos creado nuestro servidor de aplicaciones.

CREANDO LA APLICACION CLIENTE

La aplicación cliente va a ser similar a todas las que hemos creado hasta ahora:


Como puede verse en la imagen, he incluido un componente de la clase TSoapConnection de la pestaña de componentes WebServices. Al componente lo he llamado ClienteSoap y he modificado las siguientes propiedades:

URL: http://127.0.0.1/cgi-bin/ServidorSoap.exe/SOAP/
SOAPServeIID: IAppServerSOAP - {C99F4735-D6D2-495C-8CA2-E53E5A439E61}
Connected: True

Y en el componente TClientes (ClientDataSet) modificamos:

RemoteServer: ClienteSOAP
ProviderName: DSPCliente
Active: True

Haciendo esto debe verse la lista de clientes.

Este es el tipo de aplicación multicapa que más me gusta, ya que al trabajar a través del puerto 80 y mediante XML-SOAP no es necesario abrir puertos en los routers ni en los cortafuegos de los antivirus.

Como hemos visto anteriormente al crear el servidor de aplicaciones, también pueden crearse servidores que estén dentro de una librería DLL ya sea para el servidor apache o para el servidor Internet Information Server (IIS) de Microsoft.

Pruebas realizadas con Delphi 7.0, Firebird 2.0 y Apache Server 2.2.8.

07 marzo 2008

Creando aplicaciones multicapa (VI)

Hoy vamos a ver como crear las aplicaciones cliente y servidor utilizando el protocolo HTTP para establecer la comunicación. Para que funcione este método es necesario tener instalado el servidor Internet Information Server de Microsoft.

Si teneis Windows XP profesional se puede instalar de la siguiente manera:

1. Inicio -> Configuración -> Panel de control.

2. Hacemos doble clic sobre el icono Agregar o quitar programas.

3. Seleccionamos Agregar o quitar componentes de Windows.

4. Activamos Servicios de Internet Information Server (IIS).

5. Pulsamos Siguiente y nos pedirá el CD de Windows XP. Lo introducimos y pulsamos Siguiente.

6. Cuando termine la instalación pulsamos el botón Finalizar.

Con esto quedará instalado y ejecutado el servidor web de Microsoft.

CREANDO EL SERVIDOR DE APLICACIONES

La creación del servidor de aplicaciones es idéntica a la creada en el artículo anterior mediante sockets. Queda resumido en estos pasos:

1. Creamos un nuevo proyecto y lo guardamos.

2. Creamos un módulo de datos remoto: File -> New -> Other, pestaña Multitier, seleccionamos Remote Data Module y pulsamos Ok.

3. En la nueva ventana que aparece escribimos en el campo CoClass Name: ServidorHTTP.

4. Guardamos el módulo de datos remoto con el nombre UServidorWeb.pas.

5. Insertamos en el módulo de datos remoto los componentes encargados de conectar con nuestra base de datos. No voy a volver a explicarlo de nuevo ya que son los mismos componentes que he explicado en artículos anteriores:


Prácticamente no cambia nada respecto a hacerlo con sockets o con DCOM. En los tres casos lo que hace el módulo de datos es quedar registrado en Windows mediante un número de interfaz.

CREANDO LA APLICACION CLIENTE

Para crear la aplicación cliente rápidamente, podemos crear un proyecto nuevo y luego nos traemos del artículo anterior el formulario que utilizamos para crear la aplicación cliente, menos el componente de la clase TSocketConnection.

A dicho formulario le añadimos el componente WebConnection (pestaña DataSnap) y le ponemos de nombre ClienteWeb. Quedaría del siguiente modo:


Y aquí es donde empiezan las complicaciones. En primer lugar hay que copiar el archivo httpsrvr.dll que se encuentra en la carpeta bin de Delphi al directorio scripts de donde esté instalado Internet Information Server. Eso en teoria (según la documentación de Borland), porque yo no he encontrado dicho directorio (por lo menos en mi Windows XP Profesional SP2). Lo que vamos a hacer es copiar esa DLL donde esté nuestro servidor de aplicaciones HTTP.

Lo que he hecho en su lugar es ejecutar el programa que administra IIS del siguiente modo:

1. Inicio -> Configuración -> Panel de control.

2. Hacemos doble clic sobre Herramientas Administrativas.

3. Hacemos doble clic sobre Servicios de Internet Information Server.

4. Vamos pulsando el icono [+] del arbol de tenemos a la izquierda hasta acceder al icono Sitio Web Predeterminado. Se puede ver la carpeta scripts donde se pueden añadir directorios virtuales. He probado a añadir la carpeta donde está mi servidor HTTP pero ni caso.

5. Pulsamos con el botón derecho del ratón sobre el icono Sito Web Predeterminado y seleccionamos la opción Nuevo -> Directorio Virtual...


6. Pulsamos el botón Siguiente.

7. En Alias escribimos ServidorHTTP y pulsamos Siguiente.


8. Seleccionamos el directorio donde se encuentra nuestro proyecto del Servidor HTTP y el archivo httpsrvr.dll.

9. Activamos la opción Ejecutar (por ejemplo, aplicaciones ISAPI o CGI) y pulsamos Siguiente.


10. Pulsamos Finalizar.

11. Nos vamos a nuestro proyecto Cliente HTTP de Delphi 7 y seleccionamos el componente WebConnection.

12. En la propiedad ServerName seleccionamos ServidorHTTP.ServidorWeb. Se rellenará automáticamente el campo ServerGUID.

Y cuando parece que va a ir todo perfecto y activamos la opción Connected aparece este mensaje:


Y aquí es donde me he quedado. Por mucho que he dado permisos en IIS y por muchas vueltas que le he dado a los proyectos cliente y servidor no hay manera de evitar dicho mensaje. Y no he encontrado ninguna información útil por la red que solucione el problema (ni en castellano ni en inglés), bueno sí, en ruso, pero...

También he probado a copiar el archivo httpsrvr.dll dentro del directorio cgi-bin del servidor Apache y aunque llega a conectar con el mismo, me devuelve un error 500 que no lo conoce ni su padre.

Por lo tanto, aunque consiga solucionar este problema, no me gusta tener que depender de IIS para crear aplicaciones mediante HTTP. Prefiero utilizar sockets o DCOM.

Si alguien ha solucionado el problema que me lo cuente, porque yo no lo he logrado de ningún modo.

En la siguiente parte del artículo veremos como realizar lo mismo mediante servicios Web utilizando SOAP.

Pruebas realizadas en Delphi 7 y Firebird 2.0.

29 febrero 2008

Creando aplicaciones multicapa (V)

En esta ocasión vamos a crear un servidor de aplicaciones utilizando sockets en lugar de utilizar DCOM. Aunque los pasos son prácticamente los mismos, hay una pequeña diferencia: hay que utilizar un programa de Borland que hace de puente entre nuestro servidor de aplicaciones y las aplicaciones cliente.

Veamos un ejemplo paso a paso. Antes de empezar creamos una carpeta donde alojar el proyecto del servidor de aplicaciones. Por ejemplo:

D:\Desarrollo\DelphiAlLimite\Multicapa\ServidorSockets\

CREANDO EL SERVIDOR DE APLICACIONES

1. Creamos un nuevo proyecto (File -> New -> Application).

2. La ventana principal de la aplicación la llamamos FPrincipal, guardando su unidad con el nombre UPrincipal. Como título de esta ventana podemos poner: Servidor de Sockets.

3. Añadimos al proyecto un módulo de datos remoto: File -> New -> Other. Pulsamos sobre la pestaña Multitier, seleccionamos Remote Data Module y pulsamos Ok. Aparecerá la siguiente ventana:


3. En el campo CoClass Name escribimos Servidor y pulsamos Ok.

4. Guardamos la unidad del módulo de datos remoto creado con el nombre UServidor.

5. Al igual que hicimos en el servidor DCOM vamos a crear los siguientes componentes para acceder a la base de datos Firebird:


Se compone de:

- Un componente IBDatabase llamado BaseDatos (pestaña Interbase).

- Un componente IBTransaction llamado Transaccion (pestaña Interbase).

- Un componente IBQuery llamado TClientes (pestaña Interbase).

- Un componente DataSetProvider llamado DSPClientes (pestaña Data Access).

6. Para el componente IBDatabase modificamos las siguientes propiedades:

DatabaseName: 127.0.0.1:D:\Desarrollo\DelphiAlLimite\Multicapa\ServidorSockets\BASEDATOS.FDB
DefaultTransaction: Transaccion.
LoginPrompt: False
SQLDialect: 3

7. Para el componente IBTransaction ponemos en su propiedad DefaultDataBase: BaseDatos.

8. Para el componente IBQuery llamado TClientes cambiamos las propiedades:

Database: BaseDatos
Transaction: Transaccion
SQL: SELECT * FROM CLIENTES

9. Y en el componente DataSetProvider seleccionamos TClientes en su propiedad DataSet.

Con esto ya tenemos un servidor básico de aplicaciones utilizando Sockets. Como se puede apreciar no hay mucha diferencia respecto al servidor DCOM que creamos con anterioridad. Ahora vamos a ver como crear la aplicación cliente.

CREANDO LA APLICACION CLIENTE

En esta ocasión vamos a crear la aplicación cliente utilizando un módulo de datos remoto normal (no transaccional). Este módulo de datos no tiene la misma seguridad avanzada que un módulo de datos transaccional pero la comunicación es muy rápida, gastando muy poco ancho de banda.

Cuando establecemos una conexión con el servidor de aplicaciones usando sockets la comunicación se realiza a través del protocolo normal TCP/IP, gozando de la ventaja de poder traspasar cualquier red.

Aquí podemos encontrar una diferencia respecto a un cliente DCOM. Cuando conectamos con el servidor debemos tener arrancado un programa llamado Borland Socket Server que es el intermediario entre nuestro servidor y el cliente. Este programa esta en el directorio bin de la carpeta donde esté instalado Delphi. Lo recomendable sería copiar este programa (scktsrvr.exe) al directorio donde tengamos nuestro servidor de aplicaciones.

Para crear la aplicación cliente vamos a seguir los siguientes pasos:

1. Creamos una carpeta para alojar la aplicación cliente. Por ejemplo:

D:\Desarrollo\DelphiAlLimite\Multicapa\ClienteSockets\

2. Creamos un nuevo proyecto (File -> New -> Application) y le damos a la ventana principal el nombre FCliente. La guardamos con el nombre UCliente.pas.

3. En esta ventana vamos a añadir los siguientes componentes:


- Un componente ClientDataSet llamado TClientes (pestaña Data Access).

- Un componente DataSource llamado DSClientes (pestaña Data Access).

- Un componente SocketConnection que vamos a llamar ClienteSocket (pestaña DataSnap).

- Un componente DBGrid llamado ListadoClientes (pestaña Data Controls).

4. Antes de intentar conectar el cliente debemos arrancar el programa de Borland scktsrvr.exe. Al ejecutar este programa se quedará residente en la bandeja del sistema (el icono azul con el rayo amarillo):


Si pulsamos el botón derecho del ratón sobre el icono y seleccionamos Properties podemos ver la su configuración y puertos por defecto (por si nos interesa cambiarlos).

5. Para el componente SockectConnection modificamos sus propiedades:

Address: 127.0.0.1
ServerName: ServidorSockets.Servidor
Connected: True

Al seleccionar ServidorSockets.Servidor rellenará automáticamente el campo ServerGUID. Al activar la propiedad Connected arrancará automáticamente nuestro programa que hace de servidor, al igual que ocurría con nuestro servidor DCOM. Pero recordad que esto no funciona si no esta en ejecución el programa Borland Socket Server (scktsrvr.exe).

6. Para el componente ClientDataSet fijamos las siguientes propiedades:

ProviderName: DSPClientes
RemoteServer: ClienteSocket

7. Seleccionamos TClientes en la propiedad DataSet del componente DSClientes.

8. Y por último vinculamos el componente DBGrid al componente DSClientes a través de su propiedad DataSource.

9. Si ponemos a True la propiedad Active del componente ClientDataSet aparecerán los datos en pantalla en tiempo de diseño:


Si abrimos una ventana de comandos (MS-DOS) y ejecutamos:

netstat -bn (para Windows XP con SP2)

podemos ver las conexiones abiertas tanto en Delphi como en el servidor de aplicaciones:


Como puede apreciarse la comunicación se ha realizado a través del puerto 211, lo que significa que habrá que abrir dicho puerto tanto en nuestros routers como en los cortafuegos si queremos establecer la comunicación correctamente.

En la siguiente parte de este artículo veremos como crear un servidor de aplicaciones y un cliente a través del protocolo HTTP (puerto 80).

Pruebas realizadas con Dephi 7.0 y Firebird 2.0.

23 noviembre 2007

Creando aplicaciones multicapa (IV)

Una vez que hemos creado nuestro servidor DCOM vamos a implementar nuestra aplicación cliente que se va a encargar de llamarlo.

CREANDO LA APLICACION CLIENTE

Para conectar un cliente multicapa al servidor DCOM vamos a utilizar un componente de la clase TDOMConnection que buscará en tiempo de diseño el servidor.

Como se verá a continuación no es necesario añadir un componente de la clase TDataSetProvider ni ningún otro relacionado con motores de bases de datos específicos. Eso ya se lo hemos dejado al servidor de aplicaciones. Tampoco es necesario que el servidor de aplicaciones que creamos en el artículo anterior se esté ejecutando mientras diseñamos el cliente.

Para realizar las pruebas vamos a crear un nuevo proyecto que contenga un sólo formulario y los siguientes componentes:


- Un componente TDBGrid llamado ListadoClientes destinado a listar todos los campos de la tabla CLIENTES.

- Un componente TClientDataSet llamado TClientes.

- Un componente TDataSource que lo vamos a llamar DSClientes.

- Un componente TDCOMConnection que lo llamaremos Conexion.

Ahora vamos a vincular unos componentes a otros:

- Vinculamos el componente TDataSource llamado DSClientes con la rejilla ListadoClientes a través de su propiedad DataSource.

- Vinculamos el componente TClientDataSet llamado TClientes al componente TDataSource llamado DSCliente en su propiedad DataSet.

- Asociamos el componente TDOMConnection llamado Conexion al componente TClientDataSet llamado TClientes utilizando su propiedad RemoteServer.

Aquí nos detenemos para analizar un problema. El componente TClientDataSet no mostrará nada que no venga de un componente TDataSetProvider. Como dicho componente se encuentra en el servidor de aplicaciones, lo primero que hay que hacer es conectar con el servidor de aplicaciones para poder vincular su DataSetProvider:

- Seleccionamos el componente TDOMConnection y en su propiedad ServerName elegimos ServidorDatos.ServidorDCOM. Al hacer esto debe rellenarnos automáticamente el campo ServerGUID, el cual es un identificador de la interfaz del módulo de datos remoto que creamos en el servidor de aplicaciones.

- Activamos la propiedad Connected en el componente TDOMConnection y veremos que se ejecuta automáticamente el servidor de aplicaciones mostrándonos su formulario principal.

- Dejando el servidor de aplicaciones en ejecución seleccionamos el componente TClientDataSet y en su propiedad ProviderName seleccionamos DSPClientes.

Con sólo realizar estos pasos, si activamos la propiedad Active del componente TClientDataSet nos mostrará en tiempo de diseño los datos de la tabla clientes:


Al compilar y ejecutar nuestro programa cliente ya tenemos un programa que maneja los datos del servidor sin preocuparse del motor de bases de datos o de otros usuarios conectados.

El componente TDOMConnection tiene la propiedad llamada ComputerName la cual contiene el nombre del equipo donde se va a alojar el servidor de aplicaciones. Si no seleccionamos ninguno se asume que el servidor de aplicaciones y la aplicación cliente residen en la misma máquina.

Si intentamos cerrar el servidor de aplicaciones mientras está conectado el cliente saldrá este mensaje:

There are still active COM objects in this application. One o more clients may have references to these objects, so manually closing this application may cause those client application(s) to fail.

Are you sure want to close this application?

Lo que traducido al castellano sería:

Todavía hay objetos COM activos en esta aplicación. Uno o más clientes podrían estar utilizando estos objetos, así que si cierra esta aplicación podría causar un error de conexión en los clientes.

¿Esta seguro de cerrar esta aplicación?

Esto significa que nunca debemos cerrar el servidor mientras quede algun cliente conectado a nosotros. Además, si el último cliente que estaba conectado al servidor de aplicaciones desconecta entonces el servidor de aplicaciones se cerrará automáticamente al ver que no hay ninguna conexión abierta.

En la siguiente parte de este artículo veremos como crear un servidor de aplicaciones y una aplicación cliente utilizando otros protocolos distintos a DCOM.

Pruebas realizadas en Delphi 7.

20 noviembre 2007

Creando aplicaciones multicapa (III)

Vamos seguir con la base teórica de como funcionan las aplicaciones multicapa antes de comenzar a crear un ejemplo práctico.

ELIGIENDO EL PROTOCOLO DE CONEXION

Cada protocolo de comunicación que podemos usar para conectar de las aplicaciones cliente a las aplicaciones servidor tienen sus propias ventajas e inconvenientes. Antes de elegir un protocolo tenemos que considerar que servicio va a prestar la aplicación, cuantos clientes va a ser atendidos, que reglas de negocio se van a establecer, etc.

USANDO CONEXIONES DCOM

DCOM es el protocolo que proporciona el acceso más directo y rápido de comunicación, no requiriendo aplicaciones externas aparte del servidor de aplicaciones.

Este protocolo proporciona servicios de seguridad cuando se utiliza un módulo de datos transaccional. Cuando usamos DCOM podemos identificar quien llama al servidor de aplicaciones (ya sea con COM+ o MTS). Por tanto, es posible determinar que reglas de acceso vamos a asignar a las aplicaciones cliente.

Son los clientes los que instancian directamente el módulo de datos remoto para realizar la comunicación, no requiriendo ninguna aplicación externa que haga de intermediario.

USANDO CONEXIONES SOCKET

La comunicación mediante sockets nos permiten crear clientes muy ligeros. Se suele utilizar este protocolo si no tenemos la seguridad que los sistemas clientes soporten DCOM. Los sockets proporcionan un sistema comunicación simple para establecer conexiones entre los clientes y el servidor.

En lugar de instanciar el módulo de datos remoto desde el cliente (como sucede con DCOM), los sockets usan una aplicación separada en el servidor (ScktSrvr.exe), la cual acepta las peticiones de los clientes e instancia el módulo de datos remoto usando COM. El componente de conexión en el cliente y ScktSrvr.exe en el servidor son los responsables de organizar las llamadas mediante la interfaz IAppServer.

El programa ScktSrvr.exe también puede ejecutarse como un servicio NT. Para ello habría que registrarlo como servicio usando línea de comandos. También se puede eliminar de la lista de servicios del mismo modo.

Uno de los inconvenientes que tienen los sockets es que no hay protección en el servidor contra fallos en la conexión con los clientes. Mientras este protocolo de comunicación consume menos ancho de banda que el protocolo DCOM (el cual envía periódicamente mensajes de comprobación y mantenimiento), no puede detectar si un cliente se está ausente o no.

USANDO CONEXIONES WEB

Una las ventajas de utilizar el protocolo de comunicación HTTP es que los clientes pueden comunicarse con el servidor de aplicaciones aunque este protegido por un cortafuegos. Al igual que las conexiones socket, los mensajes HTTP proporcionan un sistema sencillo y de poco consumo de ancho de banda para comunicar los clientes y el servidor.

En lugar de instanciar el módulo de datos remoto desde el cliente (como sucede con DCOM), las conexiones basadas en HTTP pueden usar un servidor de aplicaciones web (como Apache) o el servidor puede ser la librería httpsrvr.dll, el cual acepta las peticiones de los clientes e instancia el módulo de datos remoto usando COM. El componente de conexión en la máquina cliente y httpsrvr.dll en el servidor son los responsable de organizar las llamadas a la interfaz IAppServer.

Las conexiones web aportan también la ventaja de la seguridad SSL suministrada por la librería wininet.dll (una librería de utilidades de internet que corre en los sistemas cliente). Una vez que hemos configurado el servidor web en la máquina que hace de servidor de aplicaciones, podemos establecer los nombre y claves de acceso para los usuario aprovechando las propiedades de conexión que aporta el componente web.

Las conexiones web tienen la ventaja de tener en una memoria caché los objetos de módulos de datos que se van instanciando, conocido como pooling. Esto permite que nuestro servidor cree un número de instancias de módulos remotos limitado para dar servicio a los clientes, sin tener que estar instanciando y destruyendo objetos sin parar cada vez que se conecta o desconecta un cliente.

A diferencia de otras conexiones con componentes, no podemos crear funciones que permitan comunicar directamente el servidor de aplicaciones con las aplicaciones clientes, lo que se llaman funciones callback.

USANDO CONEXIONES SOAP

El protocolo SOAP es el estándar utilizado para crear aplicaciones de servicios web. Este protocolo envia y recibe mensajes codificados en documentos XML, y los envía utilizando el protocolo HTTP.

Las conexiones SOAP tienen la ventaja de que son multiplataforma, ya que son soportadas por prácticamente todos los sistemas operativos actuales. Al utilizar como transporte el protocolo HTTP tienen las mismas ventajas: permite servir a los clientes a través de un cortafuegos y pueden utilizarse diversos servidores HTTP.

CONSTRUYENDO UNA APLICACION MULTICAPA

Resumiendo a grandes rasgos, los pasos generales para crear una aplicación de bases de datos multicapa son los siguientes:

1. Crear el servidor de aplicaciones.

2. Registrar el servidor de aplicaciones como un servicio o instalarlo y ejecutarlo como una aplicación (recomendado).

3. Crear la aplicación cliente.

El orden de creación es importante. Debemos crear y ejecutar el servidor de aplicaciones antes de crear el cliente. Esto se debe a que cuando vayamos a construir la aplicación cliente, en tiempo de diseño tenemos que conectar con el servidor de aplicaciones para realizar pruebas de conexión. Aunque se también se podría un crear un cliente sin especificar el servidor de aplicaciones en tiempo de diseño, pero no lo recomiendo porque es más incómodo.

Si no estamos creando la aplicación cliente en el mismo equipo que el servidor, y estamos usando una conexión DCOM, podemos registrar el servidor de aplicaciones en la máquina cliente. Esto hace que los componentes de conexión se enteren de donde está el servidor de aplicaciones en tiempo de diseño, así podemos elegir el componente Provider desde el inspector de objetos.

CREANDO UN SERVIDOR DE APLICACIONES DCOM

La mayor diferencia entre crear un servidor de aplicaciones y la típica aplicación de bases de datos cliente/servidor reside en el módulo de datos remoto. Vamos a crear una aplicación EXE que va a hacer de servidor de aplicaciones para una base de datos Firebird 2.0 que tiene una tabla llamada CLIENTES.

Para crear un servidor de aplicaciones, hay que seguir los pasos:

1. Crear un nuevo proyecto: File -> New -> Application.

2. Guardar el proyecto como ServidorDatos.exe

3. Añadimos un módulo de datos remoto al proyecto: File -> New -> Other.

4. Nos vamos a la pestaña Multitier, seleccionamos Remote Data Module y pulsamos Ok.

5. Rellenamos los campos:

CoClass Name: ServidorDCOM

Instancing: Multiple Instance

Threading Model: Apartment

6. Pulsamos Ok. Nos aparecerá una nueva ventana que representa el nuevo módulo de datos remoto creado.

7. Guardamos el módulo de datos remoto en disco con el nombre UServidorDCOM.pas

8. Insertamos en el módulo de datos remoto el componente TIBDatabase con el nombre BaseDatos.

9. Hacemos doble clic sobre el componente BaseDatos y configuramos lo siguiente:

Connection: Remote
Protocol: TCP
Database: 127.0.0.1:D:\Desarrollo\DelphiAlLimite\Multicapa\DCOM\BaseDatos.fdb
LoginPrompt: Desactivado

10. Pulsamos Ok.

11. Añadimos al módulo de datos remoto un componente TIBTransaction llamado Transaccion.

12. Vinculamos el objeto Transaccion al componente TIBDatabase a través de su propiedad DefaultTransaction.

13. Asignamos BaseDatos en la propiedad DefaultDatabase del componente Transaccion.

14. Insertamos un componente TIBQuery llamado TClientes. En su propiedad Database ponemos BaseDatos. Y su propiedad SQL escribimos:

SELECT * FROM CLIENTES

15. Hacemos doble clic en el componente TClientes y pulsamos la combinación de teclas CTRL + A para añadir todos los campos.

16. Insertamos un componente TDataSetProvider llamado DSPClientes. En su propiedad DataSet seleccionamos TClientes.

Con esto ya tenemos nuestro propio servidor de aplicaciones conectado a la base de datos Firebird. Como puede apreciarse es casi lo mismo que crear una aplicación cliente/servidor.

La diferencia está en que no es necesario instanciar en memoria el módulo de datos remoto ya que la aplicación cliente se encargará de hacerlo.

En la siguiente parte de este artículo crearemos la aplicación cliente encargada de conectarse con este servidor de aplicaciones que hemos creado.

Pruebas realizadas en Delphi 7.

16 noviembre 2007

Creando aplicaciones multicapa (II)

Después de tener una visión global de cómo funcionan las aplicaciones multicapa vamos a ver cada una de sus partes.

LA ESTRUCTURA DE LA APLICACION CLIENTE


El usuario que va a utilizar la aplicación cliente no notará la diferencia entre una aplicación cliete/servidor y una aplicación multicapa, ya que el acceso a la información se realiza a través de los componentes estándar TClientDataSet.

El componente ClientDataSet se comunica con el proveedor de datos a través de la interfaz IAppServer. Se pueden seleccionar diferentes protocolos de comunicación según el componente de conexión que se utilice, donde tenemos los siguientes componentes:

Componente Protocolo
--------------------------------------------------
TDCOMConnection DCOM
TSocketConnection Windows sockets (TCP/IP)
TWebConnection HTTP
TSOAPConnection SOAP (HTTP y XML)

LA ESTRUCTURA DE LA APLICACION SERVIDOR

Una vez instalado el servidor de aplicaciones, cuando se ejecuta por primera vez no establece una conexión con los clientes. Más bien son los clientes los que inician y mantienen la conexión con el servidor de aplicaciones. Todo esto sucede automáticamente sin que tengamos que manejar solicitudes o administrar interfaces.

La base de un servidor de aplicaciones es el módulo de datos remoto, el cual esta especializado en soportar la interfaz IAppServer (para los servidores de aplicaciones que tienen servicios web, el módulo de datos remoto soporta la interfaz IAppServerSOAP, y usa como preferencia IAppServer).

Las aplicaciones cliente usan las interfaces de módulos de bases de datos remotos para comunicarse con los componentes Provider del servidor de aplicaciones. Cuando el módulo de datos remoto usa IAppServerSOAP, el componente de conexión se adapta a este para la interfaz IAppServer que el que usa el componente ClientDataSet.

Hay tres tipos de módulos de datos remotos:

TRemoteDataModule: Se usa este tipo si los clientes van a utilizan protocolos DCOM, HTTP, sockets o una conexión OLE hacia el servidor de aplicaciones, a menos que queramos instalar el servidor de aplicaciones con COM+.

TMTSDataModule: Se utiliza este tipo si vamos a crear un servidor de aplicaciones como librería DLL que esté instalada con COM+ (or MTS). Se puede utilizar este módulo de datos remoto MTS con protocolos DCOM, HTTP, sockets u OLE.

TSoapDataModule: Este es un módulo de datos que implementa una interfaz IAppServerSOAP en una aplicación de servicios web. Utilizaremos este tipo de módulo de datos para proveer datos a los clientes con acceso a servicios web.

Si el servidor de aplicaciones es distribuido mediante COM+ (o MTS), el módulo de datos incluye eventos para cuando el servidor de aplicaciones sea activado o desactivado. Esto permite conectar automáticamente con los motores de bases de datos cuando se active y desconectarlas cuando se desactive.

EL CONTENIDO DEL MODULO DE BASES DE DATOS REMOTO

Como cualquier otro módulo de datos, se puede incluir cualquier componente no visual en el módulo de datos remoto. Pero hay que tener en cuenta ciertos aspectos:

- Para cada dataset que tiene el módulo de datos remoto en los clientes, debemos incluir un DataSetProvider. Un DataSetProvider parte la información en paquetes que son enviados a los ClientDataSet y aplican las actualizaciones de las bases de datos contra el servidor de aplicaciones.

- Para cada documento XML que el módulo de datos remoto envía al cliente, debemos incluir un proveedor XML. Un proveedor XML actua como un DataSetProvider, exceptuando que la actualización de los datos se efectua a través de documentos XML en vez de ir al motor de bases de datos.

No hay que confundir los componentes de conexión a bases de datos con los componentes de conexión a servidores de aplicaciones, ya que estos últimos utilizan los componentes de las pestañas DataSnap y WebServices.

MODULOS DE DATOS REMOTOS TRANSACCIONALES

Si vamos a crear un servidor de aplicaciones que va a utilizar los protocolos COM+ o MTS entonces podemos sacar ventaja de esto creando módulos de datos transaccionales (Transactional Data Module) en lugar de un módulo de datos remoto ordinario (Remote Data Module). Esto sólo se puede hacer en sistemas opetarivos Windows 2000 en adelante.

Al utilizar un módulo de datos transaccional tenemos las siguientes ventajas:

- Seguridad: COM+ (o MTS) proporciona unas reglas de seguridad en nuestro servidor de aplicaciones. A los clientes se les asignan reglas, las cuales determinan como pueden acceder a la interfaz MTS del módulo de datos.

- Los módulos de datos transaccionales permiten mantener la conexión de los clientes abierta cuando se conectan y desconectan muchas veces hacia el servidor de aplicaciones. De este modo, mediante unas pocas conexiones podemos controlar a muchos clientes que se conectan y se desconectan continuamente (como si fuera un servidor web).

- Los módulos de datos transaccionales pueden participar en transacciones que abarquen múltiples bases de datos o incluir funciones que no están implementadas en las bases de datos.

- Pudemos crear nuestro servidor de aplicaciones como un módulo de datos remoto cuya instancia es activada y desactivada según se necesite. Cuando se usa la activación en tiempo real, nuestros módulos de datos remotos son instanciados solamente si los necesitan los clientes. Esto evita de gastar recursos que no se vayan a utilizar.

Pero no todo son ventajas. Con una simple instancia de un módulo de datos el servidor de aplicaciones se puede manejar todas las llamadas a bases de datos a través de una simple conexión de bases de datos. Pero si se abusa de esto se puede crear un cuello de botella y puede impactar en la ejecución cuando hay muchos clientes, con lo tenemos que mantener un equilibrio entre el número de clientes que van a acceder al servidor de aplicaciones y el número de módulos de datos remotos que se van instanciar.

También puede ocurrir el efecto contrario: si se utilizan múltiples instancias de un módulo de bases de datos remotas, cada instancia puede mantener una conexión a bases de datos independiente. De modo que si hay muchas instancias del módulos de datos remotos se abrirían demasiadas conexiones con la base de datos, disminuyendo el rendimiento del motor de bases de datos como si fuera la típica aplicación cliente/servidor con muchos usuarios.

AGRUPAMIENDO DE MODULOS DE DATOS REMOTOS

El agrupamiento de objetos (pooling) nos permite crear una caché de módulos de datos remotos que estarán disponibles en memoria para las llamadas de las aplicaciones cliente. De esta manera se conservarán recursos en el servidor y evitará el tener que instanciar y destruir de memoria los módulos de datos remotos cuando se utilicen o se dejen de utilizar.

Cada vez que no estamos usando el módulo de datos transaccional obtenemos todas las ventajas que proporciona el tener una cache de objetos agrupados tanto si la conexión se efectua a través de DCOM como si es mediante el componente TWebConnection. Además podemos limitar el número conexiones a bases de datos.

Cuando el servidor de aplicaciones web recibe una petición del cliente, este las pasa a su primer módulo de datos remoto disponible en la caché de módulos de datos remotos. Si no hay disponible ninguna instancia de módulo de datos remoto, el servidor crea una nueva (no sobrepasando el máximo de módulos especificado por nosotros). Esto proporciona una gran flexibilidad permitiendo manejar varios clientes a través de un simple instancia de módulo de datos remoto (el cual puede actuar como un cuello de botella) e irá creando nuevas instancias según se vaya necesitando.

Cuando una instancia de un módulo de datos remoto que está en la caché no recibe ninguna petición de clientes durante un tiempo prolongado, es automáticamente liberado. Esto evita que el servidor de aplicaciones se sature con muchas instancias abiertas.

En la siguiente parte de este artículo abarcaremos los tipos de conexión que se pueden realizar entre las aplicaciones clientes y el servidor de aplicaciones.

Pruebas realizadas en Delphi 7.

14 noviembre 2007

Creando aplicaciones multicapa (I)

En este artículo que estará separado en varias partes vamos a ver como crear aplicaciones de bases de datos multicapa cliente/servidor. Este tipo de aplicaciones esta dividido en unidades lógicas, llamadas capas, las cuales se ejecutan en distintas máquinas. Las aplicaciones multicapa distribuyen los datos y se comunican en una red de área local o bien sobre Internet. Esto proporciona muchas ventajas tales como centralizar la lógica de negocio en un sólo servidor y donde varios clientes van tirando de él. Además podemos crear aplicaciones que comuniquen varios centros de trabajo se estén separados geográficamente a través de Internet.

Una aplicación multicapa queda particionada de la siguiente manera:

- Aplicación Cliente: se encarga de mostrar la interfaz de usuario.

- Servidor de aplicaciones: reside en la red local central y es accesible por todos los clientes donde reciben datos directamente de este servidor.

- Servidor de bases de datos: en este servidor es donde está instalado el motor de bases de datos (Interbase, Firebird, Oracle, etc.), aunque el servidor de aplicaciones y el servidor de bases de datos pueden ser la misma máquina.

En este modelo a tres capas los clientes sólo pueden comunicarse con el servidor de aplicaciones y en ningún caso directamente con el motor de bases de datos, como ocurre en las aplicaciones cliente/servidor habituales.

Este tipo de aplicaciones multicapa no tiene porque estar compuesto sólo de tres capas, podría constar de varios servidores de bases de datos y servidores de aplicaciones.

VENTAJAS DE CREAR UN MODELO MULTICAPA

En este modelo de bases de datos la aplicación cliente sólo se dedica a mostrar los datos al usuario, no sabe nada sobre como los datos son actualizados y mantenidos.

El servidor de aplicaciones (capa media) coordina y procesa las peticiones y actualizaciones de múltiples clientes. El servidor maneja todos los detalles, define el conjunto de datos e interactua con el servidor de bases de datos.

Las ventajas de este modelo multicapa son las siguientes:

- Encapsulación de lógica de negocio. Diferentes clientes de la aplicacion pueden acceder al mismo servidor intermedio. Esto permite evitar la redundancia (y coste de mantenimiento) de duplicar las reglas de negocio para cada aplicación cliente separada.

- Aplicaciones clientes pequeñas. Al delegar las tareas más pesadas en la capa media las aplicaciones clientes ocupan menos y consumen menos procesador y memoria, permitiendo instalarse en máquinas de bajo rendimiento. Esto trae la ventaja de que por muchos clientes que accedan a la aplicación, el motor de bases de datos sólo tiene una conexión, que va directamente al servidor de aplicaciones, evitando así problemas de concurrencia o latencia de datos entre distintas aplicaciones cliente. Estas aplicaciones clientes también pueden funcionar a través de Internet ya que su consumo de ancho de banda es mínimo, al contrario de conectar directamente con el motor de bases de datos.

- Procesar datos distribuidos. Distribuir el trabajo de una aplicación entre varias máquinas puede mejorar la ejecución, ya que el balanceo de carga permite reducir la carga de las máquinas que funcionan como servidor de aplicaciones. Por ejemplo, si vemos que una aplicación de gestión se relentiza podemos distribuir en una máquina las compras, en otra las ventas y la gestión de recibos en otra.

- Incrementar la seguridad. Podemos aislar la funcionalidad en las capas dando restricciones de seguridad. Esto proporciona unos niveles de seguridad configurables y flexibles. Las capas intermedias pueden limitar los puntos de entrada a material protegido, permitiendo controlar el control de acceso más fácilmente. Si usamos HTTP o COM+, podemos utilizar los modelos de seguridad que soportan.

COMPOSICION DE LAS APLICACIONES DE BASES DE DATOS MULTICAPA

Las aplicaciones multicapa usan los componentes de la pestaña DataSnap, los de la pestaña Data Access y a veces los de la pestaña WebServices, más un módulo de datos remoto que es creado por el asistente de la pestaña Multitier o WebServices del cuadro de diálogo New Items. Estos componentes proporcionan las funcionalidades para empaquetar información transportable sólo con los datos que se hayan modificado.

Los componentes que necesitamos para aplicaciones multicapa son los siguientes:

Módulo de bases de datos remoto: Los módulos de datos pueden actual como un servidor COM o implementar un servicio web para dar a las aplicaciones clientes acceso a los datos. Este componente es utilizado en el servidor de aplicaciones en la capa intermedia (el servidor de aplicaciones).

Provider: Es el que proporciona los datos creando paquetes de datos y resolviendo las actualizaciones de los clientes. Este componente es utilizado en el servidor de aplicaciones en la capa intermedia (servidor de aplicaciones).

ClientDataSet: es un dataset especializado que usa la librería midas.dll o midaslib.dcu para manejar los datos almacenados en los paquetes que se envían y reciben. Este componente es utilizado por la aplicación cliente. Tiene una caché local y sólo envía al servidor los datos que han cambiado.

Connection: Es una familia de componentes que estan localizados en el servidor y que utilizan la interfaz IAppServer para leer las peticiones de las aplicaciones clientes. Cada componente de conexión está especializado en protocolo particular de comunicaciones.

Los componentes proveedores y clientes requiren las librerías midas.dll o midaslib.dcu cuando se va a distribuir la aplicación en otros equipos.

FUNCIONAMIENTO DE UNA APLICACION A TRES CAPAS

Los siguientes pasos ilustran la secuencia normal de eventos para una aplicación a tres capas:

1. El usuario cliente arranca la aplicación. El cliente conecta con el servidor de aplicaciones (el cual puede ser elegido en tiempo de ejecución). Si el servidor de aplicaciones no estuviera arrancado, lo arranca automáticamente. Los clientes reciben una interfaz IAppServer para comunicarse con el servidor de aplicaciones.

2. El cliente solicita los datos al servidor de aplicaciones, donde puede requerir todos los datos de una vez o pedir una parte de ellos poco a poco.

3. El servidor de aplicaciones lee la información solicitada por el cliente del motor de bases de dtaos (estableciendo una conexión con si fuera necesario), empaqueta la información y devuelve la información al cliente. La información adicional (por ejemplo, las características de los campos) pueden ser incluida en los metadatos del paquete de datos. Este proceso de empaquetamiento de datos es llamado providing.

4. El cliente decodifica el paquete recibido y muestra los datos al usuario.

5. Cuando el usuario de la aplicación cliente realiza modificaciones sobre los datos (añadir, borrar o modificar registros) estas modificaciones son almacenadas en un log temporal.

6. Finalmente los clientes envian las actualizaciones al servidor de aplicaciones, el cual responde normalmente a cada acción del usuario. Para aplicar los cambios, los paquetes de los clientes leerán y cambiarán el log antes de enviar sus paquetes de datos al servidor.

7. El servidor de aplicaciones decodifica el paquete y efectua los cambios (en el contexto de una transacción cuando sea apropiada). Si un registro no puede ser actualizado (por ejemplo, porque otra aplicación cambie el registro antes de que el cliente lo solicite y después de que el cliente haya aplicado los cambios), el servidor de aplicaciones intenta reconciliar los cambios de los clientes con los datos actuales, y guarda los registros que podrían no ser actualizados. Este proceso de guardar y resolver problemas con los registros es llamado resolving.

8. Cuando el servidor de aplicaciones finaliza el proceso de actualización de registros, devuelve los registros no actualizados al cliente para que pueda resolverlos por el mismo.

9. El cliente resuelve los registros que el servidor no ha podido actualizar. Hay muchas maneras de que un cliente pueda resolver estos registros. Generalmente el cliente intenta corregir la situación asegurándose de que los registros estén validados antes de enviarlos. Si la situación puede ser rectificada, entonces vuelve a enviar los datos al servidor.

10. El cliente desempaqueta los datos que vienen del servidor y refresca su caché local.

En la siguiente parte de este artículo veremos la estructura de una aplicación cliente.

Pruebas realizadas en Delphi 7.

Publicidad