[Logo] Mentawai Forum - Mentawai Web Framework
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 

Forum Read-Only! Check the new site and forum here!

Criando taglib condicional utilizando Mentawai  XML
Forum Index -> F.A.Q.
Author Message
gapler



Joined: 08/01/2008 12:20:49
Messages: 65
Offline

Antes de entrarmos em maiores detalhes sobre o processo de criação de taglib usando o Mentawai, creio que é importante aprofundarmos um pouco mais nosso conhecimento sobre o que é uma taglib.


Para que serve uma taglib?

Se você já se aprofundou em programação voltada para web, com certeza já se deparou com o uso do JavaServer Pages (JSP). Essa abordagem de programação consiste em implementar comandos Java dentro de sua página web, o que ampliou enormemente a capacidade das páginas em se tornarem mais do que objetos estáticos, tornando-se verdadeiros sistemas, capazes de gerenciar diversas atividades.

Isso, contudo, remete à velhos problemas conhecidos dos programadores - a mistura de regras de negócio com as regras de exibição de dados, trazendo todos as dificuldades inerentes à essa estrutura: impossibilidade de reusabilidade de código, dificuldade de manutenção, constante re-trabalho ao se modificar as regras de negócio, falta de clareza e legibilidade de código gerado.

Vejamos um exemplo clássico de programação em JSP:

Code:
 <html>
     <head>
         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
         <title>Data e Hora Atual</title>
     </head>
     <body>
 
     <h1>JSP Page</h1>
 
     
     <p><b>Data e Hora Atual:</b> 
     <%= Calendar.getInstance().getTime() %></p>
 
     <p><b>Data Minha: </b> <%= new MinhaData().getDataFormatada("dd/MM/yyyy") %></p>
     
     <p><b>Seu Browser:</b> <%= request.getHeader("User-Agent") %></p>
     
     </body>
 </html>


Como se pode notar, é possível se utilizar diretamente comandos java, inclusive com classes proprietárias, dentro de uma página web.

Em uma arquitetura MVC, onde se torna imperativo separar a camada de visualização da camada de negócio, uma taglib é uma forma de abstrair tarefas (como a utilização de comandos java, execução de regras de negócio) de suas páginas JSP.


O Mentawai e as taglibs

Se você já utilizou o Mentawai para criar páginas web, com certeza já se deparou diversas vezes com as taglibs próprias do Mentawai, normalmente anotadas na forma <mtw:algumacoisa. Isso significa, a grosso modo, que existe uma diretiva chamada ?algumacoisa?, dentro de uma tag ?mtw? que irá alguma tarefa específica.

O que essas taglib fazem é abstrair uma série de tarefas de nossa web. Assim, embora você possa ter escrito o seguinte código:

Code:
 <label for="descricao" class="entradadados">Código da Empresa:</label>                            
 <mtw:inputText id="codigoEnt" name="codigoEnt" size="6" maxlength="6" klass="text" onblur='carregaUsers()' />
 <mtw:hasError>  
 <div id="mtwerror">
             		<mtw:error field="codigoEnt"  />
 </div>
 </mtw:hasError>
 <label for="usuario" class="entradadados">Usuário:</label>
 <mtw:ajaxSelect id="selfunc" name="selfunc" sourceValue="codigoEnt" functionName="carregaUsers" url="LoginEnterprise.getListFunc.mtw" />


O que a taglib do Mentawai realiza é transformar esse código da seguinte forma:

Code:
 <label for="descricao" class="entradadados">Código da Empresa:</label>
 <input type="text" name="codigoEnt" class="text" style="text-align:left;" size="6" maxlength="6" id="codigoEnt" value="" onblur="carregaUsers()" />
 <div id="mtwerror">
 	Campo requerido: Não pode ser deixado em branco!
 </div>
 <label for="usuario" class="entradadados">Usuário:</label>
 <script type="text/javascript">
 function carregaUsers() {
 	var r = new mtw.request();
 	r.waitComplete();
 	r.addParameter("sourceValue", mtw.getValue("codigoEnt"));
 	r.setUrl("LoginEnterprise.getListFunc.mtw");
 	r.onSuccess(
 		function (trans){
 			var rq = new mtw.response(trans);
 			mtw.removeOptions("selfunc");
 			mtw.addOptions("selfunc", rq);
 		}
 	);
 	r.useLoadingMessage();
 	r.send();
 }
 </script>
 
 <select  name="selfunc" id="selfunc" style=""></select>


