Reusabilidade com Tag Files

 

Olá pessoal!

 

Neste artigo iniciaremos o estudo desse recurso que pode aumentar muito a nossa produtividade. Será presumido que já existe um conhecimento básico da JSTL (Java Standard Tag Library).

 

Antes da especificação 2.0 do JSP, o único jeito de criarmos tags de componentes personalizados era através de classes Java. Umas das dificuldades dessa abordagem é que o código HTML fica embutido dentro da classe. Vejamos um exemplo:

 

Exemplo1.Java

public class Exemplo1 extends SimpleTagSupport {

   

    public void doTag() throws JspException {

       

        JspWriter out=getJspContext().getOut();

       

        try {

           

            JspFragment f=getJspBody();

            if (f != null) f.invoke(out);

           

            out.print("<h1>Exemplo de uma Custom Tag antes da especificação JSP 2.0</h1>");

        } catch (java.io.IOException ex) {

            throw new JspException(ex.getMessage());

        }

       

    }

}

 

Observem como ficaria complicado para um designer que, geralmente, não sabe programar em Java, dar manutenção em um código como este. Além disso, a legibilidade do código fica prejudicada, pois temos que ficar separando o que é HTML do que é Java e olhem que o nosso componente nem tem Javascript! :)

 

A nova especificação veio para suprir tal necessidade. Com a nova especificação o nosso componente fica assim:

 

Exemplo2.tag

<%@tag pageEncoding="UTF-8" body-content="empty"%>

<h1>Exemplo de uma Custom Tag com a especificação JSP 2.0</h1>

 

O código do nosso componente é praticamente igual ao código de uma página JSP, com exceção de algumas particularidades que veremos adiante. 

 

Certo, mas para que servem estes componentes personalizados!?

 

Suponhamos que somos desenvolvedores de uma fábrica de software. Tomemos como ponto de partida a seguinte página JSP:

 

Pagina1.jsp

<%@page contentType = "text/html" %>

<%@page pageEncoding = "UTF-8" import = "java.util.*;" %>

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

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

   "http://www.w3.org/TR/html4/loose.dtd">

 

<html>

    <head>

        <meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8">

        <title>Fabrica de Software - Listagem de Pessoas</title>

    </head>

    <body>

        <jsp:useBean id = "dataAtual" class = "java.util.Date" />

        <fmt:formatDate var = "dataAtualFormatada" value = "${dataAtual}" pattern = "dd/MM/yyyy HH:mm" />

        <p align = "right"><c:out value = "${dataAtualFormatada}" /></p>

        <hr/>

        <%

            List pessoas = new ArrayList();

            pessoas.add("Pessoa A");

            pessoas.add("Pessoa B");           

            pessoas.add("Pessoa C");           

            pessoas.add("Pessoa D");  

           

            pageContext.setAttribute("pessoas",pessoas);

        %>

        <label for = "pessoas">Pessoa: </label>

        <select name = "pessoas">

            <c:forEach var = "pessoa" items="${pessoas}" varStatus="status">

                <option value="${status.index}">${pessoa}</option>

            </c:forEach>

        </select>

        <hr/>

        <p align="center">Copyright © 2006 Fábrica de Software Todos os direitos reservados. </p>

    </body>

</html>

 

É uma página bastante simples. Temos algumas informações: o copyright da nossa empresa, uma combo com uma lista hipotética de pessoas e a data atual sendo exibida. Para simplificar o nosso estudo, a lista foi alimentada diretamente na página. Em uma aplicação real essa lista seria obtida, provavelmente, de um banco de dados. Seria também uma ótima idéia utilizarmos o padrão Model-View-Controller.

 

Enquanto isso, em uma segunda página...

 

Pagina2.jsp

<%@page contentType = "text/html" %>

<%@page pageEncoding = "UTF-8" import = "java.util.*;" %>

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

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

   "http://www.w3.org/TR/html4/loose.dtd">

 

<html>

    <head>

        <meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8">

        <title>Fabrica de Software - Listagem de Produtos</title>

    </head>

    <body>

        <jsp:useBean id = "dataAtual" class = "java.util.Date" />

        <fmt:formatDate var = "dataAtualFormatada" value = "${dataAtual}" pattern = "dd/MM/yyyy HH:mm" />

        <p align = "right"><c:out value = "${dataAtualFormatada}" /></p>

        <hr/>

        <%

            List produtos = new ArrayList();

            produtos.add("Produto 1");

            produtos.add("Produto 2");           

            produtos.add("Produto 3");            

            produtos.add("Produto 4");  

           

            pageContext.setAttribute("produtos",produtos);

        %>

        <label for = "produtos">Produto: </label>

        <select name = "produtos">

            <c:forEach var = "produto" items="${produto}" varStatus="status">

                <option value="${status.index}">${produto}</option>

            </c:forEach>

        </select>

        <hr/>

        <p align="center">Copyright © 2006 Fábrica de Software Todos os direitos reservados. </p>

    </body>

</html>

 

O que mudou? A nossa página agora possui uma listagem de produtos e não de pessoas. O copyright continuou o mesmo, a exibição da data continuou da mesma forma e, se olharmos mais cuidadosamente, veremos que apesar da lista possuir valores diferentes, ela é construída da mesma forma.

 

Nossa fábrica possui uma demanda de 200 páginas por dia. Com certeza, teremos sempre coisas em comum entre elas. É justamente aí que entram os componentes.

 

Um dos fatores que vão determinar o sucesso de nossa fábrica de software será a produtividade. Os componentes são determinantes neste aspecto, pois nos dão produtividade tanto no desenvolvimento quanto na manutenção de nossas páginas.

 

