Enlaces relacionados con este tutorial
Curso servidores
Página personal J. J. Merelo

Programando con JSPs


Introducción: servidores y contenedores de servlets/JSPs

Los servlets y Java Server Pages (JSPs) son dos métodos de creación de páginas web dinámicas en servidor usando el lenguaje Java. En ese sentido son similares a otros métodos o lenguajes tales como el PHP, los CGIs (common gateway interface), programas que generan páginas web en el servidor, o los ASP (Active Server Pages), un método específico de Microsoft. Sin embargo, se diferencian de ellos en otras cosas.

Para empezar, los JSPs y servlets se ejecutan en una máquina virtual Java, lo cual permite que, en principio, se puedan usar en cualquier tipo de ordenador, siempre que exista una máquina virtual Java para él. Cada servlet (o JSP, a partir de ahora lo usaremos de forma indistinta) se ejecuta en su propia hebra, es decir, en su propio contexto; pero no se comienza a ejecutar cada vez que recibe una petición, sino que persiste de una petición a la siguiente, de forma que no se pierde tiempo en invocarlo (cargar programa + intérprete). Su persistencia le permite también hacer una serie de cosas de forma más eficiente: conexión a bases de datos y manejo de sesiones, por ejemplo.

Los JSPs son en realidad servlets: un JSP se compila a un programa en Java la primera vez que se invoca, y del programa en Java se crea una clase que se empieza a ejecutar en el servidor como un servlet. La principal diferencia entre los servlets y los JSPs es el enfoque de la programación: un JSP es una página Web con etiquetas especiales y código Java incrustado, mientras que un servlet es un programa que recibe peticiones y genera a partir de ellas una página web

Esquema de funcionamiento de un
	 JSP. Tomado de sun.com

Ambos necesitan un programa que los contenga, y sea el que envíe efectivamente páginas web al servidor, y reciba las peticiones, las distribuya entre los servlets, y lleve a cabo todas las tareas de gestión propias de un servidor web. Mientras que servidores como el Apache están especialmente pensados para páginas web estáticas CGIs, y programas ejecutados por el servidor, tales como el PHP, hay otros servidores específicos para servlets y JSPs llamados contenedores de servlets (servlet containers) o servlet engines. Los principales son los siguientes:

Otros muchos se pueden encontrar en la página de Sun sobre la industria del servlet/JSP y en la página de contenedores de servlets en servlets.com

Contenido de esta sección
  • Prerrequisitos para instalar un servidor
  • Instalando un contenedor de servlets
  • Ejecutando los primeros JSPs
  • Hosting de servlets, de pago y gratuito

Instalando un contenedor de servlets

Vamos a ver cómo se instala un contenedor de servlets. Nos fijaremos especialmente en la versión 4.0 de Tomcat, aunque lo que se cuente valdrá para casi todos los otros contenedores Open Source. Los de pago, probablemente tendrán un interfaz pijo para instalarlos, a base de botoncitos, o si son los muy caros, vendrá un señor con corbata y maletín de cuero para hacerlo, así que de esos no nos preocuparemos demasiado.

Antes siquiera de bajarse el programa en cuestión, hay que considerar previamente de la máquina virtual Java que vamos a usar para ejecutarlo. Todos están escritos en Java, así que esto es esencial. Principalmente, hay dos opciones: las JVM de Sun (que son las originales) o las de IBM, que son algo más rápidas, pero que no siempre están actualizadas hasta la última versión. Un contenedor de servlets necesita el JDK completo, no sólo el runtime environmnt, principalmente por el compilador de java contenido en un fichero llamado tools.jar. En cualquier caso, nos podemos bajar la JVM de Sun en sus versiones para Linux, o para cualquier otra plataforma (en la versión 1.4), o bien la versión 1.3 de IBM (la más aconsejable). Si no se consigue una versión de esas, es aconsejable conseguir una que sea compatible con la versión "2" de Java, es decir, JVMs a partir de la versión 1.2. Puede que funcionen con versiones anteriores, pero lo más probable es que no lo hagan.

Igual está ya Java instalado en el sistema; habrá que verificar que java y tools.jar están también instalados; basta con intentar ejecutarlo, o bien preguntarle al administrador del sistema, que también es una criaturita del señó y tiene derecho a que alguien le dirija la palabra, caray.

Una vez instalada la JVM, nos bajamos el servidor de su sitio correspondiente ( http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/), si puede ser, en versión binaria, ya compilada. Si disponemos de una distro de Linux que use el RPM para instalación de paquetes (como Mandrake, RedHat o SuSE), se puede uno bajar los RPMs e instalarlos directamente. Dependiendo de lo que elijamos, habrá que bajarse sólo un paquete, o bien varios. En todo caso, habrá que incluir lo siguiente: Xerces-J, regexp, servletapi, tomcat y tomcat-webapps. Si bajamos el fichero .tar.gz, viene todo incluido. Para instalar el RPM se hace lo siguiente:

[yo@mimaquina]$ rpm -Uvh tomcat4-4.0.2-3.noarch.rpm