Bom, com esse exemplo é fácil perceber a facilidade de leitura do código que as tags do mentawai propiciam.


A taglib condicional do Mentawai

O Mentawai traz por default a taglib <mtw:if, que permite realizar testes lógicos. Sua sintaxe é basicamente a seguinte:

Code:
 <mtw:if test="nome" value="José">
 // executa a operação caso o nome seja igual a José
 </mtw:if>


Porém, essa taglib somente permite testes com valores parametrizados. Em casos em que seja necessário uma maior flexibilidade de uma estrutura condicional, a <mtw:if> não poderá lhe auxiliar. Porém, embora ela não seja possível de modificação, o Mentawai possibilita que você mesmo expanda sua capacidade, criando suas próprias taglibs condicionais.


Criando sua própria taglib condicional

Vamos imaginar o seguinte cenário: sua aplicação possui uma lista de beans, e você deseja exibir os dados dos mesmos em sua página JSP. Utilizando algumas taglibs do Mentawai, você conseguirá realizar isso de forma fácil. Vamos descrever o bean, para que possa melhor acompanhar o processo:

Code:
 package beans;
 
 public class Person {
 
     private String id;
     private String name;
     private String favoriteColor;
     
     public Person() {
 
     }
 
     public Person(String id, String name, String favoriteColor) {
         setId(id);
         setName(name);
         setFavoriteColor(favoriteColor);
     }
 
     public String getId() {
         return id;
     }
 
     public void setId(String id) {
         this.id = id;
     }
 
     public String getName() {
         return name;
     }
 
     public void setName(String name) {
         this.name = name;
     }
 
     public String getFavoriteColor() {
         return favoriteColor;
     }
 
     public void setFavoriteColor(String favoriteColor) {
         this.favoriteColor = favoriteColor;
     }
 
 }


Iremos criar uma página JSP inicial, com o seguinte conteúdo:

Code:
 <%@page contentType="text/html" pageEncoding="windows-1252"%>
 <!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=windows-1252">
         <title>JSP Page</title>
     </head>
     <body>
         <h2>Go Bean!</h2>
         <form action="CreateListBeans.mtw" method="post">
             <input type="submit" name="submit" value="Go Bean!">
         </form>
     </body>
 </html>


O objetivo dessa página é executar uma chamada à action CreateListBeans, que irá popular os dados dos beans, criar um ArrayList e colocá-lo na saída, para que outra página possa utilizá-lo.

Para definir essas ações, teremos o seguinte ApplicationManager:

Code:
 import actionClass.CreateListBeans;
 import java.io.IOException;
 import org.mentawai.core.*;
 import org.mentawai.filter.*;
 
 public class ApplicationManager extends org.mentawai.core.ApplicationManager {
     
     ActionConfig ac;
     
     public void loadActions() {
         ac = new ActionConfig("/CreateListBeans", CreateListBeans.class);
         ac.addConsequence(CreateListBeans.SUCCESS, new Forward("/showBean.jsp"));
         addActionConfig(ac);        
     }
     
     public void loadLists() throws IOException {
     }
     
     public void loadLocales() {
     }
     
     public void init(Context application) {
     }
 }


Setamos que a ação de /CreateListBeans, irá executar a action CreateListBeans, e terá como conseqüência um forward para ?showBean.jsp?, que irá exibir os nossos dados.

Em nossa action CreateListBeans, temos o seguinte código:

