Section 9: Building JSP Pages Using Tag Libraries


 

9.1 For a custom tag library or a library of Tag Files, create the 'taglib' directive for a JSP page.

Los custom tags son elementos/componentes que encapsulan un comportamiento. La idea que subyace detras de los custom tags es que se elimine el código Java en la página JSP. El diseñador podrá usar estos custom tags sin saber como están programados. Los programadores seremos los encargados de proveer estos componentes para que sean usados. Esto implica que el código Java estará en clases, por lo que el diseño será mucho mas limpio.

Para hacer disponibles un conjunto de tags en un JSP, primero debemos declararlo en el JSP. La sintaxis es la siguiente:

<@ taglib prefix="..." [tagdir=/WEB-INF/tags/dir | uri=" ... " ]

El prefijo se usara en todos los tags que se quieran utilizar en el JSP. Debe ser un prefijo unico en todas las páginas donde esta declarado (1. no pueden usarse prefijos estandar como: java, javax, sun, sunw, etc. 2. Tenemos que tener en cuenta las paginas incluidas, ya que el espacio de nombres es unico)

Como se puede ver en la sintaxis, el segundo atributo puede ser uri o tagdir. 'uri' se usa cuando el tag ha sido definido en un tag handler, osea en una clase java.

Ejemplo de la libreria core de JSTL:

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

El uri declara un nombre único, que sera usado en web.xml para definir la ubicación de la libreria de tags de esta manera:

<jsp-config>

    <taglib id="..." >

          <taglib-uri>....</taglib-uri>

          <taglib-location>....</taglib-location>

    </taglib>

</jsp-config>