(esto después de haber instalado todos los paquetes previos. Si se ha bajado el tar:

[yo@mimaquina]$	tar xvfz tomcat4-4.0.2.tar.gz 

Ya desempaquetado, tendremos el Tomcat listo para funcionar. Dependiendo de la manera de descargargarlo, tendremos el servidor en un directorio u otro, pero siempre habrá directorios conf, lib, bin y webapps. A continuación, habrá que decirle dónde se encuentra la máquina virtual Java, editando un fichero tomcat.conf que se encuentra dentro del directorio conf (que variará de sitio según la distribución; puede ser en /etc/tomcat4/conf o en directorio_del_tomcat/conf). En otros sistemas operativos, o con otro tipo de instalación, habrá que definir una variable de entorno, de esta forma:

[yo@mimaquina]$ export JAVA_HOME=/opt/IBMJava2-13

o bien

[yo@mimaquina]$ setenv JAVA_HOME /opt/IBMJava2-13

, dependiendo de si se trata del intérprete de comandos bash (el primero) o *csh (el segundo). En WinXX habrá que dar una orden similar. Finalmente para ejecutar el servidor, fijándonos en el caso de haberlo instalado usando el RPM, hacemos:

[yo@mimaquina yo]$ /etc/rc.d/init.d/tomcat4 start 
[Imagen de Tomcat funcionando]

En otros casos, habrá que ir al directorio bin de la distribución y ejecutar ./startup.sh o startup si se trata de Windows. Si todo falla, siempre se puede mirar el manual. Por defecto, el servidor viene configurado para lanzarse en el puerto 8080 u 8180 (dependiendo de las versiones). Si todo ha ido bien, tendremos funcionando en nuestro ordenador al Tomcat, y al introducir una dirección tal como http://localhost:8080 o http://localhost:8180 (si quieres usar direcciones por debajo de 1000 tendrás que ser superusuario).

Si no te sale lo anterior, puede ser por miles de razones diferentes. La primera es comprobar que efectivamente el servidor está funcionando. El principal problema de Tomcat es que falla silenciosamente: ejecuta cosas, y parece que ha arrancado, pero, sin embargo, no lo ha hecho. Para ver si está funcionando tienes diferentes opciones: usar netstat para ver si el puerto está ocupado y alguien está escuchando en él (y si es el Tomcat, mejor; si no lo es, ha fallado por eso, porque no ha podido ocupar el puerto), escuchar atentamente el disco duro a ver si al arrancar el tomcat le ha dado vidilla, lo cual indica que efectivamente está funcionando; mirar a ver si hay algo en el directorio webapps , porque si no lo hay, va a dar un fallo de contexto o algo por el estilo, con lo fácil que es decir, joer, que no hay una puñetera página, ¡caray!. También es interesante tratar de ejecutar los ejemplos: si fallan los JSPs pero no los servlets, es que no se ha encontrado el fichero tools.jar, que, a pesar de su nombre, es el que compila los JSPs. Por último, hay que mirar en el registro de catalina, en log/catalina_log.[fecha].txt; si se ha arrancado correctamente, aparecerá algo así:


2002-03-11 08:33:13 HttpConnector Abriendo sockets de servidor en todas las direcciones IP disponibles
2002-03-11 08:33:15 HttpConnector[10001] Iniciando thread de posterior
2002-03-11 08:33:15 HttpProcessor[10001][0] Iniciando thread de posterior

Si solamente pone el primer mensaje, chungo; no ha iniciado ninguna hebra, que son las que efectivamente sirven los JSPs. Si no es nada de eso, mira los mensajes de error en el subdirectorio log, a veces indican que falta algun fichero, o bien que hay un problema de versiones de la máquina virtual Java.

Una vez que se ha instalado, y se ha comprobado que funciona correctamente, se puede intentar cambiar la configuración, sobre todo teniendo en cuenta el número de visitas esperadas. La mayoría de los cambios de configuración se hacen sobre el fichero conf/server.xml. Para cambiar el puerto en el que se escucha y el número de servidores disponibles mínimo y máximo, hay que cambiar la siguiente orden:

<Connector className="org.apache.catalina.connector.http.HttpConnector"
               port="10001"minProcessors="2" maxProcessors=" 5"
               enableLookups="true" redirectPort="8543"
               acceptCount="10" debug="0"
		connectionTimeout="60000"/>

La configuración de Tomcat se hace sobre un fichero que usa el lenguaje XML. Con él, se definen una serie de elementos: servidores, conectores y contenedores; la configuración se ha simplificado mucho desde la versión anterior, aunque introduce nuevos elementos: las válvulas y los motores. Tomcat define para cada servidor una serie de conectores, mediante los cuales diferentes clases responden a diferentes puertos, y se encargan de servirlos; los contenedores o motores se encuentran dentro de los conectores, y se encargan de manejar todas las peticiones para un servicio. Salvo que se vayan a usar aplicaciones particulares (tales como Cocoon), no hay que preocuparse mucho del tema. En nuestor caso, sólo habrá que cambiar el número mínimo de procesadores (o hebras que sirven peticiones) y el máximo, para no sobrecargar demasiado el sistema en caso de que se cuente con poca memoria principal. El mínimo aceptable es 2, y el máximo es hasta 65535 o hasta que la memoria aguante (que no aguantará mucho). En cuanto al puerto, se puede usar cualquiera, siempre que no esté ya usado, y siempre que se ejecute desde superusuario; si no se es superusuario, hay que usar los puertos por encima del mil. Una vez hecho esto, hay que rearrancar el servidor para que tome los nuevos cambios:

[yo@mimaquina yo]$ /etc/rc.d/init.d/tomcat4 restart 

Para ahorrar recursos, se pueden eliminar cosas de ese fichero. Por ejemplo, si se trata de un servidor de desarrollo, no necesitamos conectores para el apache ni conexiones que usen SSL. Se puede eliminar la el servicio Tomcat-Apache, eliminando todo lo comprendido entre la etiqueta Service y su contraetiqueta. También se pueden eliminar los conectores AJP, SSL, "proxied", y de test, indicados con un comentario, justo debajo del conector normal (el non-SSL HTTP/1.1 ). Se pueden ahorrar unos pocos más recursos iniciando la JVM de forma que se limite el tamaño del heap y de la pila, pero no se ahorra demasiado espacio. Un Tomcat funcionando no ocupará nunca menos de 90 megas (lo que se puede ver ejecutando el top o gtop o bien, desde la línea de comandos, ps -exfua.

También se puede añadir un nuevo contexto al servidor; sobre todo si queremos que nuestras aplicaciones no se mezclen con el resto de las aplicaciones en el contexto raíz (las contenidas en el directorio ROOT. Para ello, se puede añadir, justo después de la línea donde se define tal contexto, lo siguiente:


<Context path="/micontexto" docBase="micontexto" debug="0"/>

(substituyendo micontexto por el valor adecuado; ambos nombres no tienen porqué ser iguales). El path indica el URI que se va a utilizar para referirse a él cuando lo llamen desde algún navegador, es decir, http://miservidor/micontexto, y el segundo nombre es el subdirectorio del directorio webapps al que se refiere

Una vez realizada la aplicación, se puede alojar en un servidor que ofrezca este servicio. Por ejemplo, Verio ofrece soluciones basadas en el sistema operativo Solaris (el precio hay que consultarlo). Un revendedor de este servicio, SoyDigital, menciona precios a partir de 210 €.

También hay alternativas gratuitas, aunque no son eternas como en el caso de GeoCities. Una de ellas es iSavvix DevSpace, que permite alojamiento gratuito de JSPs, con librerías de tags e incluso XSLT; lo que no permite, es que uno suba sus propias clases, aunque se pueden usar diversas librerías de clases presentes en el sitio. Otra alternativa, WebAppCabaret, que da diversos contenedores de servlets como alternativa: Tomcat y NGASI, Enterprise Java Beans, bases de datos con MySQL, pero todo ello por solamente 15 días; más allá de eso, hay que contratar el servicio Premium, a partir de 3$. Por último, MyCGIserver también permite alojamiento gratuito; hay que responder a una pregunta relacionada con los servlets, pero es usualmente fácil de encontrar la respuesta.

Ejercicios
1. Seguir los pasos anteriores e instalar un contenedor de servlets en el ordenador. Probar con el Tomcat, y si todo va bien, probar también con el Caucho Resin. El proceso es bastante similar. Cambiar la configuración de Tomcat de forma que cada conector use sólo 2 hebras mínimo, y 5 máximo. Cambiar al puerto al 10001; rearrancar el servidor. Definir un nuevo contexto para los ficheros propios.
2. Darse de alta en algún servidor gratuito, y subir alguno de los ejemplos de Resin o de Tomcat para probarlo.

Contenido de esta sección
  • Cómo crear y dónde poner la página
  • hola.jsp

Nuestra primera página JSP

Si todo va bien, y los ejemplos se ejecutan correctamente, ya está uno listo para crear su primer programa, o página, en JSP (depende de como uno lo mire). Como las páginas JSP son básicamente páginas HTML con un poco de Java por medio, sirven, en principio, cualquier editor que comprenda la sintaxis HTML y/o XML; por ejemplo, el XEmacs. Algunos otros entornos, tales como el Sun ONE, una plataforma de desarrollo completa (que consume un montón de recursos), el Visual Age for Java; estos dos están escritos en Java y pueden ejecutarse en cualquier plataforma. El Dreanweaver Ultradev, sin embargo, existe sólo en versión Windows. Forté es gratuito, y los otros dos son de pago, aunque hay versiones de prueba de tiempo limitado que se pueden bajar.

Con cualquier editor de texto se puede crear la primera página JSP (hola.jsp; en acción en iSavvix):

<!-- (c) JJ -->
<%@ page language='java' contentType="text/html" %>
<%! int count=0; %>
<html>
<head><title>Hola y números. Intro to JSP</title></head>
<body bgcolor="white">
Hola, mundo. Te lo repito  <%= count++ %> 
<% if (count == 1) { %>
 vez
<% } else { %>
 veces
<% } %>
</body></html>
[Estructura directorios Tomcat]

Tras editar esa página, habrá que ponerla en algún sitio. La estructura de directorios de Tomcat (y de otros contenedores de servlets) es un poco más compleja que la de los servidores web normales. Todos los ficheros cuelgan del directorio webapps, pero no se pueden colocar directamente ahí. De ese directorio descienden otros subdirectorios, que es donde efectivamente se colocan las aplicaciones. Cada directorio corresponde a un contexto; hay un contexto raíz ROOT y tantos otros contextos como queramos definir. Dentro de cada contexto, la estructura de directorios es también siempre la misma; directamente descendiendo del directorio se pueden poner los JSPs, y hay también un directorio WEB-INF donde hay una serie de ficheros de configuración y propiedades, y además otros directorios: classes y lib (que no aparece en esta imagen). En esos directorios se pondrán más adelante los ficheros .class y .jar, respectivamente. Por tanto, el fichero anterior, irá a parar al directorio ROOT (o bien al directorio del contexto propio que hayamos definido en el ejercicio anterior). También se puede colocar en cualquiera de los subdirectorios del directorio webapps, pero no en el principal

El fichero contiene la mayoría de los elementos de un JSP. Para empezar, la línea 2 <%@ page language='java' contentType="text/html" %> incluye una directiva, que son órdenes que se ejecutan antes de que se comience a procesar el JSP, y modifican de alguna forma el resultado del mismo. Todas las directivas en JSP se indican con una @ después del comienzo de la orden JSP (<%). En este caso, le indicamos que la página que se va a ejecutar está en lenguaje Java, y que el contenido que va a generar es de tipo text/html; el estándar JSP, a pesar de su nombre, no está limitado a un solo lenguaje, aunque en la práctica se usa casi siempre Java, y en algunos casos JavaScript. En cuanto al contenido, JSP trabaja, por defecto, con HTML, pero se podrían generar páginas en otros estándares tales como el WML que se usa en los móviles WAP, o XML.

La directiva page puede incluir otros atributos:

<%@ page language='java' 
		contentType="text/html"
		info='Mi primera página en JSP"
		import='java.util.*'
		errorPage='errorQueTeCagas.jsp' %>

info es una especie de comentario, que usa el contenedor para describir la clase en su interfaz de administración; import permite especificar una serie de paquetes en Java para importar, y errorPage indica la página a la que habría que saltar en caso de que se genere una excepción. Ahora mismo, ninguno de estos atributos son necesarios, y, de hecho, la página funciona perfectamente bien sin ellos; en ese caso, tomaría los valores por defecto, es decir, lenguaje HTML para la página y Java para los scriptlets.

Justo a continuación, la línea <%! int count=1; %> es una declaración; la admiración (!) se usa para indicar declaraciones de variables globales, es decir, variables persistentes de una llamada a otra del JSP; y es compartida por todas las llamadas a una página. La declaración se ejecutará la primera vez que se llame a la página, y se volverá a ejecutar cada vez que se recompile la página (o se rearranque el servidor); el efecto que tendrá esta declaració será un contador de visitas, que se incrementará cada vez que se visite. Por lo demás, la declaración es una declaración normal en Java; se pueden incluir tantas declaraciones como se quieran, no necesariamente al principio de la página.

A continuación vienen una serie de elementos HTML, hasta la línea 7, donde se encuentra la orden <%= count++ %>. Todo lo que comience por <%= es una expresión JSP; el efecto que tiene es la evaluación de la expresión y la impresión del resultado. En este caso, se ejecuta la expresión y luego se imprime el valor, que es lo que hace el operador post-incremento ++. Las expresiones en JSP pueden contener sólo expresiones Java que devuelvan un valor, y no hace falta que se terminen con ;, como en el caso de las declaraciones.

A continuación se encuentra una combinación de código Java y elementos de texto que se suele denominar scriptlet. Los scriptlets usan la sintaxis JSP normal, <% y %>; y dentro, se puede incluir cualquier cacho de programa en Java que se quiera. En este caso es una sentencia if, y lo único relevante es que el código Java está mezclado con el texto; en este caso, se incluiría condicionalmente un texto u otro en la página de salida. Se podría hacer usando sólo Java, de esta forma

<% if (count == 2) 
		System.out.println('vez')
} else {
		System.out.println('veces')
} %>

Sin embargo, de esta forma, se pueden incluir más fácilmente todo tipo de estructuras HTML, sin necesidad de meter montones de System.out. Lo del count == 2 es porque, cuando llega ahí el programa la primera vez que se ejecuta, el contador ya vale dos, porque se ha incrementado en la línea anterior.

Si no queremos tomarnos toda la molestia de meterlo en el contnedor de servlets, podemos intentar compilarlo antes, para ver si hay algún errorcillo que se nos hubiera saltado, por ejemplo de sintaxis. Se puede usar para ello el compilador de JSPs offline; Tomcat incluye jasper, que se puede usar de la forma siguiente (versión 4):

djasper4 jspc hola.jsp 

(aunque en el RPM de la versión 4.0.2 no funciona correctamente, creo...). Si todo va bien, se genera un fichero hola.java que, sería el que, compilado, daría el servlet; de hecho, este fichero se podría compilar y ponerse como servlet. Esta compilación no es necesaria, pero si estamos trabajando con un fichero grande y no tenemos muy claro si la sintaxis es correcta, se puede usar; aunque en la mayor parte de los casos, se lo tragará todo y dejará al engine el coger los errores. De hecho, no he conseguido que dé un error, por muchas cosas que le he he hecho...

Si nos hemos equivocado en alguna cosa, el contenedor de servlets dará los errores correspondientes. Por ejemplo, si alguna etiqueta de JSP no la hemos puesto bien (< } %>), saldrá algo así:

org.apache.jasper.JasperException: No se puede compilar la clase para JSP
/var/tomcat4/work/localhost/jmerelo/hola$jsp.java:90: 'catch' without 'try'.
        } catch (Throwable t) {
          ^

/var/tomcat4/work/localhost/jmerelo/hola$jsp.java:98: 'try' without 'catch' or 'finally'.
}
^