Code:
 package actionClass;
 
 import beans.Person;
 import java.util.ArrayList;
 import org.mentawai.core.BaseAction;
 
 public class CreateListBeans extends BaseAction {
 
      public String execute() throws Exception {
         Person p1 = new Person("1", "John", "blue" );
         Person p2 = new Person("2", "Mary", "green");
         Person p3 = new Person("3", "Jane", "blue");
         
         ArrayList listPerson = new ArrayList(); 
         listPerson.add(p1);
         listPerson.add(p2);
         listPerson.add(p3);
         
         output.setValue("listPerson", listPerson );
         
         return SUCCESS;
         
     }
 }


Como se pode notar, o papel dessa Action é simplesmente criar 3 beans de Person, e setá-los dentro de um Arraylist.

O conteúdo de showBean.jsp, que irá exibir os dados dos beans, é o seguinte:

Code:
 <%@page contentType="text/html" pageEncoding="windows-1252"%>
 <%@ taglib uri="Mentawai" prefix="mtw" %>
 <!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=windows-1252">
         <title>JSP Page</title>
     </head>
     <body>
         <h2>The Beans are ready!</h2>
         
         <mtw:list value="listPerson">
             <mtw:loop var="Person">
                 <p><mtw:out value="Person.id" /> - <mtw:out value="Person.name" /> - <mtw:out value="Person.favoriteColor" /></p>
             </mtw:loop>
         </mtw:list>
 
     </body>
 </html>


Note-se que aqui já se usa de forma ampla a taglib do Mentawai. A definição de que se usará a lib do Mentawai para tratar de todas as taglibs prefixadas por ?mtw? é feita na segunda linha do arquivo showBean.jsp. Iremos tratar mais adiante desse detalhe, quando criarmos nossa própria tag condicional.

Seguindo-se o conteúdo acima, na exibição de nossa página, teremos uma página inicial, que após pressionada o botão ?Go Bean!" deverá exibir os seguintes dados:

(ver imagem1.jpg)

Até então, conseguimos criar uma action e popular os dados, exibindo-os na tela. Mas, digamos que você somente queira imprimir os dados do bens cuja cor favorita (definida pela propriedade favoriteColor) seja ?blue?. Podemos, nesse caso, criar nossa própria taglib condicional, informando como tratar essa condição.


Iniciando a construção da taglib condicional

O primeiro passo que precisamos entender é que toda definição de uma taglib é feita através de um arquivo com extensão TLD (Tag Lib Descriptor). Esse arquivo possui algumas seções básicas:

<taglib> A descrição da Tag Lib
<tlibversion> Contém a versão da Tag Lib
<shortname> Um mnemônico através do qual sua tag lib será referenciada. Também é usado para prefixar as diretivas das tags
<uri> Identifica a URI da tag lib

Para nosso exemplo, criaremos uma tag lib que será prefixada por ?nsc?. Esse mesmo arquivo poderá conter diversas diretivas. Contudo, nesse exemplo, iremos utilizar apenas uma diretiva: ?ifColorIsEqual?. Essa diretiva irá analisar a cor desejada, permitindo que mostremos apenas os beans desejados.

Ao criarmos um arquivo TLD, preferencialmente damos o nome do arquivo como ?nsc.tld?. Observe que o arquivo normalmente será salvo dentro da pasta ?WEB-INF?, em alguma pasta própria para armazenar arquivos TLD. ?nsc? será ainda o nome do mnemônico de nossa tag:

Code:
 <?xml version="1.0" encoding="UTF-8"?>
 
 <taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlnssi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
 
 <tlib-version>1.0</tlib-version>
 <short-name>nsc</short-name>
 <uri>/WEB-INF/tlds/nsc</uri>
 </taglib>


Temos assim os dados básicos de nosso arquivo ?nsc.tld?. Porém, agora, precisaremos escrever a nossa taglib condicional, que irá realizar as comparações que desejamos. Para criar sua própria taglib condicional, basta extender a org.mentawai.tag.util.ConditionalTag. Isso lhe garantirá uma série de vantagens, como a disponibilidade de uso dos recursos herdados dessa classe, como o uso dos membros protected: application (ServletContext), session (HttpSession), req (HttpServletRequest), res (HttpServletResponse), action (org.mentawai.core.Action) e loc (java.util.Locale).

