Introdução ao Velocity

Assunto: Através deste longo tutorial, apresentaremos as vantagens e facilidades de utilizar uma ferramenta de templates. Desta maneira, você irá separar a lógica do seu programa da apresentação dos resultados.

Você pode ler este tutorial na íntegra http://www.guj.com.br/java.artigo.18.1.guj

Por favor, coloque as suas dúvidas e seus comentários sobre este tutorial aqui.
Sinta-se livre para fazer qualquer tipo de pergunta, desta maneira você estará nos ajudando e aos outros usuários!

Acho que deu para entender legal como o velocity funciona. O código está bem simples e fácil de entender.

è bom ficar claro, que apesar do VTL ser uma linguagem de template, que processa essa linguagem é o próprio java!

Tem gente que me pergunta “Se eu usar o velocity, vou estar usando outra linguagem, precisa compilar ou algo assim?”. A linguagem do velocity eh interpretada, e o interpretador eh em java! O interpretador faz parte do pacote do velocity. Voce nem chega a mexer com ele diretamente!

Outra coisa que me perguntaram era se o velocity trabalhava junto com HTML.

Bom, menciono isso no tutorial, mas acho que nao deve ter ficado muito claro. De qualquer maneira, SIM, Velocity pode ser usado no meio de HTML, tanto que esse eh um dos maiores usos da ferramenta. Com Velocity vc NAO PRECISA DE JSP, ele substitui jsp.

Rafael

To com uma duvida…

Eu tenho uma variavel $vetor, que eh uma referencia pra um array do Java. Eu posso usar o foreach pra iterar pelo vetor, certo? Mas tem como eu pegar um elemento em uma posicao especifica do vetor? Algo como $vetor[1]???

hum

acho que de array nao, mas se fosse um ArrayList, voce poderia dar um $vetor.get(1)

lembre-se, que usando isso, voce ta meio que quebrando o MVC. mas nao tem como evitar muito. soh fica esperto para nao deixar muito o business logic no seu view, que ai eh fogo!

:smiley: Opz… Paulo… surgiu aquela duvida quando vc mensionou sobre uma eventual quebra do pattern MVC.
Olha jah utilizei vector retornando de uma camada d negocio junto a jsps, e realmente nao eh legal.
Com Velocity como poderia funcionar substituindo o jsp?
Como um exemplo p/ ti quando usei um vector com jsp’s, foi da seguinte maneira.

<select name=“Nacionalidade” onchange=“setarNacionalidade()”>
<%!Vector vNac = new Vector();%>
<%oNac.setAcationNac(“findNacionalidade”);%>
<%oNac.execActionNac();%>
<%vNac = oNac.getID_Pais();%>
<%int size = vNac.size();%>
<%int divize = size / 2;%>
<%String[] ID_Nacionalidade = new String[divize];%>
<%String Pais[] = new String[divize];%>
<option value=“none”>Escolha um Pais
<%for(int i=0; i < size; i++) { /* ini2 /%>
<option value="<%=ID_Nacionalidade[0] = (String) vNac.get(i)%>">
<%i++;%><%=Pais[0] = (String) vNac.get(i)%>
<%} /
fim2 */%>
<%} %>

Teria alguma dica a exemplificar o meu caso!? Sou iniciante em velocity e gostaria de ter uma dica d como um template poderia ser usado neste caso, para nao usar jsp’s (se for o necessario) e assim deixar a camada View mais clara e eficiente para uma possivel manutencao.

Agradeço pela atencao!

PJ2002.

Bom, antes de mostrar como fazer com Velocity, o seu codigo JSP ficaria muito mais legivel se fosse feito assim:

<%
Vector vNac = new Vector();

oNac.setAcationNac("findNacionalidade");
oNac.execActionNac();

vNac = oNac.getID_Pais();

int size = vNac.size();
int divize = size / 2;

String[] ID_Nacionalidade = new String[divize];
String Pais[] = new String[divize];
%>

<select name="Nacionalidade" onchange="setarNacionalidade()">
<option value="none">Escolha um Pais</option>
<%
for(int i = 0; i < size; i++) { 
	ID_Nacionalidade[0] = (String)vNac.get(i);
	i++;
	Pais[0] = (String)vNac.get(i);
	%>
	<option value="<%= ID_Nacionalidade[0]%>"><%= Pais[0]%></option>
	<%
}
%>

ps: achei meio estranho vc criar um array de size / 2 tamanho mas sempre atribuir os dados a posicao 0 no array…

Bom, indo pro assunto principal, para fazer isso com Velocity vc tera que mudar o codigo Java para um arquivo .java, o qual ira executar as acoes de encontrar a nacionalidade etc etc… entao, ao inves de fazer um loop como vc fez, vc primeiro coloca em um ArrayList e entao configura esse ArrayList em um contexto visivel ao Velocity, e depois eh so usar as tags da VTL ( Velocity Template Language - tem um tutorial aqui no guj sobre isso ) para mostrar os dados.
Como nao entendi mto bem o teu exemplo, vou mostrar com um outro codigo bem simples de entender: pegamos do banco de dados a relacao de nomes dos empregados de uma empresa, e entao fazer um template para mostrar esses nomes em um <select>.
Se fossemos fazer em JSP ficaria mais ou menos assim:

<%
...
// executar aqui o codigo sql para pegar os empregados
// fazer o loop e ir mostrando na tela os nomes
%>
<select name='empregados'>");
<%

String nome = "";
while (rs.next()) {	
	nome = rs.getString("nome_empregado");
	%><option value="<%= nome>"><%= nome%></option><%
}
%>
</select>
<%
// resto do codigo etc etcc
%>

Para fazer isso com Velocity, movemos o codigo java para um arquivo .java, o qual ira se encarregar se processar tudo e colocar em um ambiente visivel ao velocity. Se fosse um ambiente real de producao e se quisessemos seguir corretamente as regras de Design Patterns, o exemplo aqui teria que ser mais separado as camadas ainda, mas para fins didaticos nao eh necessario tamanha abstracao :).
Basicamente o que precisamos fazer eh isso:

// AlgumArquivo.java
....
// executar aqui o codigo sql para pegar os empregados

// Pega os dados e coloca em um ArrayList
ArrayList listEmpregados = new ArrayList();
while (rs.next())
	listEmpregados.add(rs.getString("nome_empregado"));
	
...
// Cria o contexto do Velocity para colocarmos os dados
VelocityContext context = new VelocityContext();
context.put("empregados", listEmpregados);	

// Faz outras acoes necessarias para o Velocity
// codigo codigo codigo

ps: o codigo acima ( o que cria o contexto do velocity ) na maior parte das
vezes vai ser um Servlet.

Bom, com isso ja tiramos o codigo Java da camada de apresentacao, agora precisamos montar o template para mostrar os dados na tela:

## mostraEmpregados.html
## Apesar da extensao .html, este eh um 
## arquivo com diretivas VTL

## Monta o <select> dos empregados
<select name="empregados">

#foreach ($nome in $empregados)
	<option>$nome</option>
#end

</select>

e pronto!!! Viu como a parte de montar o layout ficou super simples e sem uma unica linha de java dentro?! :smiley:

Bom, basicamente eh isso. Apesar de dar mais trabalho na hora de programar, ja que eh preciso pensar melhor como o codigo vai ser feito, precisa fazer os .java e o Servlet, a medio/longo prazo compensa mto, pois a manutencao do sistema fica muito mais facil e simples.
Sei que o exepmlo fico meio grande e nao mostrou codigos concretos, mas eh que ficaria inviavel postar tudo no topico. Como voce ja deve ter visto, ja entrou um tutorial sobre a VTL, e na semana que vem ja estara entrando mais um tutorial de Velocity, o qual ira mostrar - e explicar - exemplos de aplicacoes usando Servlets e XML com Velocity. Portanto, caso nao tenha entendido tudo, ja esta vindo um tutorial ai :slight_smile:

Rafael

Rafael,

no meu caso coloquei um a seguinte instrução no meu action:

resultContext.put(“pm_cList”, pm_cList.toArray());

e no meu html estou colocando:

teste: $pm_rfpList.length

porém a mesma expressão é impressa, ao invés de

teste: 1

como se o objeto em questão não existisse, a prova que o objeto está ok está mais abaixo no código:

#foreach ($pm_rfp in $pm_rfpList)

esta expressão está funcionando corretamente.

vc saberia me dizer onde está o problema?

grata

Débora

Debora

os nomes das suas variaveis nao estao batendo!

voce colocou no context uma tal de “pm_cList”, mas dentro do tempalte voce tenta acessar “$pm_rfpList”, que simplesmente nao existe no contexto, por isso ele nao interpreta

Boas!

Gostei do tutorial, realmente o velocity parece facilitar as coisas em relação à apresentação dos dados, só queria alertar q o tutoral tem um pequeno erro, repare no seguinte código:

[code]Listagem dos itens de um ArrayList

Existem $lista.size() itens na lista.


#foreach ($item in $list)
$item
#end
-------------------[/code]

Em cima foi usado a variavel $lista para representar o array mas depois no ciclo foi usada a $list, ou seja os elementos não vão ser listados pq n existe nenhum array chamado $list mas sim um chamado $lista, é um pequeno erro fácil de detectar mas de qq maneira pode levar mta gente ao engano.

Fiquem bem

fala galera…

seguinte…gostei mto da utilidade do velocity…

mas tenho a seguinte situacao aqui…
preciso gerar relatorios via web no meu sistema…nao quero usar .pdf pq toda vez q gerar, vai ter q abrir o acrobat, etc…

entao o nosso amigo dukejeffrie me disse p/ usar o Velocity p/ exibir os relatorios como HTML…

alguem pode me ajudar a resolver esse problema??
estou gerando meus relatorios usando o JasperReports ( ele gera um .xml e monta o relatorio a partir dele)…

valew galera.

Editado
Eita o tutorial é do Rafael. Mals ai. Qualquer um que puder respondel ta blz.
Editado
Paulo, acabei de ler o tutorial de velocity. Tem como processar o velocity junto com xml?

