Nota: Este artículo está en
contínua evolución mediante la colaboración
de los miembros de la comunidad, si tienes alguna idea, noticias
o sugerencia y deseas colaborar, a pie de artículo encontrarás
el lugar para poder hacerlo.
PROGRAMACION DE SERVLETS Y WML
Por Santiago Márquez
15/12/2000
1.- INTRODUCCION
Hola amigos, después de los últimos artículos sobre programación
en VoxML y la introducción que hicimos sobre las redes GSM, volvemos
al ataque con un nuevo tema de programación que os resultará de
sumo interés para muchos de vosotros que habitualmente estáis
trabajando con tecnología Java y su integración con WML, nos referimos
a los servlets, esos pequeños programas que actúan como pasarela
entre nuestras aplicaciones WML y los recursos del servidor y
los servidores de aplicaciones. En este artículo vamos a ver las
posibilidades que los servlets nos brindan para hacer nuestras
aplicaciones mucho más interactivas con la ventaja añadida que
el propio lenguaje Java proporciona que es la multiplataforma,
de este modo y junto a los artículos sobre ASP y VoxML vamos completando
las posibilidades que existen actualmente para hacer páginas WML
interactivas y dinámicas. No obstante, este artículo presenta
el inconveniente que para poder hacer un uso correcto de los servlets
y sacarles el máximo partido implica conocer por un lado el lenguaje
Java (al menos a un nivel medio) y por otro conceptos relacionados
con la invocación de métodos remotos o RMI así como tener unas
nociones básicas de orientación a objetos, esto es, saber que
es una clase, que es un objeto, que se entiende por invocación
de métodos, en definitiva toda la jerga que forma parte de este
paradigma y que debemos conocer sino queremos perdernos antes
de empezar, sin embargo vamos a intentar que todos los conceptos
nuevos que puedan aparecer y que puedan dar lugar a dudas queden
explicados para que todos podamos sacar partido de las posibilidades
que nos brindan los servlets para que al finalizar el artículo
veaís que implementar un servlet es muy sencillo. He dedicado
algunos apartados de este artículo a comentar diversas posibilidades
que tenemos de trabajo ya que creo que es muy importante tener
una panorámica amplia de todas las opciones que tenemos a la hora
de desarrollar aunque para los ejemplos nos centraremos en la
programación clásica de servlets, aunque eso si, con los resultados
orientados a la elaboración de páginas WML más atractivas.
2.- CICLO DE VIDA DE UN SERVLET
Los servlets surgen debido a la limitación existente que existían
en los applets desarrollados para el Web en dos vertientes distintas:
la imposibilidad de acceder a otro servidor que no sea el mismo
en el que el applet se este ejecutando (generalmente la máquina
cliente) y la limitación en el acceso a los servicios de dicha
máquina. Por otro lado un applet es un programa que se descarga
desde el Web y se ejecuta en el navegador y puede resultar relativamente
sencillo llegar al código fuente del mismo el cual puede verse
comprometido seriamente dejando al descubierto información que
puede que no queramos que se vea. Qué son por tanto los servlets,
un servlet no es más que una aplicación que se ejecuta en un servidor
Web quedando a la espera para resolver peticiones efectuadas por
los clientes. Mediante los servlets se puede tener acceso a otros
servidores y acceder a la información que en ellos haya contenida,
por ejemplo una base de datos. Según todo lo expuesto anteriormente
los servlets podemos verlos como la evolución lógica de los CGI,
ya que estos últimos no son más que aplicaciones cuyo cometido
es resolver peticiones hechas por los clientes que adolecían de
un número de inconvenientes considerables como era el hecho del
lenguaje de programación utilizado (generalmente lenguajes interpretados),
un rendimiento muy bajo, baja portabilidad, dificultad de comunicación
entre CGIs, etc. que se han visto superados por la aparición de
los servlets, en el cuadro 1 tenéis resumidas las características
básicas de todo servlet.
Los servlets se pueden invocar desde un formulario, un applet,
otro servlet y lo que a nosotros nos interesa desde una aplicación
WML, el único requisito imprescindible que necesitamos tener es
que nuestro servidor Web sea capaz de ejecutar servlets y aquí
entramos en una problemática de que motor utilizar, por un lado
si estamos usando Internet Information Server, Apache o Netscape
podemos hacer uso de JRun (podéis descargarlo desde la página
Web de Allaire en http://www.allaire.com)
o de ServletExec que se integran a la perfección con estos servidores
Web. Otra posibilidad es hacer uso del Java Web Server de Sun
,el cual incorpora un motor para ejecución de servlets dentro
del propio servidor Web.
- Son independientes de la plataforma en donde se ejecutan.
- Son muy rápidos (en comparación con los CGIs)
- Se pueden comunicar distintos servlets entre si.
- Son muy seguros (hacen uso del Security Manager de
Java)
- Son más eficientes dado que multiples llamadas sobre
el mismo servlet no origina la ejecución de distintos
procesos sino que crea threads de ejecución una vez
que ya existe el proceso del servlet ejecutandose en
la máquina.
Cuadro 1. Características de los servlets |
Actualmente probablemente la plataforma más utilizada para la
ejecución de servlets, JSP, EJB etc es JRun que junto con Internet
Information Server 4.0 o Apache hacen un conjunto que permite
obtener muy buenos resultados con una configuración mínima.
Para poder hacer funcionar los ejemplos que veremos más adelante
es necesario instalar JRun. En este
tutorial se explica cómo hacer la instalación de JRun sobre
Internet Information Server, aunque es muy sencillo configurarlo
para otros servidores web.
Visto todo lo anterior podemos decir que el ciclo de vida de
un servlet es un proceso que consta de cuatro pasos básicos que
se repiten siempre: .
- - El cliente solicita una petición a un servidor mediante
una URL .
- - El servidor recibe la petición y la procesa, en este caso
el servidor detecta que es un servlet e inicia la ejecución
del mismo sino se encuentra ya en ejecución alguna instancia
del mismo.
- - El servlet procesa la petición y la retorna al cliente.
- - El servlet creado solo se destruye cuando el motor de servlets
se para o bien cuando hay un fallo en el sistema.
3.- DESCRIPTION DEL JSDK 2.0 de SUN y EVOLUCION A TOMCAT El JSDK
(Java Servlet Developer Kit) proporciona el conjunto de herramientas
necesarias para el desarrollo de servlets, la última versión disponible
es la 2.2 que se encuentra disponible en el web de Sun. La instalación
del JSDK es muy sencilla y basta con hacer clic en el ejecutable
que nos bajaremos desde Sun, durante la instalación el único dato
que se nos pedirá será la carpeta en la cual queremos instalar
el programa. El JSDK consta básicamente de 3 partes:
1. El API del JSDK, que se encuentra diseñada como una extensión
del JDK y consta de dos packages javax.servlet y javax.servlet.http
cuyo funcionamiento veremos más adelante.
Siempre que derivemos una nueva clase de GenericServlet se deberá
definir al menos el método service() aunque en la práctica todos
los servlets deberán construirse a partir de la clase HttpServlet
que es una subclase de GenericServlet y que ya no es abstract
y dispone de una implementación del método service().
En esta implementación se detecta el tipo de servicio HTTP que
ha sido solicitado desde el terminal y llama al método adecuado
de la misma clase. Como podeis comprobar hay mucha chicha dentro
del JDSK pero los fundamentos básicos son estos en el cuadro teneís
un explicación del resto de clases. En este apartado y dado que
la mayor parte de los servlets que crearemos serán del tipo HttpServlet
vamos a hacer un estudio más detallado de esta clase.
- ServletContext: permite a un servlet acceder a información
sobre el entorno en que se están ejecutando.
- ServletConfig: contiene métodos que permiten pasar
al servlet información sobre sus parámetros de inicialización.
- ServletRequest: permite al método service() de GenericServlet
obtener información sobre una petición de servicio recibida
de un cliente.
- ServletResponse: sirve al método service() de GenericServlet
enviar la respuesta al cliente que ha solicitado el
servicio
- HttpServletRequest: deriva de ServletRequest. Sirve
a los métodos de la clase HttpServlet recibir una petición
de servicio HTTP.
- HttpServletResponse: extiende ServletResponse. A través
de esta interface los métodos de HttpServlet envían
información a los clientes que les han pedido algún
servicio.
Cuadro 3. Interfaces del JSDK |
LA CLASE HTTPSERVLET
Los servlets que utilizan el protocolo HTTP son los más comunes
como ya hemos dicho y sabemos que en HTTP los terminales (o browsers)
y los servidores puedan comunicarse entre sí, mediante la utilización
de una serie de métodos como son GET, HEAD, POST, PUT, DELETE,
TRACE, CONNECT y OPTIONS. Estos métodos son los que van dentro
de la clase HttpServlet van a interesarnos implementar como ya
veremos.
La clase abstracta javax.servlet.http.HttpServlet implementa
la interface javax.servlet.Servlet e incluye un numero importante
de funciones adicionales. La forma más sencilla de escribir un
servlet HTTP es heredando de HttpServlet que es también una clase
abstract, de modo que es necesario definir una clase que derive
de ella y redefinir en la clase derivada al menos uno de sus métodos,
tales como doGet(), doPost(), etc.
Como ya se ha comentado, la clase HttpServlet proporciona una
implementación del método service() en la que distingue qué método
se ha utilizado en la petición (GET, POST, etc.), llamando seguidamente
al método adecuado (doGet(), doHead(), doDelete(), doOptions(),
doPost() y doTrace()). Estos métodos e corresponden con los métodos
HTTP anteriormente citados. Así pues, la clase HttpServlet no
define el método service() como abstract, sino como protected,
al igual que los métodos init(), destroy(), doGet(), doPost(),
etc., de forma que ya no es necesario escribir una implementación
de service() en un servlet que herede de dicha clase.
La clase HttpServlet es bastante hábil ya que es también capaz
de saber qué métodos han sido redefinidos en una sub-clase, de
forma que puede comunicar al cliente qué tipos de métodos soporta
el servlet en cuestión. Así, si en la clase MiServlet sólo se
ha redefinido el método doPost() y el cliente realiza una petición
de tipo HTTP GET el servidor lanzará automáticamente un mensaje
de error similar al siguiente:
501 Method GET Not Supported
Donde el número que aparece antes del mensaje es un código empleado
por los servidores HTTP para indicar su estado actual.
Para finalizar con todo esta explicación lo mejor es ver un servlet
muy básico para que nos muestre su estructura, como podeis ver
el esqueleto de este tipo de programas es algo tan simple como
esto:
import javax.servlet.*;
import javax.servlet.http.*;
public class MiServlet extends HttpServlet
{ public void init(ServletConfig config) throws ServletException
{ super.init (config);
Resto del código de init
} // fin del método init()
public void destroy()
{
Código del destroy
} // fin del método destroy()
public void doPost (HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException
{
Código del doPost generalmente:
- obtención de variables
- Tratamiento de datos
- Devolver Pagina WML
} // fin del método doPost()
public String getServletInfo()
{
Método adicional de información
} // fin del método getServletInfo()
}
Fijaros que no es necesario hacer una redefinición del método
service ya que estamos heredando de la clase HttpServlet por lo
que dicho método se hereda de esta y solamente hacemos el trabajo
para aquellos métodos que son realmente necesarios como son init,
destroy y suponiendo que las variables se pasen desde el terminal
mediante el método Post la definición de la función doPost, aunque
podriamos haber definido un doGet o similares en caso de necesitarlas.
También es interesante ver que en la definición del método init
se ha hecho una llamada al método init de su super clase lo cual
es siempre necesario a fin de garantizar la correcta inicialización
del mismo, a continuación de esta instrucción podemos incluir
el resto de inicializaciones que consideremos necesarias como
puede ser la apertura de ficheros o de conexiones contra base
de datos o cualquier otra estructura que pueda sernos de interés.
También observar en que la especificación del servlet anterior
hemos añadido una función denominada getServletInfo() la cual
no es más que una función que podemos declarar o no y que sirve
para retornar información sobre el servlet como puede ser el autor,
la fecha de creación o cualquier dato que consideremos interesante.
También podríamos haber incluido otra función adicional denominada
getServletConfig a través de la cual podríamos pasar al servlet
parametros de configuración básicos. Estas dos últimas funciones
junto con init, destroy y service son los métodos principales
que forman parte de la interface javax.servlet.Servlet y son como
ya hemos visto el mecanismo de comunicación entre el servidor
web y nuestro servlet.
Con respecto a destroy indicar que no es necesario su definición
salvo en el caso que debamos de concluir aquellas tareas que hayamos
levantado y que estén pendientes de finalización como puede ser
el cierre de ficheros.
Por otro lado todos los métodos de clase HttpServlet que puede
redefinir el programador reciben como argumentos un objeto HttpServletRequest
y otro HttpServletResponse. La interface HttpServletRequest proporciona
métodos para obtener información acerca de la petición del cliente,
por otro lado, el objeto de la interface HttpServletResponse permite
enviar desde el servlet al cliente información acerca del estado
del servidor así como establecer los valores del header del mensaje
saliente, en las siguientes tablas teneis los métodos más útiles
de estas dos clases, también se añaden los métodos de la clase
ServletConfig del método init.
| Clase ServletConfig |
|
| GetInitParameter(String) |
Devuelve un string que contiene el valor de los parametros
de inicialización del servlet o null si el parametro no
existe |
| GetInitParameterName() |
Devuelve los nombres de los parametros de inicialización
del servlet como una enumeración de strings |
| GetServletContext() |
Devuelve el contexto de un servlet |
| Clase HttpSerlvetRequest |
|
| GetCookies() |
Devuelve un array de cookies encontradas en la petición |
| GetDateHeader(String) |
Devuelve la fecha de la peticion |
| GetHeader(String) |
Devuelve el contenido del header HTTP de la petición |
| GetMethod() |
Devuelve el método de la petición Get, Post, Put, etc |
| GetRemoteUser() |
Devuelve el nombre del usuario que está haciendo la petición |
| GetRequestedSessionId() |
Devuelve el id de sesión de la petición |
| GetHeaderNames() |
Devuelve el nombre del header HTTP |
| Clase HttpServletResponse
|
|
| AddCookie(Cookie) |
Sirve para añadir una nueva cookie a la respuesta |
| ContainsHeader(String) |
Verifica si el header HTTP del mensaje de respuesta contiene
un campo con el nombre especificado |
| SendRedirect(String) |
Redirige al cliente a la URL especificada |
| SendError(int) |
Envia un error de respuesta al cliente usando el code indicado
y un mensaje por defecto |
| SendError(int,String) |
Envia un error de respuesta al cliente usando el code indicado
y un mensaje por defecto |
EXCEPCIONES
Si es importate en un programa que el código escrito sea estable
lo debemos fundamentalmente a que dentro de dicho código se haga
una adecuada gestión de errores, en el caso de los servlets los
errores en la ejecución de los mismos se manipulan del mismo modo
que en cualquier otro programa Java a través del uso de las excepciones.
Dentro del JSDK vamos a encontrar que hay dos tipo de excepciones
diferentes: Por un lado tenemos la excepcion javax.servlet.ServletException
que se utiliza cuando se produce un fallo general en el servlet
durante su ejecución. Por otro lado tenemos la excepción javax.servletUnavailableException
que indica que el servlet no está disponible, la excepción UnavailableException
hereda de ServletException por lo que además de los métodos que
ella implementa dispone además de algunos adicionales. Igual que
himos antes en las siguientes tablas tenéis los métodos más útiles:
| Clase ServletException |
|
| ServletException() |
Constructor para crear una nueva excepcion |
| ServletException(String) |
Constructor para crear una nueva excepcion con un mensaje
descriptivo |
| Clase UnavailableException |
|
| GetServlet() |
Devuelve el servlet que no está disponible |
| IsPermanet() |
Devuelve true si el servlet va estar permanentemente fuera
de servicio, generalmente cuando se produce esta situación
se requiere la intervención del administrador de la máquina
para poder solucionar el problema |
| . GetUnavailableSeconds() |
Devuelve el tiempo que se espera que el servidor este temporamente
fuera de servicio |
5.- INTEGRACION DE SERVLETS Y WML
Bueno con lo dicho hasta ahora solamente nos queda ver un ejemplo
completo en el cual toda la tecnología que acabamos de ver se
integran en algo concreto, concretamente vamos a desarrollar un
pequeño servlet que genera una página WML con una serie de datos
que recibe como parámetros en el método init, estos datos se suponen
son pasados por una página WML la cual puede ser la que vosotros
querais, no vamos a detenernos en esos detalles de implementación
ya que lo realmente importante es ver como recoger los parámetros
y generar la posterior respuesta al terminal del usuario, según
esto el código podría ser algo similar a lo siguiente:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ServletEjemplo extends HttpServlet {
private String Param1=null;
private String Param2=null;
private String Param3=null;
private String Param4=null;
public void init(ServletConfig config) throws ServletException
{
super.init(config);
} // fin del método init()
public void destroy()
{ /* No hay nada que hacer, incluimos la función a modo de ejemplo
*/;
} fin del método destroy()
public void doPost (HttpServletRequest req, HttpServletResponse
resp)
throws ServletException, IOException {
Param1=req.getParameter("Param1");
Param2=req.getParameter("Param2");
Param3=req.getParameter("Param3");
Param4=req.getParameter("Param4");
GenerarPaginaWML(resp);
} // fin del método doPost()
public void doGet (HttpServletRequest req, HttpServletResponse
resp)
throws ServletException, IOException {
doPost(req,resp);
} // fin del método doPost()
public void GenerarPaginaWML (HttpServletResponse resp) { resp.setContentType("text/vnd.wap.wml");
PrintWriter out = null;
try {
out=resp.getWriter();
}
catch (IOException io) {
;
}
// Se genera el contenido de la página WML
out.println("<%
Response.ContentType = "text/vnd.wap.wml" %>");
out.println(" <?xml version="1.0"?> ");
out.println("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD
WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
");
out.println("<WML>");
out.println("<card id="Ejemplo" title="Ejemplo">");
out.println("<p><strong>Valores devueltos:</strong></p>");
out.println("<p>Param1: "+Param1+"</p>");
out.println("<br><p>Param2: " + Param2 +
"</p>");
out.println("<br><p>Param3: " + Param3 +
"</p>");
out.println("<br><p>Param4: " + Param4 +
"</p>");
out.println("</card>");
out.println("</wml>");
out.flush();
out.close();
} // fin de GenerarPaginaWML ()
public String getServletInfo() {
return "Un servlet completo para WML";
} // fin del método getServletInfo()
}
Este ejemplo aunque muy sencillo incluye algunas de las posibilidades
más interesantes que podemos hacer mediante los servlets. Quizas
lo más interesante sea fijarse por un lado en la manera de inicialización,
con la llamada al método init de la superclase tal y como ya hemos
comentado y la manera de generación de la página de respuesta
que nuestro terminal recibirá (en la figura teneis un ejemplo
del aspecto que presentaría suponiendo que los valores de los
parametros son Uno, Dos, Tres y Cuatro respectivamente para cada
parámetro), en esta página generada podemos ver que abrimos un
flujo de salida a traves del parámetro resp de la clase HttpServletResponse,
a través de este flujo únicamente devolvemos los resultados de
las variables junto con la generación de la página WML que queremos
visualizar en el terminal, muy importante establecer al principio
del envio del resultado el tipo de contenido que se está generando
ya que de no hacerlo así obtendríamos un mensaje de error. El
método en que llamamos al servlet sería similar a la llamada a
cualquier otra página WML salvo por la particularidad de que ahora
la llamada será atendida por un servlet tal y como podéis ver
en la función doPost para recoger los parámetros hacemos uso del
método getParameter perteneciente a la clase HttpServletRequest.
La función doGet la hemos implementado como una llamada a doPost
de manera que las llamadas al servlet puedan ser tanto de un tipo
como de otro.

Existe un aspecto que no hemos tratado hasta ahora y que muchos
de vosotros seguro os estareis preguntado por ellas, ¿donde estan
las cookies?, ¿se pueden hacer uso de ellas desde un servlet?,
la respuesta como podeis imaginar es afirmativa ya que el JSDK
implementa la posibilidad de hacer uso de ellas, veamos como podemos
hacerlo.
1.- Crear un objeto Cookie: La clase javax.servlet.http.Cookie
tiene un constructor que presenta como argumentos un String con
el nombre de la cookie y otro String con su valor, dado que la
información almacenada en una cookies lo es en forma de String
será preciso convertir cualquier valor a String antes de añadirlo
a una cookie. El código para crear una cookie dentro de un servlet
es tan simple como escribir las líneas siguientes:
String ValorNuevaCookie = new String("IDUser0001");
if(ValorNuevaCookie!=null) Cookie miCookie=new Cookie("Valor",
ValorNuevaCookie);
2.- Establecer el valor de una Cookie: La clase Cookie
proporciona varios métodos para establecer los valores de una
cookie y sus atributos:
Cookie miCookie=new Cookie("Nombre", "ValorInicial"); miCookie.setValue("ValorFinal");
Para cambiar los atributos que la cookie presenta se pueden hacer
uso de las funciones siguientes:
- public void setComment(String):Sirve para añadir un
comentario a la cookie, este comentario podemos verlo por ejemplo
desde el emulador de Phone.
- public void setDomain(String): Establece el patrón de
dominio a quien permitir el acceso a la información contenida
en la cookie. Por ejemplo .cocotero.com permite el acceso a la
cookie al servidor www.cocotero.com pero no a a.b.cocotero.com
- public void setMaxAge(int): Establece el tiempo de caducidad
de la cookie siendo la unidad de tiempo los segundos. Un valor
de -1 indica al terminal que borre la cookie cuando se apague
mientras que un valor 0 borra la cookie de inmediato.
- public void setPath(String): Establece la ruta de acceso
del directorio de los servlets que tienen acceso a la cookie.
Por defecto es aquel que originó la cookie.
- public void setVersion(int): Establece la versión de
la cookie.
3.- Enviar una Cookie: Las cookies son enviadas como parte
del header de la respuesta al cliente por lo que deben de incluirse
dentro del objeto de la clase HttpServletResponse de cualquiera
de los parámetros de las funciones que se definen dentro de la
clase, por ejemplo suponiendo una llamada a doGet podriamos hacerlo
del modo siguiente:
public void doGet(HttpServletRequest req, HttpServletResponse
resp)
throws ServletException, IOException {
Cookie miCookie=new Cookie("Nombre","Valor");
resp.addCookie(miCookie);
PrintWriter out=resp.getWriter();
Fijaros en la llamada al método addCookie para incluirlo dentro
de la salida resp y la posterior llamada a getWriter que realiza
el envio propiamente dicho.
4.- Recibir una Cookie: Del mismo modo que la cookie se
envia en el header de respuesta del servidor los clientes devuelven
las cookies siguiendo el mismo mecanismo. Por este motivo, las
cookies enviadas deberán recogerse del objeto HttpServletRequest
mediante el método getCookies(), que devuelve un array de objetos
Cookie tal y como se ve en el siguiente ejemplo:
Cookie miCookie = null;
Cookie[] arrayCookies = req.getCookies();
miCookie = arrayCookies[0];
El anterior ejemplo recoge la primera cookie del array de cookies
si quisieramos recoger todas las cookies recibidas abria que implemetar
el código anterior dentro de un bucle for.
5.- Obtener el valor de la cookie: Para obtener el valor
de una cookie se utiliza el método getValue() de la clase Cookie.
6.- JAWAP 1.3.1B1 DE ERICSSON
Bien, hasta ahora hemos visto que si queremos hacer uso de los
servlets tenemos que las únicas herramientas disponibles son las
que proporciona Sun, aunque en este punto no vamos a detenernos
en demasiados detalles de implementación de código, sí que conviene
saber que otras alternativas tenemos. Como podeis imaginar actualmente
no solo contamos con las herramientas de Sun, a parte de las herramientas
de otras empresas como Borland, o IBM entre otras muchas para
el desarrollo Java y que contienen utilidades para el desarrollo
de servlets, existe un kit de desarrollado por Ericsson en el
cual se han desarrollado un conjunto de clases y utilidades que
bajo el nombre de Jawap (Java Application Framework) están orientadas
y pensadas para facilitar el desarrollo de programas basados en
tecnología Java para plataformas móviles, la versión actual de
este kit es la 1.3.1 y podéis descargarlo desde la siguiente dirección
de Internet y os recuerdo que para poder acceder a dicha Web debéis
de estar registrados para poder bajaros el programa:
http://www.ericsson.com/developerszone
El Jawap se basa en el uso de servlets para funcionar y si ojeamos
su documentación veremos que está pensado para ser usado en un
entorno donde el servidor web es Apache y las conexiones que se
efectúan entre el servidor web y el servidor de aplicaciones se
basan en la invocación de métodos remotos de Java (RMI o Remote
Method Invocation) que comentaremos brevemente más adelante.
Una vez que os descarguéis el programa tendréis un fichero zip
jawap131B1.zip que al descomprimirlo generara en vuestro disco
duro una serie de carpetas y subcarpetas conteniendo los distintos
paquetes que forman parte del kit de desarrollo. El Jawap esta
divido en cinco paquetes diferentes cada uno de los cuales presenta
funcionalidades distintas, son los siguientes:
1. com.ericsson.wasalab.KWWS_UPL (contenido en el fichero:
wlrmi.jar)
2. com.ericsson.wasalab.DSSOLFDWLRQVHUYHU_UPL (contenido en
el fichero: wlapsrmi.jar)
3. com.ericsson.wasalab.DSSOLFDWLRQVHUYHU_MDZDS (contenido en
el fichero: wlapsrv.jar)
4. com.ericsson.wasalab.DSSOLFDWLRQVHUYHU_ZPO (contenido en
el fichero: wlapswml.jar)
5. com.ericsson.wasalab.DSSOLFDWLRQVHUYHU_GHEXJ (contenido en
el fichero: wlapsdbg.jar)
El primer paquete contiene la clase Wapplet la cual proporciona
los mecanismos necesarios para que el programador pueda crear
una clase que trabaje como una aplicación cliente. Este paquete
debe instalarse en el servidor Web y debería ser visible para
el motor de los servlets. El segundo paquete contiene las clases
WapplicationServer, WapplicationServer_Stub (subclase de WapplicationServer)
y the WapplicationServer_Skel (subclase de WapplicationServer),
este paquete debe residir tanto en el lado del servidor de aplicaciones
como en el lado del servidor Web.
El tercer paquete contiene la clase Wapplication que hace uso
de las clases contenidas en el paquete cuatro, de manera que ambos
representan un conjunto de utilidades que pueden ser accedidas
por nuestros propios programas. Finalmente el paquete quinto es
un paquete de debug que sirve para depurar los programas que elaboremos
haciendo uso de Jawap.
INTRODUCCION AL FUNCIONAMIENTO DE RMI
RMI o Remote Method Invocation (Invocación de Métodos Remotos)
surge con la idea de poder comunicar aplicaciones de forma remota
y de esta manera hacer que las aplicaciones trabajen cooperando
unas con otras con la finalidad de tener un sistema distribuido
potente, escalable y seguro. No obstante, no hay que pensar que
RMI es la única forma de comunicar aplicaciones dentro de una
red, existen otros métodos de hacerlo como es CORBA o Java IDL
(o incluso DCOM si nos gusta más el mundo Microsoft) sin embargo
RMI forma parte del JDK y no tiene asociado ningún coste por lo
que para nosotros resulta muy interesante, además como ocurre
con todo (o casi) de lo que forma parte del mundo Java el que
sea gratuito no significa que sea menos potente.
La idea que subyace debajo de RMI es sencilla, lo que se pretende
es llamar o ejecutar (realmente invocar) métodos de objetos remotos
como si estuvieran ejecutándose en local de modo que resultan
totalmente transparente las llamadas que se efectúan a los objetos,
en RMI la principal característica que tenemos es que la invocación
al objeto de remoto se realiza sin saber a priori en que servidor
reside, para ello se hace uso de una técnica que se conoce como
resolución de nombre (o naming) que posibilita invocar al objeto
por su nombre y no por la máquina en la que se encuentre, es importante
indicar que gracias a esto no es necesario que los objetos que
van a ser invocados estén disponibles en tiempo de compilación
bastándonos con que existan en tiempo de ejecución sino queremos
tener un error.
La arquitectura de RMI es una arquitectura en capas cada una
de las cuales presenta una serie de particularidades que vemos
a continuación:
1.- Capa de Enlace: Sirve de interfaz entre clientes y
servidores, la capa de enlace del cliente se le conoce como Stub
y a la del servidor como Skeleton. Las capas de enlace sirven
para asegurar las llamadas remotas, en el Jawap si os fijáis en
el apartado anterior veréis que teníamos las clases WapplicationServer_Stub
y the WapplicationServer_Skel que se derivaban de WapplicationServer
y que nos proporcionan esta capa de enlace tanto a nivel de cliente
(WapplicationServer_Stub) como a nivel de servidor (WapplicationServer_Skel).
2.- Capa de Referencia: Se encarga de manipular las llamadas
que sobre la capa de enlace se vayan efectuando buscando los objetos
y ejecutando las llamadas que se efectúen sobre el mismo.
3.- Capa de Transporte: Se encarga de mantener la conexión
entre el cliente y el servidor y por tanto entre las máquinas
virtuales que cada uno utilice. La tabla con los diferentes objetos
remotos disponibles esta situada en esta capa y siempre que se
crea un nuevo objeto remoto se añade una entrada en la misma para
que puedan crearse objetos de esta clase desde la capa de referencia.
En la figura siguiente tenéis un pequeño gráfico que representa
la arquitectura RMI.

Concluyendo con el Jawap podemos decir que fundamentalmente está
pensado para la generación de páginas WML de manera dinámica usando
la plataforma Java y haciendo que la comunicación se produzca
a través de RMI donde un servlet espera para la elaboración de
los contenidos.
7.- CONCLUSIONES
Bien, como habéis podido comprobar por todo lo que hemos contado
en el artículo anterior las posibilidades que los servlets nos
ofrecen para la programación de aplicaciones inalámbricas son
muchas, lo mejor que presenta este tipo de tecnología como hemos
visto es su independencia de la plataforma hardware en la cual
se ejecutan por lo que la portabilidad a otros entornos diferentes
del que habitualmente estemos acostumbrados a trabajar es muy
sencilla, ya que al estar basados en la tecnología Java el único
requisito que vamos a necesitar es tener configurada la máquina
virtual correspondiente a nuestra plataforma para poder trabajar
sin ningún tipo de problemas, además la posibilidad de hacer uso
de objetos remotos y la existencia del kit Jawap orientado completamente
al desarrollo WML hacen que nuestras aplicaciones tengan una nueva
perspectiva. Como siempre mi turno finaliza con el fin de este
artículo y comienza el vuestro, vuestra investigación y vuestras
pruebas son fundamentales para poder sacar a los servlets todo
el potencial del que disponen para hacer nuestras páginas WML
más interactivas. Y nada más por mi parte, nos vemos en el próximo
artículo.