Opiniões: JSTL x Tags do Framework

Desculpem a pentelhação :wink: , mas quem quiser e puder dar uma olhada nos tags de display do Mentawai e colocar aqui um feedback sobre o assunto, seria ótimo.

O framework precisa da opinião da comunidade para ficar legal!

Acabou de sair do forno: http://mentawai.lohis.com.br/displaytags.jsp

Obrigado,

Eu achei “out”, “bean” e “loop” meio sem motivo, especialmente por causa de JSTL e EL.

Pra que elas existem?

mtw:out é para cuspir as coisas, em qualquer contexto.

mtw:bean pega um bean que está no output e coloca no contexto. Daí para cuspir seus atributos vc só precisa usar o mtw:out value=“username” por exemplo.

com JSTL ficaria assim:

c:out value="${action.output.user.username}"

A idéia é colocar o bean num contexto pois daí vc pode criar uma infinidade de tags para acessar esse contexto, como é o caso do user:avatarImg, no final do tutorial.

Já o loop é necessário para loopar um contexto de lista. A dúvida que surge é porque não fazer o próprio mtw:list loopar ? A resposta é porque vc quer usar tags como isEmpty entre a declaração do contexto e o loop.

Faz sentido? :slight_smile:

Dá para usar JSTL com EL pra tudo, mas usando as tags do framework fica mais limpo e direto.

Achei o mesmo. Uma coisa, vendo as tags me lembrei um pouco do tempo que eu trabalhava com ColdFusion

<cfif x="a"> foo <cfelseif x="b"> xazam <cfelse> yada yada </cfif>

Quer dizer que ainda existem 2 contextos antes de se chegar a alguma coisa que o usuário tenha colocado por lá? Action e output?

Acho que isso tá meio complicado demais…

O melhor mesmo era que ele simplesmente fizesse ${usuario.nome} e desse um print no usuário.

Eu acho que taglibs só devem ser criadas quando for uma coisa absolutamente necessária, se já tem uma ótima forma de se fazer isso, pra que reinventar a roda? Pra que fazer o cara ter que entender ainda mais coisas do que EL e JSTL? Isso é realmente necessário? Vai facilitar ou atrapalhar o serviço dele?

E porque não usar o “forEach” pra fazer os loops? É exatamente pra isso que ele serve.

[quote=Maurício Linhares]Quer dizer que ainda existem 2 contextos antes de se chegar a alguma coisa que o usuário tenha colocado por lá? Action e output?

Acho que isso tá meio complicado demais…
[/quote]

Não digo que fica complicado, porque é obvio que vc tem action.input, action.output e action.session, mas realmente fica mais verbose.

A solução seria criar um filtro (ou fazer isso para todas as action mesmo, independente de filtro) para pegar os elementos do output e jogar no request. Daí o cara acessa: c:out value=“user.username” ao invés de c:out value=“action.output.user.username”

As tags de JSTL são genéricas, isto é são pau pra toda obra, logo elas não são tão clean assim. Já as tags do framework, por serem integradas com o framework são mais consisas.

Por exemplo:

Como eu faço isso com JSTL, assumindo que eu tenho uma lista de usuários chamada users no request. (Primeiro problema sério: a interface List não tem getSize, só size que o EL não pega!)

[color=red]Alguem bom de JSTL poderia passar o código abaixo para JSTL para fazermos uma comparação de simplicidade e objetividade?[/color]

<mtw:list value="users">
<mtw:isEmpty>
Vc não tem nenhum amigo!
</mtw:isEmpty>
<mtw:isEmpty negate="true">
<table><tr><td>Nome</td><td>Email</td></tr>
</mtw:isEmpty>
<mtw:loop>
<tr>
<td><mtw:out value="username" /></td>
<td><mtw:out value="email" /></td>
</tr>
</mtw:loop>
<mtw:isEmpty negate="true">
</table>
</mtw:isEmpty>
</mtw:list>

Acho que menos verbose que isso impossível. Com JSTL deve ficar bem mais verbose. E espere até vc ver os tags de paginação. :slight_smile:

O que eu estou defendendo é que embora vc consiga tudo com JSTL, eles são bastante verboses por serem genéricos. Acredito que com os tags do framework as coisas ficam mais limpas e claras.

Eu acho que complica Sérgio, se eu estudei um livrão de 800 páginas que me dizem que a sessão fica no map implícito do jsp chamado ${session}, quando eu usar o seu framework eu quero que ele esteja lá também, porque eu aprendi que a coisa funciona assim, já é natural buscar as coisas seguindo a especificação.

Eu voto no filtro pra cuidar disso.

Eu achei o “isEmpty” interessante, mas ainda assim não acho que isso é o tipo de processamento que deva ser feito na própria página, isso é coisa pra se fazer no action.