Digo, no exemplo, foi escrito uma classe que “configurava” o contexto sobre o qual o velocity ia ser processado. Significa que tenho que ter uma classe para cada “.vm” certo?

Imagine agora que você escreve uma única classe que funcione como um template output builder e você configuraria o contexto através de .xml.

No caso, você não teria a classe da listagem VelocityListProcess e sim um xml ± assim.

<template-context>
  <reference name="lista">
    <value>Lista 1</value>
    <value>Lista 2</value>
    <value>Lista 3</value>
    <value>Lista 4</value>
    <value>Lista 5</value>
  </reference>

  <reference name="cargo">
    <value>Engenheiro de Software</code>
  </reference>
</template-context>

No caso, teriamos duas referências: “lista” que, por possuir varias filhas “value”, o builder entende que é uma coleção e “cargo”, com um único valor e uma variável “normal”.

Dessa forma, você não precisa recompilar classes java.

Não sei nada de velocity ainda, acabei de ler o primeiro tutorial. Ele já tem algo parecido? Se não tem, vale a pena implementar algo do tipo (pergunto isso pela experiência que vocês devem possuir, talvez o ganho seja mínimo)?

Como só vi chamadas as referências, pode ser que a idéia conflita com algo que haja mais na frente.

[]'s

Nao, nao precisa. Voce pode ter uma unica classe para a qual voce passa qual template processsar, por exemplo. Ou seja, voce implementa da maneira que achar melhor.

No mais, o que voce perguntou sobre o XML nao da para fazer, nativamente com o Velocity. Seria necessario fazer a implementacao da classe que processa o XML para entao trabalhar com o Velocity.

Rafael

A idéia é essa mesmo, desenvolver uma classe.
Mas dessa forma, eu teria que ter conhecimento prévio dos valores da variável que precisariamos passar, para colocar no XML.
Com certeza isso é o que menos acontece, os parâmetros vem dinâmicos…
Acho que não rola não.

Paulo ou Rafael, preciso de um help no velocity. Não sei se vocês deram uma olhada no macros.vm da aplicação velocity + struts.

O que tentei fazer foi uma mini biblioteca de macros, para “parsear” dentro de meus outros templates. Cada template meu teria então:

#parse(“macros.txt”)

Pois todos utilizariam as macros contidas nesse template. Dessa forma, não preciso colar o texto de todas as macros em cada template que eu possua. Se vocês viram, não consegui fazer isso.

Quando usei #include, o conteudo foi incluido e gerado como output, mas ao usar #parse, não consegui usar as macros de dentro do template, ele não reconheceu as macros. To fazendo algo errado?

E mais, como faço para quando o usuario acessar algo do tipo http://localhost/projeto ele não liste o conteúdo do diretório, mas redirecione para o meu VelocityServlet e ele reconheça que deve chamar o index.vm? (não quero usar o welcomefile).

Mais uma coisa, posso definir vários paths para
file.resource.loader.path?

Voce precisa especificar quais arquivos de macros vc vai estar usando. Para isso, use a diretiva “velocimacro.library”, passando o nome ( ou nomes ) do arquivo com as macros.
Para desenvolvimento, eh interessante setar “velocimacro.library.autoreload” para “true”, assim qdo vc alterar o arquivo com as macros, nao sera necessario restartar o tomcat.

Outro detalhe: se vc colocar uma macro dentro de um template ( e nao no arquivo de templates ), toda vez que vc alterar essa macro local vc precisara restartar o tomcat, pois mesmo com o cache setado pra false, o Velocity parece ignorar as tuas alteracoes na macro local… puta saco isso.

Nao conheco outra forma de redirecionar que nao seja usando o welcome-file.

Rafael

[quote=“Rafael Steil”]Outra coisa que me perguntaram era se o velocity trabalhava junto com HTML.

Bom, menciono isso no tutorial, mas acho que nao deve ter ficado muito claro. De qualquer maneira, SIM, Velocity pode ser usado no meio de HTML, tanto que esse eh um dos maiores usos da ferramenta. Com Velocity vc NAO PRECISA DE JSP, ele substitui jsp.

Rafael[/quote]

já entendi que vc pode utilizar o velocity para gerar qualquer tipo de código como HTML,JSP,XML… mas como assim não preciso usar JSP?

como gerar o código eu entendi… mas como fazer isso dinamicamente?

por exemplo, eu já tratei minha requisição com um Servlet e agora vou enviar a resposta a uma página com JSP… mas se o JSP foi substituido pelo Velocity… como eu faça então?

não seu se consegui deixar claro minha dúvida! :?

Ricardo

JSP voce usa para gerar o HTML, certo? Entao, com Velocity, ao inves de voce colocar as tags do JSP, voce coloca as do Velocity e usa uns metodos dele para fazer o processamento e jogar o resultado para o browser.

Rafael

O velocity pode o substituir JSP?

fica mais rápido?

Sim, pode perfeitamente.

Velocidade depende de como eh a qualidade do teu codigo. ( mas fica muito rapido sim ).

Rafael