Capítulo 7

VRaptor

7.1 - Sobre o VRaptor

VRaptor 3 é um framework MVC para web focado no desenvolvimento ágil.

Através da inversão de controle e injeção de depêndencias, ele diminui drasticamente o tempo de trabalho que seria perdido com o código repetitivo: validações, conversões, direcionamentos, ajax e lookups.

7.2 - Como instalar

Para utilizar o VRaptor, basta fazer o download da última versão do VRaptor, e depois fazer o unzip.

Após fazer o unzip, abra a pasta que foi criada e copie os jar's que estão em lib/mandatory para a pasta WEB-INF/lib do seu projeto, além do vraptor-3.X.X.jar. Também é necessário escolher um container de injeção de dependências (falaremos sobre eles mais pra frente no curso), entre o Spring, Google Guice ou Pico container, adicionando todos os jars da pasta lib/containers/<container>.

Nova editora Casa do Código com livros de uma forma diferente

Editoras tradicionais pouco ligam para ebooks e novas tecnologias. Não conhecem programação para revisar os livros tecnicamente a fundo. Não têm anos de experiência em didáticas com cursos.
Conheça a Casa do Código, uma editora diferente, com curadoria da Caelum e obsessão por livros de qualidade a preços justos.

Casa do Código, ebook com preço de ebook.

7.3 - Como configurar

Uma das grandes vantagens do VRaptor é que ele usa muitas convenções, ou seja, ao invés de termos que configurar tudo, como por exemplo no Struts, não precisamos configurar quase nada.

Seguindo as convenções que o VRaptor usa, podemos criar apenas nossas lógicas (código java) sem precisar escrever xml's ou properties.

A única configuração que precisamos fazer é configurar o controlador do VRaptor. Essa configuração é feita dentro do arquivo web.xml, o arquivo de configuração da aplicação.

<web-app ...>
  <!-- configura o controlador do VRaptor -->
  <filter>
    <filter-name>vraptor</filter-name>
    <filter-class>br.com.caelum.vraptor.VRaptor</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>vraptor</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>
</web-app>

Essas configurações já foram feitas no projeto base.

Servlet 3.0

Se você estiver usando um Servlet Container que implementa a Servlet 3.0 você nem precisa da configuração do filtro no web.xml. Basta colocar o jar do VRaptor na pasta WEB-INF/lib e ele será configurado automaticamente.

7.4 - Primeiro exemplo com o VRaptor

Vamos criar nosso primeiro exemplo utilizando o VRaptor. Esse primeiro exemplo será bem simples, para entendermos o funcionamento do VRaptor. Veremos mais adiante exemplos mais complexos e mais elaborados.

Nosso primeiro exemplo será composto de uma classe, que representará as regras de negócio, e uma página de resultado.

Vamos começar pela regra de negócio, um método dentro de uma classe java simples.

1 package br.com.caelum.goodbuy;
2 
3 public class Mundo {
4 
5   public void boasVindas() {
6     System.out.println("olá mundo!");
7   }
8   
9 }

Repare que essa classe não herda nem implementa nenhuma interface. Essa classe é um exemplo de um POJO. Isso é muito importante porque a classe está bem simples, bem legível.

Agora como fazer para chamar essa lógica? Queremos chamá-la assim pelo browser:

http://localhost:8080/goodbuy/mundo/boasVindas

Para chamar essa lógica, temos que anotar nossa classe que contêm a regra de negócio, para indicar para o controlador do VRaptor que essa classe deve ser controlada por ele.

A anotação que utilizaremos para indicar isso é a @Resource.

Nossa classe ficará assim:

 1 package br.com.caelum.goodbuy;
 2 
 3 import br.com.caelum.vraptor.Resource;
 4 
 5 @Resource
 6 public class Mundo {
 7 
 8   public void boasVindas() {
 9     System.out.println("olá mundo!");
10   }
11   
12 }

O VRaptor vai usar uma convenção para chamar o nosso método: para executar o método boasVindas() da classe Mundo, posso chamar no browser a URI /mundo/boasVindas a partir da nossa aplicação, ou seja, a URI http://localhost:8080/goodbuy/mundo/boasVindas.

 1 package br.com.caelum.goodbuy;
 2 
 3 import br.com.caelum.vraptor.Resource;
 4 
 5 @Resource
 6 public class Mundo {
 7   
 8   public void boasVindas() {
 9     System.out.println("olá mundo!");
10   }
11   
12 }