E não dá pra passar esse código pra JSTL não, exatamente por causa do “isEmpty”.

[quote=Maurício Linhares]Eu acho que complica Sérgio, se eu estudei um livrão de 800 páginas que me dizem que a sessão fica no map implícito do jsp chamado ${session}, quando eu usar o seu framework eu quero que ele esteja lá também, porque eu aprendi que a coisa funciona assim, já é natural buscar as coisas seguindo a especificação.
[/quote]

Concordo! Deixa eu apenas tentar defender o meu ponto mais uma vez, pois acho que vc está sendo um pouco resistente. (Sem bronca porque tu ajuda demais Mauricio! Só tenho que te agradecer pelo seu feedback sempre com questões interessante!) :wink:

Aprender e se acostumar com um sistema de tags ridículo como esse é tranquilo. Não é nada que vai te tomar mais do que 15 minutos. São tags intuitivas, mais até que o JSTL. JSTL te obriga a declarar a todo momento a qual contexto vc se refere, já com as tags do framework esse contexto fica implícito, me entende.

Como vc faria isso na action ??? Meteria uma boolean no output só para dizer se está empty ou não ??? Hummm… Isso é realmente legal ? Pode ser, não tenho certeza… Toda action que meter uma lista no output, vai ter que meter esse boolean tb para dizer se está empty ou não ??? Meio esquisito na minha cabeça…

Então temos um problema. Se vc não está conseguindo imagina o Zé Mané que tá começando agora?

Se não for te dar muito trabalho, solucione a questão do isEmpty como vc desejar e passe esse código para JSTL, assim poderemos fazer uma comparação boa.

Imagine paginação, que é algo importante pra caramba. Eu tenho uns tags aqui que fazem isso de uma maneira limpa e transparente, pois toda a lógica está dentro do tag e se comunica com o framework.

Agora como é que vc faz paginação com JSTL ??? Fica uma zona incrível !!! Só se vc fizer isso na action, mas aí tu já começa a poluir a action, me entende. Esse tag de paginação é uma mão na roda!

[quote=saoj]

<mtw:list value="users">
<mtw:isEmpty>
Vc não tem nenhum amigo!
</mtw:isEmpty>
<mtw:isEmpty negate="true">
<table><tr><td>Nome</td><td>Email</td></tr>
</mtw:isEmpty>
<mtw:loop>
<tr>
<td><mtw:out value="username" /></td>
<td><mtw:out value="email" /></td>
</tr>
</mtw:loop>
<mtw:isEmpty negate="true">
</table>
</mtw:isEmpty>
</mtw:list>

Acho que menos verbose que isso impossível. Com JSTL deve ficar bem mais verbose. E espere até vc ver os tags de paginação. :slight_smile: [/quote]

Bom, vejamos como isso ficaria se vc estivesse usando Ruby On Rails, e dai vamos ver quem ganha no quesito expressividade, ok? :wink:

<% if @users.empty? %> Voce nao tem nenhum amigo! <% else %> <table><tr><td>Nome</td><td>Email</td></tr> <% @users.each |u| do %> <tr> <td>${u.username}</td> <td>${u.email}</td> </tr> <% end %> <% end %>

Opinioes?

Eu ia até responder… mas fiquei envergonhado :shock:

A proposito, vc nao precisa de isEmpty se o seu loop tiver um “else”. Em Python funciona assim, e o codigo fica com cheirinho de chiclé:

foo = [1,2,3] for f in foo: print "foo has " + f else: print "meh!"

Ruby on Rails:

<% if @users.empty? %>
 Voce nao tem nenhum amigo!
 <% else %>
 <table><tr><td>Nome</td><td>Email</td></tr>
 <% @users.each |u| do %>
 <tr>
 <td>${u.username}</td>
 <td>${u.email}</td>
 </tr>
 <% end %>
</table>
 <% end %>

Mentawai tags: (melhorado pois minha lógica estava tosca)

<mtw:list value="users">
 <mtw:isEmpty>
 Vc não tem nenhum amigo!
 </mtw:isEmpty>
 <mtw:isEmpty negate="true">
 <table><tr><td>Nome</td><td>Email</td></tr>
 <mtw:loop>
 <tr>
 <td><mtw:out value="username" /></td>
 <td><mtw:out value="email" /></td>
 </tr>
 </mtw:loop>
  </table>
 </mtw:isEmpty>
 </mtw:list>

Ruby é melhor!!!

Mas a questão aqui é comparar com JSTL. Voltando ao mundo Java… :wink:

Nops, a EL procura em todos os contextos, em sequencia:

page -> request -> session -> aplication

Se não encontrar em nenhum não imprime nada.