Uma observação importante é que os arquivos de tag devem ficar dentro do diretório WEB-INF/tags de nossa aplicação web.

 

O nosso primeiro componente será responsável por fornecer o copyright de nossa empresa.

 

Copyright.tag

 

<%@tag pageEncoding="UTF-8" body-content="empty"%>

<p align="center">Copyright © 2006 Fábrica de Software Todos os direitos reservados. </p>

 

Viram como é simples!? Que tal criarmos agora um componente para exibir a data? Este nosso componente receberá como parâmetro o formato da data que queremos exibir, sendo o padrão dd/MM/yyyy HH:mm.

 

DataAtual.tag

<%@tag pageEncoding="UTF-8" body-content="empty"%>

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

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

<%@attribute name="formato" %>

 

<c:choose>

    <c:when test="${empty formato}">

        <c:set var="pattern" value="dd/MM/yyyy HH:mm" />

    </c:when>   

    <c:when test="${not empty formato}">

        <c:set var="pattern" value="${formato}" />

    </c:when>       

</c:choose>

<jsp:useBean id="dataAtual" class="java.util.Date" />

<fmt:formatDate var="dataAtualFormatada" value="${dataAtual}" pattern="${pattern}" />    

<c:out value="${dataAtualFormatada}"/>

 

Os parâmetros são declarados através da diretiva attribute. É importante notar que o tipo padrão para um atributo é String.

 

Criaremos agora um componente comboBox que exigirá como parâmetro uma lista de valores, um label e o nome.

 

ComboBox.tag

<%@tag pageEncoding="UTF-8" body-content="empty"%>

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

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

<%@attribute name="lista" required="true" type="java.util.List" %>

<%@attribute name="label" required="true" %>

<%@attribute name="nome" required="true" %>

<label for="${nome}">${label}</label>

<select name="${nome}">

    <c:forEach var="elemento" items="${lista}" varStatus="status">

        <option value="${status.index}">${elemento}</option>

    </c:forEach>

</select>

 

Analisando o atributo “nome”, podemos perceber que ele é um parâmetro requerido (required=”true”) e que o tipo foi definido (type=”java.util.List”) levando-se em consideração que a variável passada para este atributo não será uma String.

 

Vamos alterar o código de nossas páginas para usarem os nossos componentes.

 

Pagina1.jsp

<%@page contentType = "text/html" %>

<%@page pageEncoding = "UTF-8" import = "java.util.*;" %>

<%@ taglib prefix="custom" tagdir="/WEB-INF/tags/" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

   "http://www.w3.org/TR/html4/loose.dtd">

 

<html>

    <head>

        <meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8">

        <title>Fabrica de Software - Listagem de Pessoas</title>

    </head>

    <body>

        <p align="right"><custom:dataAtual /></p>

        <hr/>

        <%

            List pessoas = new ArrayList();

            pessoas.add("Pessoa A");

            pessoas.add("Pessoa B");           

            pessoas.add("Pessoa C");           

            pessoas.add("Pessoa D");  

           

            pageContext.setAttribute("pessoas",pessoas);

        %>

        <custom:comboBox label="Pessoa:" lista="${pessoas}" nome="pessoa" />

        <hr/>

        <custom:copyright/>

        <hr/>

    </body>

</html>

 

Reparem a diretiva taglib. Nela temos o prefixo (prefix=”custom”) e o caminho onde estão os arquivos de tag (tagdir=”/WEB-INF/tags/”). Abaixo segue o código de nossa segunda página, mostrando a reutilização de nossos componentes:

 

Pagina2.jsp

<%@page contentType = "text/html" %>

<%@page pageEncoding = "UTF-8" import = "java.util.*;" %>

<%@ taglib prefix="custom" tagdir="/WEB-INF/tags/" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

   "http://www.w3.org/TR/html4/loose.dtd">

 

<html>

    <head>

        <meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8">

        <title>Fabrica de Software - Listagem de Produtos</title>

    </head>

    <body>

        <p align="right"><custom:dataAtual /></p>

        <hr/>

        <%

            List produtos = new ArrayList();

            produtos.add("Produto 1");

            produtos.add("Produto 2");           

            produtos.add("Produto 3");           

            produtos.add("Produto 4");  

           

            pageContext.setAttribute("produtos",produtos);

        %>

        <custom:comboBox label="Produto:" lista="${ produtos }" nome="produto" />

        <hr/>

        <custom:copyright/>

        <hr/>

    </body>

</html>

 

Nossos componentes foram uma ‘mão na roda’! Podemos fazer componentes muito mais complexos do que este. Tudo vai depender da necessidade. Que tal ficar como exercício a criação de um componente que utilize javascript para validação e/ou formatação de um campo?

 

E vou deixar também uma pergunta no ar como sugestão de estudo...

 

Se todos os atributos que serão utilizados na tag devem ser declarados, então como passar uma lista de parâmetros dinâmica para a nossa tag? Só por curiosidade, vejam quantos atributos existem em um componente input do HTML. Imaginaram ter que declarar todos eles!? Então...fica a pergunta no ar. :)

 

Conclusões        

Produtividade, produtividade e produtividade. Utilizando componentes bem projetados ganhamos este importante diferencial competitivo com eficácia e eficiência.

 

Bons estudos e até a próxima!

 

Referências

Developing Custom Tag Libraries as Tag Files

http://www.onjava.com/pub/a/onjava/excerpt/jserverpages3_ch11/index.html?page=1

 

Custom Tags in JSP Pages

http://java.sun.com/javaee/5/docs/tutorial/doc/JSPTags.html

 

Creating JSP 2.0 Tag Files

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html

 

MVC

http://pt.wikipedia.org/wiki/MVC

 

Using JSTL

http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSTL3.html