** el atributo "id" serviría para identificar los diferentes mapeos (ver dtd

Si no especificamos explicitamente la ubicación de la libreria de tags con las entradas anteriores, el container buscar dentro de los jars que deben estar empaquetados de una manera especial.

Finalmente, lo único que resta definir es el TLD (DTD).

<taglib + una serie de atributos>

   <tlib-version></tlib-version>

   <jsp-version></jsp-version>

   <short-name></short-name>

   <tag>

      <name></name>

      <tag-class></tag-class>

      <body-content></body-content>

      <attribute>

         <name></name>

         <required></required>

         <rtexpvalue></rtexprvalue>

      </attribute>

   </tag>

</taglib>

Donde:

- name es el nombre del tag.

- tag-class es el tag handler

- body-content define el contenido del tag: empty, scriptless (sin código Java), tagdependent (el container no evalúa el contenido, sino que el custom tag lo hace) y JSP (el más permisivo de todos).

- dentro de los atributos, tenemos el 'name' de nuevo y luego 'required' que determina si es obligatorio y 'rtexpvalue' que determina si se pueden usar EL para el valor del atributo. 

Si la libreria de tags esta definida usando tag files, usamos el atributo tagdir='/WEB-INF/tags/dir' (los tag files son estudiados con más profundidad en 10.5).

9.2 Given a design goal, create the custom tag structure in a JSP page to support that goal.

La sintaxis de los custom tags es la siguiente:

<prefix:tag attr1="..." ... attrN="..." />

o

<prefix:tag attr1="..." ... attrN="..." >

     body

<prefix:tag />

Por ejemplo:

<ejemplo:mayusculas>federico</ejemplo:mayusculas>

9.3 Given a design goal, use an appropriate JSP Standard Tag Library (JSTL v1.1) tag from the "core" tag library.

Struts fue el primer framework que provee un conjunto de tags con funcionalidad comun a muchas pàginas JSP (iteradores, condicionales, acceso a recursos URL, formateo, internacionalización, etc) pero no fue el único. Muchos frameworks desarrollaron conjuntos de tags. JSTL nace como un proyecto open source de Apache (http://jakarta.apache.org/taglibs/) para estandarizar esto. SUN luego lo incorpora a la especificación en especificiones posteriores.

La libreria estandar de taglibs ofrece tags en las siguientes areas (tabla obtenida del J2EE tutorial 1.4)

La segunda table muestra mas en detalle los Core tags

Soporte de variables

Tag set

El tag set sirve para setear una variable EL o una propiedad de una variable EL en cualquiera de los scopes. Si la variable no existe, entonces es creada (la semantica es la misma que useBean. El valor se puede especificar en el atributo "value" o en el cuerpo del tag:

<c:set value="test" var="foo" />

o

<c:set var="foo">test</set>

El valor puede ser constante o puede ser calculado mediante una EL, como en el siguiente ejemplo:

<c:set value="${valor1 + valor2}" var="valor_final" />

Para especificar el scope, debemos incluir el atributo scope.

<c:set value="${valor1 + valor2}" var="valor_final" scope="session" />

**Si no lo incluimos, toma por default page (como siempre).

Si quisieramos setear una propiedad de una variable EL, debemos reemplazar var por target + property de la siguiente manera:

<c:set value="50" target=${pageContext.session} property="maxInactiveInterval" />

Tag remove

Si queremos borrar una variable EL, utilizamos el tag remove especificando var y scope:

<c:remove var="test" scope="session" />

Control de flujo

Tag if

Este tag permite la ejecución del cuerpo de acuerdo al resultado de la evaluación de una expresión definida en el atributo test:

<c:if test="${!empty param.nombre]"> ... </if>

También se puede guardar el resultado de la evaluación en una variable, para poder usarlo más adelante (si hacemos esto, el cuerpo del tag será vacio)

<c:if test="${!empty param.nombre]" var="es_nom_vacio" scope="session" />

Tag choose, when y otherwise

Estos 3 tags emulan la sentencia switch de java. La diferencia es que solamente se ejecuta el cuerpo de la primera condición verdadera. Si ninguna de las condiciones es verdadera, entonces el cuerpo de default se ejecuta. Por ejemplo:

<c:choose>

   <c:when test="${edad eq 10}">Tiene 10 años</c:when>

   <c:when test="${edad eq 20}">Tiene 20 años</c:when>

   <c:otherwise>no tiene ni 10 ni 20 años</c:otherwise>

</c:choose> 

Tag forEach, forTokens

Este tag nos permite iterar sobre diferentes tipos de Collection. La collection se especifica en el atributo items, mientras que el elemento corriente de la iteración se especifica a través del atributo var.

El siguiente ejemplo nos permite mostrar los primeros elementos de todas las cabeceras:

<c:forEach var="hdr" items="${headerValues}">

    <tr><td>${hdr.key}</td><td>${hdr.value[0]}</td>

<c:forEach>

Este tag soporta todos los tipos de colecciones y Maps. Si es un map, var se va a instanciar con un objeto de tipo Entry. También soporta arrays de primitivas, aunque el valor actual se va a wrappear automaticamente. También soporta String, pero en este caso existe la condición de que los diferentes tokens esten separados por una coma.

Para iterar sobre un conjunto de tokens separados por otro elemento, utilizamos el tag <c:forTokens>. Este tag como se pueden imaginar permite especificar el delimitador, utilizando el atributo "delims".

Manejo de URLs

Tag import

<jsp:include>  nos permite incluir un recurso en tiempo de ejecución. Sin embargo, tiene 2 problemas: 1. no nos permite incluir recursos que esten fuera de la aplicación web. 2. Provoca un buffering innecesario cuando la salida es usada por otro elemento del JSP. El tag import soluciona estos dos problemas.

Entonces, si queremos importar un recurso de otro contexto, lo hacemos de esta manera:

<c:import url="ejemplo1" context="/ejemplo1" />

o directamente incluimos una URL externa

<c:import url=http://www.ejemplo.com/recurso.jsp/>

Si queremos almacenar el recurso incluido, simplemente especificamos la variable y el scope medianle los atributos var/VarReader y scope. VarReader importa el contenido directamente en un reader.

Tag url

Este tag nos permite crear y almacenar una URL para luego ser usada en la JSP.

<c:url value="/lala.jsp" context="/ejemplo1" var="m_link" />

La ventaja que nos brinda este tag con respecto a incluirlo directamente es que escribe el jsessionid en caso que el cliente deshabilite el mecanismo de cookies.

Otra manera de incluir los parámetros es a través de la action c:param de esta manera:

<c:url value="/lala.jsp">

   <c:param name="userid" value="fede">

</c:url>

Tag redirect

Este tag representa exactamente el método HttpServletResponse.redirect(). El atributo obligatorio es url, que puede contener una URL completa (con método y nombre de servidor) o relativa a la URL actual.

<c:redirect url="http://www.clarin.com/espectaculos.asp" />

También se puede incluir una url relativa y el context:

<c:redirect url="ejemplo1.jsp" context="/ejemplo1" /> 

Tag param

Este atributo nos permite añadir parametros a cada uno de los tags anteriores

<c:url value="/lala.jsp" context="/ejemplo1" var="m_link" >

  <c:param name="nombre" value="Fede" />

  <c:param name="apellido" value="Zuppa" />

</c:url>

Miscelaneos

Tag out

El tag out evalua una expresión y manda el resultado a un JspWriter. La sintaxis es la siguiente:

<c:out value=" ... " [escapeXml="{true|false}"] [default="dafaultValue"] />

Si escapeXml=true, el tag transformará las caracteres de XML inválidos en las entidades que corresponden. Por otra parte el atributo default nos permite especificar un valor por default, que será enviado al JspWriter cuando la expresión se evalúa a null.

Tag catch

Este tag nos permite interceptar errores para que no sean propagados. Este tag se ubica rodenado todo el código que pueda arrojar un error.

<c:catch>
    <jsp:scriptlet>out.write(6/0);</jsp:scriptlet>
</c:catch>

Se puede especificar un atributo "var" con el nombre de la excepción para luego ser accedido más adelante.