Assim, temos nossa classe IfColorIsEqual:

Code:
 package tags;
 
 import beans.Person;
 import javax.servlet.jsp.JspException;
 import org.mentawai.tag.Out;
 import org.mentawai.tag.util.ConditionalTag;
 
 public class IfColorIsEqual extends ConditionalTag {
 
     private String beanName = null;
     private String value = null;
      
     public String getBeanName() {
         return beanName;
     }
 
     public void setBeanName(String beanName) {
         this.beanName = beanName;
     }
 
     public String getValue() {
         return value;
     }
 
     public void setValue(String value) {
         this.value = value;
     }
 
     public boolean testCondition() throws JspException {
 
         if (getBeanName() == null) {
             return false;
         }
 
         // algum valor que está no pageContext, output, session ou application nessa ordem...
         // O ultimo parametro do método abaixo (false) serve para indicar que não queremos procurar
         // por tipos booleanos através dos métodos isMyObject (assumindo que o valor de test seja "myObject")
         Person person = (Person) Out.getValue( getBeanName(), pageContext, false);
 
         if ( person.getFavoriteColor().equals(getValue()) ) {
             return true;
         }
         
         return false;
     }
 }


Observe que nesse caso, iremos passar dois parâmetros para nossa classe analisar: o beanName, que conterá o nome do Bean que desejamos analisar, e o value, que conterá o valor da cor que desejamos que seja comparado. Observe também que o método testCondition() deve obrigatoriamente ser implementado da interface ConditionalTag. Nesse método, iremos colocar a lógica da análise de nossa tag.

Nesse exemplo, verificamos se o nome do Bean é nulo. Caso seja, retornamos false e encerramos a análise. Caso o nome do Bean seja fornecido, é preciso procurar pelo valor do mesmo. Isso é feito através do método Out.getValue, que busca o dado desejado no PageContext, output, session ou application, nessa ordem, até encontrá-lo. Observe que fizemos um cast do retorno, tratando-o como um bean de nossa classe original. A seguir, basta tratar se o método getFavoriteColor do bean é igual à cor desejada, que informamos à classe. Caso sejam iguais, retornamos true e encerramos o processamento.

Contudo, devemos retornar ao arquivo ?nsc.tld? para implementar mais informações que serão necessárias à nossa taglib. Assim, esse arquivo ficará da seguinte forma:

Code:
 <?xml version="1.0" encoding="UTF-8"?>
 <taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlnssi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
     <tlib-version>1.0</tlib-version>
     <short-name>nsc</short-name>
     <uri>/WEB-INF/tlds/nsc</uri>
 
     <tag>
         <name>ifColorIsEqual</name>
         <tag-class>tags.IfColorIsEqual</tag-class>
         <body-content>JSP</body-content>
         <display-name/>
         <attribute>
               <name>negate</name>
               <required>false</required>
               <rtexprvalue>true</rtexprvalue>
               <type>boolean</type>
         </attribute>
         <attribute>
               <name>beanName</name>
               <required>true</required>
               <rtexprvalue>true</rtexprvalue>
               <type>beans.Person</type>
         </attribute>
         <attribute>
               <name>value</name>
               <required>true</required>
               <rtexprvalue>true</rtexprvalue>
               <type>java.lang.String</type>
         </attribute>
     </tag>
 </taglib>


Além das definições já vistas anteriormente, agora podemos definir os dados específicos de nossa tag, como o nome da mesma - definido pela área <name></name>, qual será a classe que deverá ser executada ao acessar essa tag ? definido pela área <tag-class></tag-class>. No item <body-content> permite-se definir os seguintes valores:

Code:
 JSP - o corpo é avaliado pelo container, e então pode ser processado pela tag
 tagdependent - o corpo somente é processado pela tag. Nenhum JSP no corpo será avaliado.
 empty - não há corpo na tag.
 