/var/tomcat4/work/localhost/jmerelo/hola$jsp.java:98: '}' expected.
}
 ^
3 errors

tras explicar el tipo, el mensaje y la descripción. En realidad, este mensaje no tiene nada que ver con el error, pero es lo más que se puede pedir, teniendo en cuenta que tenemos varias fases de compilación. A lo que hay que prestarle atención es a la última línea, la que dice que se esperaba un }; como el cierre de llave está fuera de una etiqueta JSP, el intérprete no lo entiende. Sin embargo, si cometemos un error de sintaxis Java, la cosa estará un poco más clara:

org.apache.jasper.JasperException: No se puede compilar la clase para JSP

An error occurred at line: 10 in the jsp file: /hola.jsp

Generated servlet error:
/var/tomcat4/work/localhost/jmerelo/hola$jsp.java:83: Invalid expression statement.
                 } ese { 
                   ^


An error occurred at line: 10 in the jsp file: /hola.jsp

Generated servlet error:
/var/tomcat4/work/localhost/jmerelo/hola$jsp.java:83: ';' expected.
                 } ese { 

Como los errores no son muy informativos, muchas veces no queda otro remedio que leer bien leido el código de error, y mirar las fuentes, a ver qué es lo que le ha molestado. En estas cosas, como en otras muchas, la experiencia es un grado.

Ejercicios
1. Usando la clase java.util.Date, hacer un JSP que imprima la hora y los minutos, y probarlo en algún servidor gratuito o en un servidor propio

Contenido de esta sección
  • Etiquetas jsp
  • Clases en Java. Beans

Elementos adicionales del JSP. Beans.

A partir de este momento, vamos a intentar montar paso a paso una quiniela en Internet, que la gente pueda rellenar, votar los resultados, y, finalmente, sacar un resumen de todos para que en la oficina se rellene la quiniela común de acuerdo con ello (aunque siempre hay un asaúra que está en desacuerdo, y que quiere ponerle un 2 al Depor-Recre).

Para empezar, vamos a montar simplemente un JSP que presente el resultado de un partido, un resultado que incluiremos también dentro de la página (resultado0.jsp; y en acción en iSavvix)

.

<%! public class Partido {
    String juegaEnCasa;
	String juegaFuera;
	boolean[] pronostico = new boolean[3];
    public String getJuegaEnCasa() {
		return this.juegaEnCasa;
    }
	public void setJuegaEnCasa( String _newVal) {
		this.juegaEnCasa = _newVal ;
    }
	public String getJuegaFuera() {
		return this.juegaFuera;
    }
	public void setJuegaFuera( String _newVal) {
		this.juegaFuera = _newVal ;
    }
	public boolean[] getPronostico() {
		return this.pronostico;
	}
    public void setPronostico(boolean[] _newVal) {
        for ( int i = 0; i < 3; i ++ ) {
		  pronostico[i] = _newVal[i];
        }  
    }
}%>
<%! Partido estePartido = new Partido(); %>
<html>
<head><title>Resultado de un partido - con scriptlets</title></head>
<%@ include file='cabecera.jsp' %>
<h1>Ejemplo 2: Resultados de la quiniela</h1>
<table border borderwidth='1'>
<tr><th colspan="2">Partido</th><th colspan="1">Pronostico</th></tr>
<%	estePartido.setJuegaEnCasa( "Madrid" );
		estePartido.setJuegaFuera("Barcelona" );
        boolean[] pronostico = new boolean[3];
		for ( int i = 0; i < 3; i ++ ) {
		  pronostico[i] = true;
        }  
		estePartido.setPronostico( pronostico ); %>
<td><%= estePartido.getJuegaEnCasa()  %> </td><td> <%= estePartido.getJuegaFuera() %>
<%!  boolean[] estePronostico = estePartido.getPronostico(); %>
<td><% if (estePronostico[0] ){ %>1 <% } %><% if (estePronostico[1] ){ %>X <% } %>
<% if (estePronostico[2] ){ %>2 <% } %>
</table>
<%@ include file='pie.jsp' %>

El JSP es un poco extenso, sobre todo por el código Java insertado. Este código crea una clase llama Partido, que consta de los dos equipos que juegan, en casa y fuera, y del pronóstico. El pronóstico se define como un array de 3 booleanos, uno para cada resultado posible; 1, X o 2 (gana el equipo de casa, empate o gana el de fuera). Los pronósticos se pueden combinar (son las llamadas apuestas múltiples), de forma que un posible resultado a un partido puede ser X, 12 o incluso 1X2. La clase se compone de tres pares de métodos, para establecer el valor (set) de una variable, y para devolver (get) el valor de la misma.

A continuación, se crea una instancia de la clase llamando a new; el objeto estePartido contendrá el valor de la variable, y lo compartirán todas las llamadas al JSP. No es que sirva de mucho la compartición, pero lo hemos dejado así.

Unas líneas más abajo se usa la etiqueta jsp:include, nuestra primera etiqueta JSP. Es una orden específica de JSP, que en el servidor, antes de crearse la respuesta que se envíe al cliente, se ejecutará, incluyendo, en este caso, un fichero JSP (o uno HTML). Si se trata de un fichero JSP, este fichero, a su vez, se interpretará y se incluirá el resultado en la página. Esto se puede hacer también de la forma siguiente:

<%@ import file='cabecera.jsp' >

con la diferencia de que, en este caso, primero se incluye el contenido del fichero y luego se interpreta. import es una directiva de tiempo de compilación, mientras que jsp:include actúa en tiempo de ejecución. En este caso, se incluye una pequeña cabecera común a todos los ejercicios, de la misma forma que, al final del fichero, se incluye un pie, que cierra el fichero HTML y los cambios de fuente.

En el siguiente scriptlet se establecen los valores de las variables llamando a los métodos set, para después recuperarlos dentro de una tabla, usando los métodos get; el resultado del array booleano que devuelve getPronostico se tiene que formatear para convertirse en 1X2

En realidad, para lo que hemos hecho, podíamos habernos ahorrado tanta clase y tanto JSP y tanta gaita, pero nos sirve para introducir un concepto que resulta terriblemente útil en el mundo del JSP: las habichuelas o beans. Los beans están definidos por un estándar de Sun, y tienen cierta complejidad, pero desde el punto de vista de los JSPs son simplemente clases en las cuales las variables pueden ser accedidas mediante métodos set (para cambiar su valor) y get para recuperar su valor; los métodos set se llaman con un sólo argumento del mismo tipo que la variable de instancia, y los métodos get devuelven un objeto del tipo de la variable de instancia, sin tomar ningún argumento. No todos los métodos set tienen que corresponder a una variable de instancia, ni tampoco los get; pero todos los métodos que devuelvan un valor tienen que tener esa estructura, igual que todos los que alteren un valor. La clase Partido anterior es un Bean, igual que lo es la siguiente, ligeramente ampliada (quiniela/Partido.java):


package quiniela;

public class Partido {

    String juegaEnCasa;
	String juegaFuera;
	boolean[] pronostico = new boolean[3];
	String  unoequisdos="1X2";

    public String getJuegaEnCasa() {
		return this.juegaEnCasa;
    }

	public void setJuegaEnCasa( String _newVal) {
		this.juegaEnCasa = _newVal ;
    }
	public String getJuegaFuera() {
		return this.juegaEnCasa;
    }
	public void setJuegaFuera( String _newVal) {
		this.juegaFuera = _newVal ;
    }
	public boolean[] getPronostico() {
		return this.pronostico;
	}
    public void setPronostico(boolean[] _newVal) {
		this.pronostico = pronostico;
    }
	public void setPronosticoAsString(String _newVal) {
		for ( int i=0;  i < 3; i++ ) {
			if ( _newVal.indexOf(this.unoequisdos.charAt(i)) >= 0 ) {
				this.pronostico[i] = true;
			} else {
				this.pronostico[i] = false;
			}
		}
    }
	public String getAsString() {
		String str=this.juegaEnCasa + "-" + this.juegaFuera + ": ";
		for ( int i = 0; i < 3; i ++ ) {
			if ( this.pronostico[i] ) {
				str += this.unoequisdos.charAt(i);
			}
		}
		return str;
	}

	public String getFormatted() {
		String str= "<tr><td>" + this.juegaEnCasa + "</td><td>" + this.juegaFuera + "</td>";
		for ( int i = 0; i < 3; i ++ ) {
			if (this. pronostico[i] ) {
				str += "<td>" + unoequisdos.charAt(i)+ "</td>";
			} else {
				str += "<td bgcolor=black> </td>";
			}
		}
		str += "</tr>";
		return str;
	}
}

Los beans se pueden usar fácilmente desde los JSPs, usando etiquetas. El JSP anterior se puede poner de la forma siguiente, usando beans (resultado.jsp; el resultado en acción es prácticamente igual al caso anterior):


<%@ page import = "quiniela.Partido" %>

<jsp:useBean id="estePartido" class="quiniela.Partido"  />
<jsp:setProperty name="estePartido" property="juegaEnCasa" value="Madrid" />
<jsp:setProperty name="estePartido" property="juegaFuera" value="Barça" />
<jsp:setProperty name="estePartido" property="pronosticoAsString" value="1X2" />
<html>
<head><title>Resultado de un partido</title></head>
<%@ include file ="cabecera.jsp" %>
<h1>Resultados de la quiniela</h1>
<table border borderwidth='1'>
<tr><th colspan="2">Partido</th><th colspan="3">Pronostico</th></tr>
<jsp:getProperty name="estePartido" property="formatted" />
</table>
<%@ include file ="pie.jsp" %>

Antes de que esto funcione, hay que compilar la habichuela y ponerla en su sitio correspondiente. En este caso, tendremos que colocarla en el subdirectorio WEB-INF/classes/quiniela; las dos primeras partes corresponden al camino en el que hay que colocar todos los .class, y quiniela es el nombre del package en el que hemos metido nuestra clase Partido. Todas las clases compiladas de este paquete tendrán que ir a ese directorio. Los JARs irán también dentro de su directorio correspondiente, así como otros ficheros que no se destinan directamente a servirse al público.

El JSP usa la orden en tiempo de compilación explicada anteriormente para importar la habichuela dentro del contexto de la página. Posteriormente, declara un bean llamado estePartido mediante la etiqueta jsp:useBean. Esta etiqueta crea un Bean de una clase determinada; es el equivalente a llamar a new en Java. Las propiedades de ese bean (las variables accesibles mediante get y set) se usarán a través de los métodos jsp:getProperty y jsp:getProperty; es decir, <jsp:setProperty name="estePartido" property="juegaEnCasa" value="Madrid" /> es equivalente a estePartido.setJuegaEnCasa( "Madrid" ). El atributo property incluye a la propiedad a la que se va a acceder; a esa propiedad se pone la primera letra en mayúscula y se le precede con get o set para hallar el método de la clase al que hay que llamar. Las líneas siguientes establecen los valores de las tres propiedades del bean. Posteriormente, se imprimen los valores devueltos por esas propiedades. Únicamente hay que fijarse un poco en la propiedad formatted; en realidad, consiste en una llamada a un método sin correspondencia con ninguna variable de instancia; al JSP le da exactament igual, y llama al método correspondiente.

Como los errores no son muy informativos, muchas veces no queda otro remedio que leer bien leido el código de error, y mirar las fuentes, a ver qué es lo que le ha molestado. En estas cosas, como en otras muchas, la experiencia es un grado.

Ejercicios
1. Crear un bean para una pregunta a una encuesta y su respuesta correspondiente, y un JSP que lo presente en pantalla.
2. Modificar el JSP anterior para que presente los 14 resultados de la quiniela.

Contenido de esta sección
  • Acceso a objetos implícitos
  • Contenido dinámico
  • Excepciones

Páginas dinámicas.

Como para hacer páginas estáticas, ya tenemos el HTML propiamente dicho, vamos a meter un poco de dinamismo en las páginas, permitiendo que se modifique la página según cómo se la llame. Más adelante veremos cómo hacer que el usuario introduzca esos datos directamente. Para empezar, haremos que la página varíe dependiendo de la forma cómo se la invoque, en la pagina siguiente (resultadoDyn.jsp)


<%@ page import = "quiniela.Partido" %>
<jsp:useBean id="estePartido" class="quiniela.Partido"  />
<jsp:setProperty name="estePartido" property="*"  /> 
<html>
<head><title>Resultado de un partido dinámico</title></head>
<-- El resto igual -->
Resultado del script dinámico

En este caso, usamos, igual que en los ejemplos anteriores, jsp:setProperty, pero ahora le asignamos valores a todas las propiedades a la vez tomándolas de los argumentos con los que se llama el JSP; si lo llamamos de la forma siguiente http://localhost:8080/jmerelo/resultadoDyn.jsp?juegaEnCasa=Osasuna&juegaFuera=Villareal&pronosticoAsString=X; se llamarán a las tres propiedades correspondientes, y se les asignará el valor indicado. La sintaxis que se sigue en esas llamadas es nombredel.jsp?variable=valor&variable=valor, y así sucesivamente. Es la sintaxis normal para pasar valores a los programas que se ejecutan en el servidor, tal como los JSPs. El resultado se puede ver en la imagen

Al usar los parámetros que se pasan al JSP, estamos utilizando en realidad un objeto implícito del JSP, el objeto request, una instancia de la clase javax.servlet.http.HttpServletRequest, exactamente igual que se usa en los servlets (y es que, en realidad, se tratan de la misma cosa). Podemos acceder a él tal como se hace en el siguiente ejemplo (resultadoDyn2.jsp), que sólo varía unas líneas con respecto al anterior:

<tr><td colspan='5'><em>Comentario</em><% if (request.getParameter("pronosticoAsString") == "X" ) { %>
Empate 
<% } else if (request.getParameter("pronosticoAsString") == "1" ) { %>
Gana el de casa 
<% } else { %>
Gana visitante
<% } %> </td></tr>

Aquí estamos usando el objeto implícito request, llamando a su método getParameter para obtener el valor del parámetro de llamada pronosticoAsString. Este objeto tiene los mismos métodos que el equivalente de servlets, así que no nos extendemos más en él. Los más útiles son el anterior, getParameterNames y getParameterValues; otros, tales como getCookies, se usarán para obtener las cookies del cliente. En este caso, se incluirán en la salida diferentes cadenas dependiendo del valor del pronóstico; si es un resultado múltiple, no se incluirá nada.

Hay otros objetos implícitos; probablemente los más usados sean session, que maneja las variables de sesión, y application, con métodos relativos al contexto dónde se está ejecutando el servlet al que corresponde el JSP.

¿Qué puede ocurrir si alguno de los parámetros pasados tiene un valor inválido? Por ejemplo, se podían validar que los equipos correspondieran a la misma división, o que los pronósticos estén siempre compuestos de 1, equis o doses; hasta el momento, no se hace ningún tipo de comprobación. Para ello, tendremos que modificar ligeramente el bean, haciendo que el método setPronosticoAsString tire una excepción si se encuentra con un carácter inválido en la cadena que se le pasa. Después de cambiarle el nombre a la clase ( quiniela/PartidoValidado.java):

public void setPronosticoAsString(String _newVal) throws RuntimeException{
		if (_newVal.length() > 3) 
			throw new RuntimeException ( "Pronóstico más largo de la cuenta" );
		if (_newVal.length() == 0) 
			throw new RuntimeException ( "No hay pronóstico" );
		for ( int j = 0; j < _newVal.length(); j ++ ) {
			if ( _newVal.charAt(j) != '1' &&  _newVal.charAt(j) != 'X'
				 &&  _newVal.charAt(j) != '2' ) {
				throw new RuntimeException ( "Carácter raro en cadena:"+  _newVal.charAt(j) + " en la posición " + j );	
			}
		}
		for ( int i=0;  i < 3; i++ ) {
			if ( _newVal.indexOf(this.unoequisdos.charAt(i)) >= 0 ) {
				this.pronostico[i] = true;
			} else {
				this.pronostico[i] = false;
			}
		}
    }

Con respecto a la versión anterior, se han añadido una serie de comprobaciones de longitud excesiva, demasiado pequeña, o si hay algún carácter que no sea 1X2. Capturar la excepción en un programa en Java es fácil (con las sentencias try y catch), pero, en un JSP nos encontraremos algo así:

java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Pronóstico más largo de la cuenta
	at
				quiniela.PartidoValidado.setPronosticoAsString(PartidoValidado.java:31)

Para ello se usan las páginas de error, que se llaman en caso de que se haya producido una excepción; es más o menos lógico que no se traten las excepciones dentro de la misma página, porque, en algunos casos, pueden producirse antes incluso de que el código haya sido generado. Para usar la página de error, incluimos al principio del fichero ( resultadosDynVal.jsp):

<%@ page errorPage="paginaError.jsp?debug=log" %>
<% request.setAttribute("paginaOrigen", request.getRequestURI()); %>

Con esto se declara una página de error, y se asigna un atributo a la petición, que almacenará el URI de la peticición, es decir, el camino con el que se la ha llamado. El código de la página de error es el siguiente ( paginaError.jsp):

<%@ page isErrorPage="true" %>
<html>
<head><title>Se ha producido un error</title></head>
<%@ include file ="cabecera.jsp" %>
<h1>Se ha producido un error</h1>

<p>Endeluego, que a ver si tenemos cuidaico, que se ha producido el siguiente error:<br>
<%= exception.getMessage() %> en la página
				 <%= request.getAttribute("paginaOrigen") %>
<%@ include file ="pie.jsp" %>

Lo más importante es la primera línea: la página se declara a sí misma como una página que responde a los errores, lo cual permite que se cree el objeto implícito exception. Ese objeto se usa más adelante para imprimir el mensaje que se ha producido (aunque no siempre funciona). También se recupera un atributo del objeto implícito request, que había sido puesto por la página que ha producido el error, para que se sepa de dónde procede el error. Cuando se produzca alguna entrada errónea, por ejemplo, pronosticoAsString=123, se producirá una excepción en el objeto PartidoValidado, que se propagará al JSP que la contiene, que a su vez llamará a esta página de error

.

Ejercicios
1. Cambiar la encuesta para que tome los resultados de los parámetros que se le pasen al JSP .
2. Cambiar la EncuestaBean para que detecte errores (tales como una respuesta incorrecta), y levante una excepción; crear una página de error que capture esa excepción y la muestre.

Contenido de esta sección
  • Formularios
  • Combinación de elementos JSP
  • Ámbitos
  • Taglibs

Procesamiento de formularios

Ya está bien de tanto objeto implícito y tanta gaita, vamos a ir directamente al turrón de procesar formularios como Dios manda. Vamos a tratar de hacer una página JSP que cree y a la vez procese el formulario; de esta forma es más fácil de mantener. El formulario nos permitirá rellenar la quiniela sin hacer nada en concreto con ella, sólo presentarla. En la práctica, habría probablemente que almacenar los resultados en una base de datos, o por lo menos un fichero, pero por lo pronto, lo dejaremos así. El formulario se implementa en el código siguiente:(quiniela.jsp, que usa la clase Quiniela:)


<%@ page import = "quiniela.*" %>
<jsp:useBean id='estaQuiniela' class="quiniela.Quiniela" scope='request'/>
<jsp:setProperty name='estaQuiniela' 
		  property='inputFile' value= "/home/jmerelo/public_html/JSP/quiniela.dat" /> 

<html>
  <head>
    <title>Rellena tu quiniela</title>
  </head>
<%@ include file ="cabecera.jsp" %>
    <h1>Rellena tu quiniela</h1>
<form action='quiniela.jsp' method='get' >
<%  for ( int i = 0; i < estaQuiniela.getNumPartidos(); i ++ ) { 
	String proStr = "pronostico"+i; 
	try { %>
<jsp:setProperty name='estaQuiniela' property='numPartido' value="<%= i %>" />
<%        if ( request.getParameter("pronostico0") != null ) { %>
<jsp:setProperty name='estaQuiniela' property='pronosticoAsString' value="<%= request.getParameter( proStr) %>" />
<%        } else { %>
<jsp:setProperty name='estaQuiniela' property='pronosticoAsString' value="1X2" />        
<%        }
        } catch (Exception _e ) {
		System.err.println( "Esto no debiera pasar: " + _e.getMessage() );
	}
    }%>
<table border>
		  <tr><th> </th><th>Partido</th><th>Pronóstico</th><th>Pronóstico Anterior</th>
		  </tr>
<% for ( int i = 0; i < estaQuiniela.getNumPartidos(); i ++ ) { 
	      String proStr = "pronostico"+i; %>
<tr><td><%= i %></td>
<jsp:setProperty name='estaQuiniela' property='numPartido' value="<%= i %>" />
<td><jsp:getProperty name='estaQuiniela' property='juegaEnCasa'  />-
<jsp:getProperty name='estaQuiniela' property='juegaFuera'  /></td>
				  <td><input type='text' name='pronostico<%= i %>' value='<jsp:getProperty name='estaQuiniela' property='pronostico' />' ></td>
					<td><jsp:getProperty name='estaQuiniela' property='pronostico' /> </td>
				</tr>
<% } %>
<tr><td colspan="4" align="center"><input type='submit' ></td>
				</tr>
			  </table>

</form>
<%@ include file ="pie.jsp" %>
Para quien no haya trabajado con formularios (ver por ejemplo este tutorial de formularios o bien este tutorial de HTML, que incluye también formularios)

Para empezar, hemos creado un nuevo bean que contiene un vector de partidos, llamado Quiniela; este bean será el que usemos en la página; en general, es una buena idea reflejar la estructura de una página en un bean, o viceversa. En el caso anterior usábamos los beans Partido y PartidoValidado, y en este caso usamos esta. La única peculiaridad de esta clase es que, debido a su estructura como Bean, no se puede llamar a ningún método con dos argumentos, por lo que tenemos que establecer un cursor de partido que indique sobre qué partido van a actuar los métodos que ponen o extraen valores de la clase

El objeto que va a contener la quiniela se declara en las primeras líneas, mediante el tag <jsp:useBean>. A continuación se le pasa el fichero quiniela.dat, que contiene los datos de una quiniela (de primera división universal especial, como se puede comprobar). A continuación, después de abrir el formulario, se detecta si se ha usado uno de los datos del mismo (pronostico0), en cuyo caso se empieza a procesarlo: se crea una cadena con el nombre del parámetro (pronostico + el índice), se usa esa cadena para colocar el cursor (%lt;jsp:setProperty name='estaQuiniela' property='numPartido' value="<%= i %>" />) y se asigna el pronóstico al partido correspondiente de la quiniela. Como se ve, este formulario sirve para las dos cosas: para recibir las entradas, y para procesarlas.

En las siguientes líneas se presentan los resultados que se han introducido lado a lado con una serie de cuadros de texto que permiten cambiar el pronóstico.

Este código se puede mejorar un tanto, evitando errores en origen poniendo checkboxes (es decir, cuadraditos sobre los cuales se puede pinchar) en vez de introducirlo mediante el teclado. Eso no quiere decir que se tenga que eliminar el código de corrección de errores, porque siempre se puede modificar a mano la petición al servidor. Simplemente, se le evitan problemas al usuario. Eso se hace en la siguiente versión quinielaBoton.jsp:


<!-- El principio es similar >
<%  for ( int i = 0; i < estaQuiniela.getNumPartidos(); i ++ ) { 
	String proStr = "pronostico"+i; 
	String strPronostico ="";
	String[] params = request.getParameterValues( proStr );%>
<jsp:setProperty name='estaQuiniela' property='numPartido' value="<%= i %>" />
<%        if ( request.getParameter("submit") != null ) { 
        for ( int j = 0; j < params.length; j ++ ) { strPronostico += params[ j ]; } 
 %>
<jsp:setProperty name='estaQuiniela' property='pronosticoAsString' value="<%= strPronostico % >" />
<%        } else { %>
<jsp:setProperty name='estaQuiniela' property='pronosticoAsString' value="1X2" />  
<%        }    
    }%>
<table border>
		  <tr><th rowspan='2'> </th><th rowspan='2'>Partido</th><th colspan='3'>Pronóstico</th><th rowspan='2'>Pronóstico Anterior</th>
		  </tr>
		  <tr><td>1</td><td>X</td><td>2</td>
		    </tr>
<% for ( int i = 0; i < estaQuiniela.getNumPartidos(); i ++ ) { 
	      String proStr = "pronostico"+i;
 %>
<tr><td><%= i %></td>
<jsp:setProperty name='estaQuiniela' property='numPartido' value="<%= i %>" />
<td><jsp:getProperty name='estaQuiniela' property='juegaEnCasa'  />-
<jsp:getProperty name='estaQuiniela' property='juegaFuera'  /></td>
		      <%    boolean[] pronosticos =  estaQuiniela.getPronostico();
		      for ( int j = 0; j < 3; j ++ ) { %>
		      <td><input type='checkbox' name='pronostico<%= i %>' value='<%= quiniela.PartidoValidado.get1X2( j ) %>' <%= pronosticos[j]==true?"checked":"" %>' ></td>
                      <% } %>
					<td><jsp:getProperty name='estaQuiniela' property='pronosticoAsString' /> </td>
				</tr>
<% } %>
<tr><td colspan="4" align="center"><input type='submit' name='submit' value='Enviar'></td>
				</tr>
			  </table>

</form>

El truqui del asunto está al principio: en vez de usar getParameter para coger un solo parámetro, se usa getParameterValues, que devuelve un array con todos los valores que tiene un parámetro; en este caso, cada grupo de 3 botones usa el mismo nombre de elemento del formulario, por eso cada parámetro tendrá tantos elementos como botoncitos se hayan rellenado. En todo caso, se pegan los parámetros en una sola cadena, que se usa para asignarle un valor al pronóstico.

En cuanto al formulario, en este caso tenemos que usar el pronóstico como un array de valores booleanos (en vez de una cadena como hacíamos anteriormente), porque nos conviene más a la hora de poner el valor por defecto a los botones. Usamos también un método de clase de Java, para pasar de un índice de 0 a 2 al símbolo correspondiente (1, X o 2).

Pero claro, lo interesante no es sólo presentar los datos del formulario, sino agregarlos en unas estadísticas para toda la oficina (y de camino, fastidiar al asaúra mostrándole que su pronóstico no lo comparte nadie) y presentarlos en un gráfico chuli. Eso lo haremos en el siguiente programa (stats.jsp):


<%@ page import="quiniela.*" %>

<jsp:useBean id='stats' class='quiniela.Stats' scope='application' />
<jsp:useBean id='estePartido' class="quiniela.PartidoValidado" scope='request' />
<jsp:setProperty name='estePartido' property='juegaEnCasa' value= "Valencia" /> 
<jsp:setProperty name='estePartido' property='juegaFuera' value= "Inter" /> 

<-- El resto similar a los anteriores -->
<%@ include file ="pie.jsp" %>

Este fichero es similar a los anteriores que se han tratado, pero en este caso se usa un bean que tiene ámbito de aplicación, indicándolo con scope='application' . Eso significa que va a poder ser "visto" por todos los demás servlets y JSPs del servidor; sería algo así como una variable del servidor. Esto lo vamos a usar para poder compartir información entre diferentes invocaciones y diferentes JSPs.

Hay cuatro ámbitos diferentes en las variables usadas en JSPs y servlets:

.

Este último ámbito es el que usamos precisamente en esta página. Para entendernos, serían como una especie de objetos persistentes, que estarán ahí hasta que rearranquemos el servidor. Y precisamente eso es lo que vamos a hacer, usarlos para ver esas estadísticas en plan chuli (viewstats.jsp).

<%@ taglib uri="bartag.jar" prefix="bar" %>
<%@ page import="quiniela.*" %>
<jsp:useBean id='stats' class='quiniela.Stats' scope='application' />
<html>
  <head>
    <title>Ver Estadísticas de la quiniela</title>
  </head>
<%@ include file ="cabecera.jsp" %>
    <h1>Ver Estadísticas de la quiniela</h1>
      <table border>
	<tr><th>Partido</th><th colspan='2'>Estadísticas</th>
	</tr>
	<tr>
	  <td>Alcorcón - Vitigudino</td>
	  <td><bar:Hbar values="<%= stats.getAsString() %>" fgcolor="#FF0000" width="220" labels="1,X,2" bgcolor="#0000FF" />
	  </td>
	  <td><%= stats.getAsString() %></td>
	</tr>
      </table>
      <%@ include file ="pie.jsp" %>
[pantallazo del fichero
     viewstats.jsp ejecutado]

Las novedades de este nuevo fichero empiezan pronto: en la primera línea. Los gráficos no es algo que se pueda hacer con JSPs así, a pelo, así que usamos una librería de etiquetas, una tag library. En este caso se trata de la librería barchart, una taglib para hacer gráficos de barras horizontales y verticales. Instalarla es fácil: hacen falta dos ficheros: el archivo de clases de java, .jar, y una descripción de las etiquetas y su correspondencia con métodos y clases, .tld. Cada uno de estos ficheros suele ir a un sitio diferente: el primero a WEB-INF/lib y el segundo a WEB-INF/tlds. También pueden ir al mismo directorio donde esté el fichero correspondiente, pero será más complicado de usar desde otros JSPs. La taglib esta también está disponible en iSavvix, entre otras muchas

Las taglibs son simplemente un cambio de interface con respecto al código Java normal; te ahorran insertar código dentro de las páginas, y son, en general, más fáciles de mantener, porque, en el más puro estilo OO, encapsulan su lógica y el que las usa no tiene que preocuparse por cómo hacen lo que hacen, sólo por acceder a ellas. Hay muchas gratuitas, y hay colecciones tales como esta de JSPin. Sin embargo, la que usamos aquí no lo es, y sólo permite cinco datos simultáneos, así que tendremos que hacer un gráfico chiquitito.

En este caso no nos hemos complicado la vida y hemos puesto directamente el fichero en el mismo directorio que el fichero JSP correspondiente; eso lo indicamos con uri="bartag.jar" ; además, tenemos que definir el prefijo (en realidad, el espacio de nombres) que vamos a usar para referirnos a esa taglib: en este caso prefix="bar" indica que el prefijo va a ser bar (barra).

Con esta taglib se pueden hacer barras horizontales y verticales; nosotro susamos las barras horizontales bar:Hbar, a las que hay que pasarle los valores que se quieren representar separados por comas, y otra serie de atributos que establecen los colores, la anchura y las etiquetas de cada uno de los valores que se le han pasado. El resultado es el que se muestra en la figura.

Ejercicios
1. Hacer un formulario con una encuesta que guarde estadísticas sobre las respuestas contestadas
2. Usar una librería de etiquetas que incluya bucles, y convertir algún JSP anterior que use bucles java a uno que use los bucles de la taglib.
3. Hacer un JSP que contenga un carrito de la compra usando beans con ámbito de sesión.

Bibliografía y enlaces relacionados con JSP

Enlaces en Internet

Para empezar, hay que mencionar el debate generado por la publicación de este debate en Barrapunto, donde puedes participar si quieres: http://barrapunto.com/article.pl?sid=02/03/18/0837221. En la discusión sugieren otras alternativas, enlaces interesantes, y discuten las ventajas e inconvenientes de los JSPs frente a otras alternativas.

El más popular en Amazon parece ser Beginning JSP Web Development by Jayson Falkner (Editor), John Timney, Casey Kochmer, Romin Irani, Perrumal Krishnaraj, Meeraj Moidoo Kunnumpurath, Sathya Narayana Panduranga, Ben Galbraith. Uno de los clásicos "libros rojos" de Wrox press, explica todos los aspectos de la programación con JSP: librerías de etiquetas, programación con base de datos, Tomcat...
Como siempre, los libros de O'Reilly son garantía de calidad, y JavaServer Pages (segunda edición) by Hans Bergsten no podía ser menos. Un poco más condensado que el anterior, explica inicialmente HTTP y los servlets, para meterse luego en profundidad en faena hablando de sesiones, acceso a base de datos, programación con XML y otras cosas que se hacen habitualmente con JSPs. También se puede acceder desde Safari, en caso de que estés suscrito a ese servicio y a la referencia de bolsillo .

Juan Julian Merelo Guervos
Last modified: Fri Oct 22 11:01:20 CEST 2004