Introdução ao Velocity

38 respostas
A

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!

38 Respostas

P

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!

R

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

F

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]???

P

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!

P

: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 <em>/%>

<option value="<%=ID_Nacionalidade[0] = (String) vNac.get(i)%>">

<%i++;%><%=Pais[0] = (String) vNac.get(i)%>

<%} /</em> 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.

R

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

D

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

P

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

B

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:
Listagem dos itens de um ArrayList

Existem $lista.size() itens na lista.

-------------------
#foreach ($item in $list)
    $item
#end
-------------------

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

R

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.

E

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

R

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

E

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.

E

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?

R

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

R

“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

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

R

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

R

O velocity pode o substituir JSP?

fica mais rápido?

R

Sim, pode perfeitamente.

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

Rafael

P

“Elvis.The.Pelvis”:
#parse(“macros.txt”)

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?

Deveria funcionar. Se voce vai usar como global essas macros, tem uma propriedade pra isso no velocity.properties. algo como global.vm.

Bem. Entao voce vai ter de mapear por servlet mapping.

“Elvis.The.Pelvis”:

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

Sim, separa por virgula porque o velocity usa o extendProperties do jakarta-commons-colletcions. Voce pode setar essas variaveis em runtime tambem, eu acho mais interessante.

M

Bom dia a todos,

Gostaria de receber uma pequena dica. Acabo de instalar o velocity e tudo funcionou muito bem.

Gostaria de saber com posso configurar meu ambiente para não precissar usar o classpath, eu setei os .jars no classpath e isso me forçou a colocar o caminho de onde estão minhas classes também para que o classloader(java) as encontra-se. Gostaria de não precissar usar o classpath.

Obrigado
Marcos

R

Essas libs do Java que voce falou eh a rt.jar, por acaso?. Parece que voce esqueceu de incluir alguma coisa no classpath. Geralmente, fazendo

*nix ( bash )

export CLASSPATH=$CLASSPATH:/dir/meuJar1.jar:/dir/meuOutroJar.jar

Win

set CLASSPATH=%CLASSPATH%;c:\dir\meuJar1.jar

resolve o problema.

M

Rafael,

Primeiro obrigado.

A questão é a sequinte, quando eu instalo o velocity tenho que referenciar os .jars que contém as classes necessárias ao velocity. No artigo que tem no GUJ dis para eu setar no classpath o velocity-dep-x.x.x.jar e o velocity-x.x.x.jar no classpath onde x.x.x é a versão do velocity.

Ao faze-lo o meu ambiente passa a não enxergar orde está as minhas classes. por exemplo: c: esteVelocity este.java
c: esteVelocity este.vm
c: esteVelocity este.class
Ele compila legal mas não executa a classe, a menos que eu sete no mesmo classpath o diretório c: esteVelocity.

Ou seja tudo funcionou muito bem. Mas quero chegar a uma solução, caso tenha como, onde eu não tenha que setas no classpath os arquivos .jars para que assim eu não tenha que setas os diretórios onde eu tenho classes para executar.

E que eu nunca uso o classpath. Gostaria de saber como não usá-lo agora também. E aproveitando, gostaria de saber se não usar o classpath é uma boa ou não e porque.

Obrigado
Marcos

R

Quando as bibliotecas estao em .jar’s eh necessario referenciar cada uma mesmo, nao tem jeito. O problema que voce esta tendo eh porque faltou o diretorio corrente, representado pelo caracter de ponto, no classpath… por isso que ele nao achava a classe no diretorio que voce estava.

set CLASSPATH=.;XXXXX

note o “.;” ( ponto-e-virgula )… isso diz ao java para procurar as classes tambem no diretorio que voce se encontra.

Rafael

M

Rafael,

Muito obrigado.

Resolveu. Não sabia do “.;”. Se tivese que setar cada diretório onde tenho classes no classpath seria terrível.

Novamente Obrigado,
Marcos

G

Webwork2 e velocity!
Estou com essa dúvida de como fazer isso:

Seguinte:
preciso colocar valores dentro de um combobox usando tags do velocity no webwork2... uma combobox normal que seri no html

<select>
<option></option>
</select>

o que não ta dando certo seria colocar os valores no option...

to fazendo o seguinte :

eu crio meu array:
#set ($prior = ["Normal", "Alta", "Baixa"])

dai quando tento chamar os valores do array:

#bodytag (Form "name='name'" "action='InavisAction.action'" "method='post'")

#tag(Select "label='Prioridade'" "name='inavis.avisTpPrioridade'" "value=$prior")

#end
ele não consegue pegar o valor da variavel $prior dentro do value aí, o curioso é que se colocar fora ele traz os valores..

conclusão : não consigo miontar uma combobox com valores queeu quero definir... alguem pode dar um help!


E

Quer saber qual propriedade diz onde o Velocity grava os logs? Aqui está:

runtime.log = path/arquivo.log

penei muito para encontrar, aproveite a dica! :stuck_out_tongue:

R

“Rafael Steil”:
Sim, pode perfeitamente.

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

Rafael