A seguir, podemos definir os atributos que deveremos fornecer para nossa tag, para que ela realize seu trabalho. No caso, podemos definir, para cada atributo, seu nome - através da área <name></name>, se ele é requerido ou não ? através da área <required></required>, seu tipo ? através da marcação <type></type>, e também se a expressão deverá estar disponível em tempo de execução, pela área <rtexprvalue></rtexprvalue>.

Com todas as definições realizadas, podemos modificar nosso JSP showBean.jsp, para que este possa exibir utilizar nossa taglib.

Para fazermos isso, devemos inserir a seguinte linha em nosso JSP:

Code:
 <%@ taglib uri="/WEB-INF/tlds/nsc.tld" prefix="nsc"%>


Com isso, indicamos que todas as tags prefixadas com ?nsc? devem ser procuradas no arquivo /WEB-INF/tlds/nsc.tld.

A partir desse ponto, podemos modificar nosso arquivo JSP e inserir nossas próprias tags condicionais. Digamos que queiramos que sejam apenas exibidos os dados dos beans de Person que possuem a cor favorita igual a ?blue?. A estrutura de nosso JSP será:

Code:
 <%@page contentType="text/html" pageEncoding="windows-1252"%>
 <%@ taglib uri="Mentawai" prefix="mtw" %>
 <%@ taglib uri="/WEB-INF/tlds/nsc.tld" prefix="nsc"%>
 <!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=windows-1252">
         <title>JSP Page</title>
     </head>
     <body>
         <h2>The Beans are ready!</h2>
         
         <mtw:list value="listPerson">
             <mtw:loop var="Person">
                 <nsc:ifColorIsEqual beanName="Person" value="blue">
                     <p><mtw:out value="Person.id" /> - <mtw:out value="Person.name" /> - <mtw:out value="Person.favoriteColor" /></p>
                 </nsc:ifColorIsEqual>
             </mtw:loop>
         </mtw:list>
 
     </body>
 </html>


E o resultado de nossa exibição será:

(ver imagem2.jpg)

Observe, para finalizar, que existe um outro atributo em nossa tag, que é herdada automaticamente de ConditionalTag ? o atributo negate. Ele permite realizar pesquisa de forma a negar o conteúdo de uma pesquisa. Nesse caso, podemos utilizar:

Code:
 <%@page contentType="text/html" pageEncoding="windows-1252"%>
 <%@ taglib uri="Mentawai" prefix="mtw" %>
 <%@ taglib uri="/WEB-INF/tlds/nsc.tld" prefix="nsc"%>
 <!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=windows-1252">
         <title>JSP Page</title>
     </head>
     <body>
         <h2>The Beans are ready!</h2>
         
         <mtw:list value="listPerson">
             <mtw:loop var="Person">
                 <nsc:ifColorIsEqual beanName="Person" value="blue" negate="true">
                     <p><mtw:out value="Person.id" /> - <mtw:out value="Person.name" /> - <mtw:out value="Person.favoriteColor" /></p>
                 </nsc:ifColorIsEqual>
             </mtw:loop>
         </mtw:list>
 
     </body>
 </html>


Que teremos como resultado uma lista dos beans que estiverem sendo negados o valor = ?blue?. O resultado será:

(ver imagem3.jpg)

Bom, espero que esse pequeno tutorial auxilie-o na criação de suas próprias tags condicionais usando o Mentawai. Qualquer dúvida, poste no fórum ou mande um e-mail para rafael@nscinfo.com.br.

Até mais!
 Filename imagem1.JPG [Disk] Download
 Description
 Filesize 20 Kbytes
 Downloaded:  792 time(s)

 Filename imagem2.JPG [Disk] Download
 Description
 Filesize 19 Kbytes
 Downloaded:  818 time(s)

 Filename imagem3.JPG [Disk] Download
 Description
 Filesize 18 Kbytes
 Downloaded:  826 time(s)

[WWW] [MSN]
 
Forum Index -> F.A.Q.
Go to:   
Powered by JForum 2.1.6 © JForum Team