7.5 - Exercícios

  1. Crie a classe Mundo no pacote br.com.caelum.goodbuy.

    1 package br.com.caelum.goodbuy;
    2 
    3 public class Mundo {
    4 
    5   public void boasVindas() {
    6     System.out.println("olá mundo!");
    7   }
    8   
    9 }
    
  2. Anote a classe Mundo com @Resource.

  3. Abra um browser, por exemplo o Firefox, e digite a seguinte url: http://localhost:8080/goodbuy/mundo/boasVindas

  4. Ao acessar essa url, é mostrada uma página com erro 404 (página não encontrada). Isso ocorreu porque ainda não criamos a página de resultado. Ela será criada na próxima seção. O importante é verificar o log da aplicação, na view Console do Eclipse, e ver que a mensagem apareceu.

    log-console1.png
  5. (Opcional) Crie outro método, parecido com o que fizemos, e acesse pelo browser. Se quiser, esse método pode ser em outra classe.

Já conhece os cursos online Alura?

A Alura oferece centenas de cursos online em sua plataforma exclusiva de ensino que favorece o aprendizado com a qualidade reconhecida da Caelum. Você pode escolher um curso nas áreas de Java, Front-end, Ruby, Web, Mobile, .NET, PHP e outros, com um plano que dá acesso a todos os cursos.

Conheça os cursos online Alura.

7.6 - Redirecionando para uma view

Nosso último exemplo executava a lógica que tínhamos criado, mas a página de resultado não tinha sido feita, e recebíamos o erro 404.

Vamos fazer a página de resultado, para que depois de executada a lógica, essa página seja chamada. Esse é o conteúdo da página:

Olá Mundo!

Conforme foi dito anteriormente, o VRaptor prefere convenções do que configurações. A convenção de redirecionamento de páginas após a lógica é a seguinte:

/WEB-INF/jsp/{nomeDoResource}/{lógica}.jsp

Para nosso caso, temos a seguinte situação:

O VRaptor vai fazer algumas modificações nesses valores. A primeira letra do nome do resource, que para nós é o nome da classe, será passado para minúsculo. O resto do nome continuará igual. Já o nome da lógica continuará igual, mas sem os parênteses. Então o VRaptor vai considerar os seguintes valores:

E a página que ele buscará será a seguinte:

/WEB-INF/jsp/mundo/boasVindas.jsp

7.7 - Exercícios

  1. Crie uma pasta chamada jsp dentro da pasta WEB-INF. Cuidado, o nome da pasta deve ser com letras minúsculas.

  2. Crie uma pasta chamada mundo dentro da pasta WEB-INF/jsp. Cuidado, o nome da pasta deve ser com letras minúsculas.

  3. Crie um jsp chamado boasVindas.jsp dentro da pasta WEB-INF/jsp/mundo. Seu projeto deve ficar assim:

    redirecionando-para-a-view1.png
  4. Abra o arquivo boasVindas.jsp que acabamos de criar e digite o seguinte conteúdo:

    Olá Mundo!
    
  5. Vamos testar nossas alterações. Inicie o Tomcat na view Servers, depois abra um browser e digite a seguinte url: http://localhost:8080/goodbuy/mundo/boasVindas

  6. Verifique se o console mostra a mensagem "olá mundo!", e verifique se o browser exibe a mensagem Olá Mundo.

    redirecionando-para-a-view2.png

7.8 - Disponibilizando informações para a view

Nosso exemplo até agora só executa algo no servidor e depois a view é chamada.

Mas para muitos casos precisamos que a lógica carregue informações do banco de dados e depois a view exiba essas informações.

No VRaptor 3 foi criada uma característica muito intuitiva de se mandar informações para a view. Quando um método é invocado, por exemplo nosso método boasVindas(), podemos fazer com que ele retorne algo, e esse retorno será enviado para a view automaticamente.

As versões anteriores usavam atributos junto com anotações ou getters. O problema dessa abordagem é que a classe ficava muito poluída com atributos, getters ou anotações.

Vamos alterar nosso método para enviar informações para a view:

 1 package br.com.caelum.goodbuy;
 2 
 3 @Resource
 4 public class Mundo {
 5   
 6   public String boasVindas() {
 7     return "olá mundo!";
 8   }
 9   
10 }