Bom, isso você está certo, usamos Velocity aqui para gerar códigos e com parser view, mas jsp é melhor… hehehe

B

Oi

Como consigo gerar arquivos .java com o velocity? alguem tem algum exemplo?

Obrigado…

R

Da mesma forma como vc gera qualquer outro tiop de arquivo com Velocity. A unica diferenca eh que o teu template devera usar as palavras-chave validas para um fonte jav :wink:

Rafael

G

Olá,

Estou tentando entender um pouco melhor o velocity, mas acho que não comecei muito bem.

Peguei o tutorial mas quando fui tentar rodar a classe de exemplo lá existente não consegui de forma alguma… Ele sempre da erro quando tenta localizar o arquivo de template.

“org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource ‘template1.vm’”

Coloquei o caminho absoluto do arquivo no código e não funcionou, coloquei o arquivo de template no diretório do projeto e também não funcionou…

Alguém pode me ajudar??? O classpath está perfeito, pois existem algumas referências a classes do velocity antes de tentar localizar o template e essas estão funcionando.

Obs.: Uso o Jdev como IDE e container. Também costumo usar o Websphere (mas esse uso raramente)… E nos dois o erro foi o mesmo

G

Sinceramente eu acho isso puro MODISMO.

Não tem pra que eu chamar um script que se encontra em arquivo um vsl.

Motivos:

  1. Não tem nenhuma IDE que lhe auxilie a trabalhar com ela;
  2. Não existe nenhum auto-complete com os códigos;
  3. Não tem como debugar;
  4. Eu poderia resolver essa questão de não misturar código java com a apresentação facilmente utilizando Struts.

Estou falando isso por experiência própria.

M

:roll:

I

Pessoal,

Tenho um dúvida quanto ao Velocity. Eu sei que ele é usado para escrever documentos texto utilizando template + variáveis. No entanto, eu gostaria de uma ferramenta Java que fizesse o contrário disto: A partir de um template c/ variáveis + documento, obtesse um objeto Java de uma classe qualquer determinada. Em outras palavras tenho:

  • um template XML
  • um documento XML que “encaixa-se” neste template (ou seja, pode ter sido gerado por este template)
  • um objeto Java de uma classe qualquer que contenha atributos com os mesmos nomes das variáveis do template.

Gostaria de saber se o Velocity consegue ler os dados de um XML (por exemplo), baseando-se nas variáveis do template, para alimentar os atributos do objeto Java?

Exemplificando…

template XML:

<?xml version='1.0'?>
<Documento versao='${versao}'>
   <Atributos>
      <Atributo1 valor='${atributos.atributo1}' />
      <Atributo2 valor='${atributos.atributo2}' />
   </Atributos>
   <Name>${name}</Name>
</Documento>

XML:

<?xml version='1.0'?>
<Documento versao='5.5'>
   <Atributos>
      <Atributo1 valor='valor do atributo1' />
      <Atributo2 valor='valor do atributo2' />
   </Atributos>
   <Name>Nome qualquer...</Name>
</Documento>

Classes Java:

public class ClasseQualquer {
   private Atributos atributos;
   private String name;

   // Métodos set e get dos atributos private
}

public class Atributos {
   private String atributo1;
   private String atributo2;

   // Métodos set e get dos atributos private
}

Sendo assim, seria executado um processo ao qual um objeto da classe ClasseQualquer teria o atributo ‘name’ alimentado com ‘Nome qualquer…’, ‘atributos’ seria alimentado com um objeto da classe Atributos. Este por sua vez, teria os atributos ‘atributo1’ e ‘atributo2’ alimentados respectivamente com os valores: ‘valor do atributo1’ e ‘valor do atributo2’.

era isso…

I

putz… ninguem respondeu?!
Vai ver não existe isso né? :-o

Bom… ótima oportunidade para implementar…

J

Com Velocity eu não sei se da p/ fazer, mas qualquer parser xml por ae, tipo o XStream faz o que vc quer.

[]´s

I

jgbt:
Com Velocity eu não sei se da p/ fazer, mas qualquer parser xml por ae, tipo o XStream faz o que vc quer.

[]´s

Obrigado pela resposta.
Nunca usei o XStream, mas pelo que pesquisei essa tecnologia não permite eu costumizar o meu XML. Eu quero que faça algo semelhante ao que faz o XStream, porém o formato do XML tem que ser costumizavel (por isto o exemplo que eu dei tem um TEMPLATE) pois as variáveis no XML podem estar contidas tanto dentro de TAGs quando dentro de atributos de TAGs.

Espero ter sido claro…

E

Administrador:
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!

Bom dia.

Cara, eu sou um novo usuário desse fórum e tenho uma grande dúvida sobre VELOCITY.

Eu estou implementando uma notificação, e tenho que enviá-la por e-mail. Porém quero enviar esse e-mail formatado com logo, cor de fundo etc. É possível usar código HTML dentro desse arquivo - VELOCITY???

Ps. Se for possível, por favor mande um exemplo.

Grato por toda ajuda,

Elimarcos Alles.

Criado 21 de setembro de 2002
Ultima resposta 7 de nov. de 2008
Respostas 38
Participantes 21