Na verdade eu meto um “null” e boto um <x:choose/> na página, se for null faz “blablabla” se não for roda o loop. Fica do mesmo jeito do seu, só que com mais palavrinhas (mas não dá nem pra comparar nenhum dos dois com RoR).

Só com JSTL é impossível, não dá pra chamar métodos usando EL, só propriedades. Tem que fazer alguma coisa no action, como eu faço, ou então criar uma tag como as suas pra fazer isso.

Isso é extremamente relativo, porque paginação é uma coisa que tem muitas variáveis, acho que um bom exemplo disso é o DisplayTags, que tem um monte de opções pra serem colocadas, como ordenação e tudo mais. Acho que nesse caso não tem uma solução “simples” não, cada caso termina sendo um caso diferente, só dá pra “generalizar” se você vai usar um “componente” (como o DisplayTag) ou então JSF.

Nops, a EL procura em todos os contextos, em sequencia:

page -> request -> session -> aplication

Se não encontrar em nenhum não imprime nada.

[/quote]

O contexto que eu estava me referindo é o nome da variável e não o escopo. (Me expressei mal!) No mentawai quando vc faz um <mtw:out value=“username”/> o user, que é o nome da variável em questão está impícito.

Concluindo: quer usar JSTL, use JSTL, pois o framework te dá essa opção. Quer brincar com as tags do framework então brinque. :slight_smile:

Po, vou pegar um exemplo das tags de paginação e colocar aqui para vc ver. Acho que com elas dá até pra fazer uma frente melhor com o RoR. :lol: :lol: :lol:

Como isso é feito em JSTL/EL:

&lt;c:choose&gt;

     &lt;c:when test="${users == null}"&gt;
          Você ainda não tem nenhum amigo.
     &lt;/c:when&gt;

     &lt;c:otherwise&gt;

               &lt;table&gt;
                    &lt;tr&gt;
                         &lt;td&gt;Nome&lt;/td&gt;
                         &lt;td&gt;Email&lt;/td&gt;
                   &lt;/tr&gt;

          &lt;c:forEach items="${users}" var="user"&gt;
                   &lt;tr&gt;
                         &lt;td&gt;&lt;c:out value="${user.nome}" /&gt;&lt;/td&gt;
                         &lt;td&gt;&lt;c:out value="${user.email}" /&gt;&lt;/td&gt;
                   &lt;/tr&gt;
          &lt;/c:forEach&gt;

                &lt;/table&gt;

     &lt;/c:otherwise&gt;

&lt;/c:choose&gt;

Ah, outra coisa Sérgio, como é que eu faço pra acessar propriedades aninhadas dos objetos?

Imagine que o usuário tem uma propriedade nome que tem mais duas propriedades, primeiroNome e segundoNome, como eu acesso isso?

Eu ainda prefiro assim…

    #if ($users.isEmpty())
      Você ainda não tem nenhum amigo.
    #else
      &lt;table&gt;
        &lt;tr&gt;
          &lt;td&gt;Nome&lt;/td&gt;
          &lt;td&gt;Email&lt;/td&gt;
        &lt;/tr&gt;
        #foreach ($user in $users)
        &lt;tr&gt;
          &lt;td&gt;$user.nome&lt;/td&gt;
          &lt;td&gt;$user.email&lt;/td&gt;
        &lt;/tr&gt;
	#end
      &lt;/table&gt;
    #end

Pessoal,

A grande vantagem da EL está em suprimir o tamanho da sintaxe?

Sem +!

[quote=Maurício Linhares]Ah, outra coisa Sérgio, como é que eu faço pra acessar propriedades aninhadas dos objetos?

Imagine que o usuário tem uma propriedade nome que tem mais duas propriedades, primeiroNome e segundoNome, como eu acesso isso?[/quote]

&lt;mtw:bean value="user"&gt;
    &lt;mtw:bean value="nome"&gt;
        &lt;mtw:out value="firstName"/&gt;
        &lt;mtw:out value="lastName"/&gt;
    &lt;/mtw:bean&gt;
&lt;/mtw:bean&gt;

Nesse caso JSTL é melhor mesmo !!! :?

O Struts tinha (ainda tem, mas ninguém mais usa) uma expression language que era só clocar “.” (pontos) pra acessar as propriedades, porque você não faz assim também Sérgio?

[quote=betonit]Pessoal,

A grande vantagem da EL está em suprimir o tamanho da sintaxe?

Sem +! [/quote]

Nops, a grande vantagem da EL é poder ser colocada diretamente dentro do HTML e não deixar você chamar métodos (e isso as vezes é uma desvantagem, quando lidamos com classes antigas ou que não seguem a especificação JavaBean), apenas acessar propriedades JavaBeans.