Agora o método boasVindas() não imprime nada, apenas retorna uma string. Após a execução desse método, essa string já estará disponível na view.

É muito importante perceber a legibilidade desse método. É uma classe java normal, e um método que retorna uma string.

Para que a view possa imprimir esse valor, vamos utilizar Expression Language no nosso jsp. Nosso jsp ficará assim:

Mensagem vinda da lógica: ${string} 

Como utilizamos o retorno do método para disponibilizar informações para a view, não temos como dar um nome significativo para utilizar depois.

O VRaptor usa a convenção de buscar o tipo do retorno, nesse nosso caso uma String, e disponibilizar para a view com o mesmo nome, apenas passando a primeira letra para minúsculo. Por esse motivo que foi utilizado a expression language ${string}.

Saber inglês é muito importante em TI

O Galandra auxilia a prática de inglês através de flash cards e spaced repetition learning. Conheça e aproveite os preços especiais.

Pratique seu inglês no Galandra.

7.9 - Disponibilizando coleções para a view

Podemos utilizar a mesma maneira que fizemos com Strings para disponibilizar coleções para a view. Utilizamos muito as coleções do pacote java.util, seja pela facilidade no uso ou pela integração com frameworks como o Hibernate.

Se nossa lógica criasse uma coleção com informações que vieram do banco de dados, poderíamos retornar essa coleção, assim como fizemos anteriormente. O código ficaria assim:

 1 package br.com.caelum.goodbuy;
 2 
 3 @Resource
 4 public class Mundo {
 5   
 6   public String boasVindas() {
 7     return "olá mundo!";
 8   }
 9   
10   public List<String> paises() {
11     List<String> result = new ArrayList<String>();
12     result.add("Brasil");
13     result.add("Portugal");
14     result.add("Japão");
15     result.add("Canadá");
16     result.add("Paraguai");
17     return result;
18   }
19 
20 }

Na nossa view, podemos imprimir os valores dessa coleção da seguinte forma:

Países vindos da lógica: ${stringList} 

Note que agora o valor passado na expression language foi ${stringList}. O VRaptor identifica que devolvemos uma lista, e essa lista é genérica, informando que o tipo de informação dentro da lista será String.

Para listas, o VRaptor vai adotar a seguinte convenção:

{tipoDaLista}List

Nosso exemplo era de uma lista de String, ou seja, List<String>, que virou ${stringList}.

7.10 - Exercícios

  1. Altere o método boasVindas() da classe Mundo para retornar uma String.

     1 package br.com.caelum.goodbuy;
     2 
     3 @Resource
     4 public class Mundo {
     5   
     6   public String boasVindas() {
     7     return "olá mundo!";
     8   }
     9   
    10 }
    
  2. Altere o jsp boasVindas.jsp, que está dentro da pasta WEB-INF/jsp/mundo.

    Mensagem vinda da lógica: ${string} 
  3. Teste a lógica que acabamos de criar, acessando a seguinte url: http://localhost:8080/goodbuy/mundo/boasVindas Sua página deve exibir o seguinte resultado:

    disponibilizando-para-a-view1.png
  4. Crie um método chamado paises() na classe Mundo. Esse método deve retornar uma lista de Strings. Seu código ficará assim:

    public List<String> paises() {
      List<String> result = new ArrayList<String>();
      result.add("Brasil");
      result.add("Portugal");
      result.add("Japão");
      result.add("Canadá");
      result.add("Paraguai");
      return result;
    }
    
  5. Crie um jsp em WEB-INF/jsp/mundo chamado paises.jsp. O conteúdo deve ser esse:

    Países vindos da lógica: ${stringList} 
  6. Teste a lógica que acabamos de criar, acessando a seguinte url:

    http://localhost:8080/goodbuy/mundo/paises

    Sua página deve exibir o seguinte resultado:

    disponibilizando-para-a-view2.png
  7. (Opcional) Crie outro método que mande alguma informação para a view. Dessa vez, tente retornar um valor inteiro ou um valor decimal.

  8. (Opcional) Crie outro método que retorne um Produto, com algumas informações preenchidas. Tente imprimir essas informações no jsp.

  9. (Opcional) Na view que exibe os países, itere sobre a coleção e mostre cada país em uma linha. Dica: use o JSTL, tag c:forEach.

  10. (Opcional) Um método só pode retornar uma informação. Mas como faríamos para disponibilizar para a view mais de uma informação?