Bom, meu último post desse ano, vou falar do incrível framework brasileiro o VRaptor.
É outro framework MVC que vale a pena aprender e escrever sobre é o VRaptor, é um framework MVC muito poderoso, teve seu início na época do Struts 1.x, como solução a burôcracia que o Struts trazia, é mantido pela Caelum, grátis e open source e se diferencia pela facilidade na curva de aprendizado e por trabalhar com convenções a configurações, ou seja, adeus um monte de XML, para quem viu o último post de Spring, verá que VRaptor é tão simples de utilizá-lo quanto o próprio Spring MVC.
Outra vantagem é documentação nas opções Português e Inglês, a Caelum também fornece uma apostila completa de forma grátis para download e caso a empresa queira investir há o curso de VRaptor FJ 28 e o curso VRaptor online.
Fiz o curso online e recomendo.
Vamos ver um exemplo que montei em VRaptor, o código está disponível para download.
Aconselho antes a ler sobre Patterns como DAO, Repository, MVC, TO, PO, VO, DTO.
Criei um pequeno CRUD sem acesso ao banco apenas para mostrar a simplicidade do framework, basta pegar o código e rodar no seu Eclipse ou IDE favorita.
Tentei manter no estilo do post sobre Spring para quem estiver acompanhando validar o quão semelhante e mais simples o VRaptor é.
Passo 1:
Crie um projeto Web (ou importe o código).
Passo 2:
Criei a estrutura de pacotes:
Passo 3:
Vamos criar os Beans que ficaram no pacote domain:
Passo 4:
Assim como no Spring é utilizado no VRaptor algumas anotações para o framework saber o que vamos querer e criar seus mapeamentos assim não necessitamos de XMLs.
No DAO utilizaremos as anotações:
@Component - VRaptor mapeará as classes como componentes (instâncias das classes que executarão tarefas)
@RequestScoped - Os componentes ficam em escopos específicos, podemos mapeá-los como @RequestScoped (o componente é o mesmo durante uma instância), @SessionScoped (Componente é o mesmo durante uma http session), @ApplicationScoped (Singleton, apenas 1 por aplicação), @PrototypeScoped (Componente sempre instanciado quando requisitado), maiores informações aqui.
Comparativo:No Spring utilizávamos a anotação @Repository.
LivroDao
É boa prática sempre criar interfaces então criei a LivroDaoI
Lembrete: Esses livros do exemplo existem e recomendo.
Passo 5:
Criei uma camada de business ondem a lógica de negócio será mantida separada da DAO e da camada de View, também está mapeada com @Component, como o foco não é o Spring não utilizei o @Autowired para injetar dependências, mas você pode utilizá-lo.
Comparativo:
No Spring utilizávamos a anotação @Service.
LivroService
LivroServiceI
Para evitar acessar diretamente o Bean e se por ventura necessitar colocar algum atributo de tela criei um Form onde conterá o Bean e os demais atributos de tela caso necessário.
LivroForm
Passo 7:
Criei uma classe Controller assim como no Spring o padrão adotado é NomeClasseController, utilizaremos aqui a anotação @Resource TODOS seus controllers deverão ter essa anotação.
@Resource - O VRaptor saberá através dessa anotação qual a convençao para criar a URI exemplo: /nomeController/nomeMetodo.
Temos também a anotação @Post e @Path("/livro/{id}").
@Post - Aqui poderíamos criar comportamentos REST, iremos receber nosso form completamente populado.
@Path("/livro/{id}") - Aqui receberemos no nosso bean livro o atributo id preenchido, essa anotação muda a URI que acessará o método.
Foi utilizado também a Classe Result que tem como objetivo retornar um ou mais objetos, assim como mensagens, dentro outas coisas vale a pena ler aqui.
Validação:
validator.checking(new Validations(){{
that(livroForm.getLivro().getPreco().doubleValue() > 0,"erro", "livro.preco.invalido");
}});
validator.onErrorUsePageOf(this).formulario();
Para validar os dados de retorno no método basta chamar o validator.checking, instanciar Validations, dentro do that você colocará a validação, a categoria e a mensagem.
O validator.onErrorUsePageOf(this).formulario(); é utilizado para fazer o direcionamento, dentro passo um this informando que é essa classe (LivroController) que ele vai utilizar no método formulario, ou seja ele irá redirecionar para o formulário com as mensagens de erro.
No JSP para exibir a mensagem basta colocar:
Comparação:
No Spring utilizamos as anotações: @Controller, @RequestMapping, @RequestParam(value = "produto.id") que fariam as mesmas coisas acima.
No caso do Result seria a utilização do ModelAndView quem traz a mesma idéia de enviar um ou mais objetos.
Validação:
No Spring utilizamos no parametro do método do Controller um @Valid e quem trata o erro e adiciona as mensagens após a verificação por um if ou pelo HibernateValidator é o BindingResult.
No JSP colocaríamos por exemplo:
Assim como no Spring, no VRaptor um método terá um JSP que o representa, assim o VRaptor por convenção o redirecionará.
Passo 8:
Os JSPs devem estar dentro da pasta WEB-INF -> jsp -> nomeDoQueEleRepresenta -> nomeMetodoQueEleRepresenta.
Exemplo:
Simples se o controller vai criar a URI, nossa estrutura do JSP deverá estar representando esse acesso, nosso controller chama-se LivroController e dentro há um método exibe sua url ficará /livro/exibe, dentro da pasta jsp (padrão) deverá conter a pasta livro (LivroController, remove-se do nome Controller), exibe (Método que há dentro de LivroController), por convenção ele saberá se achar e fazer a escolha do jsp para abrir no browser.
No exemplo para download tem todos JSPs, acesso via EL aos valores ea única taglib que utilizei foi a de formatação já citada no exemplo Spring MVC.
Comparação:
No caso do Spring é necessário configurar pelo menos 1 XML que representará onde ele encontrará os JSPs e também terá a configuração para ele achar os pacotes que contenham os mapeamentos, isso NÃO é feito no VRaptor, não existe essa configuração, o VRaptor por suas convenções é mais inteligente.
Passo 9:
web.xml
Passo 10:
Para internacionalização das mensagens de erro criei um message.properties
Mais Informações:
Blog da Caelum - Links de Artigos e Cursos
Macelo Madeira - Vantagens do VRaptor
Lucas Toniazzo - Iniciando com VRaptor
Washington Botelho - Posts sobre Vraptor
Revistas:
Mundo Java (Mundo J) - Ediçoes: 61, 93, 94, 96, 98
Java Magazine - Ediçoes: 17, 38
Um Feliz Ano Novo para todos.
É outro framework MVC que vale a pena aprender e escrever sobre é o VRaptor, é um framework MVC muito poderoso, teve seu início na época do Struts 1.x, como solução a burôcracia que o Struts trazia, é mantido pela Caelum, grátis e open source e se diferencia pela facilidade na curva de aprendizado e por trabalhar com convenções a configurações, ou seja, adeus um monte de XML, para quem viu o último post de Spring, verá que VRaptor é tão simples de utilizá-lo quanto o próprio Spring MVC.
Outra vantagem é documentação nas opções Português e Inglês, a Caelum também fornece uma apostila completa de forma grátis para download e caso a empresa queira investir há o curso de VRaptor FJ 28 e o curso VRaptor online.
Fiz o curso online e recomendo.
Vamos ver um exemplo que montei em VRaptor, o código está disponível para download.
Aconselho antes a ler sobre Patterns como DAO, Repository, MVC, TO, PO, VO, DTO.
Criei um pequeno CRUD sem acesso ao banco apenas para mostrar a simplicidade do framework, basta pegar o código e rodar no seu Eclipse ou IDE favorita.
Tentei manter no estilo do post sobre Spring para quem estiver acompanhando validar o quão semelhante e mais simples o VRaptor é.
Passo 1:
Crie um projeto Web (ou importe o código).
Passo 2:
Criei a estrutura de pacotes:
Passo 3:
Vamos criar os Beans que ficaram no pacote domain:
public class Livro {
private Long id;
private String titulo;
private String loja;
private BigDecimal preco;
private String autor;
public Livro(Long id, String titulo, String loja, BigDecimal preco, String autor){
this.id = id;
this.titulo = titulo;
this.loja = loja;
this.preco = preco;
this.autor = autor;
}
public Livro() {
}
//getters and setters
}
Passo 4:
Assim como no Spring é utilizado no VRaptor algumas anotações para o framework saber o que vamos querer e criar seus mapeamentos assim não necessitamos de XMLs.
No DAO utilizaremos as anotações:
@Component - VRaptor mapeará as classes como componentes (instâncias das classes que executarão tarefas)
@RequestScoped - Os componentes ficam em escopos específicos, podemos mapeá-los como @RequestScoped (o componente é o mesmo durante uma instância), @SessionScoped (Componente é o mesmo durante uma http session), @ApplicationScoped (Singleton, apenas 1 por aplicação), @PrototypeScoped (Componente sempre instanciado quando requisitado), maiores informações aqui.
Comparativo:No Spring utilizávamos a anotação @Repository.
LivroDao
@Component
@RequestScoped
public class LivroDao implements LivroDaoI {
private final static Listlivros = new ArrayList ();
static {
populaProdutosIniciais();
}
public void salva(Livro livro) {
livro.setId(livros.size() +1l);
livros.add(livro);
}
public ListlistaTodos() {
return Collections.unmodifiableList(livros);
}
public void remove(Livro livro) {
Iteratorit = livros.iterator();
while(it.hasNext()) {
Livro existente = it.next();
if(existente.getId().equals(livro.getId())) {
it.remove();
break;
}
}
}
private static void populaProdutosIniciais() {
livros.add(new Livro(1l, "Introdução À Arquitetura e Design de Software - Uma Visão Sobre a Plataforma Java", "Saraiva", new BigDecimal(73.00), "Sergio Lopes, Paulo Silveira, Guilherme Silveira"));
livros.add(new Livro(2l, "iWOZ - a Verdadeira História da Apple Segundo Seu Cofundador", "Saraiva", new BigDecimal(49.90), "Steve Wozniak, Gina Smith"));
livros.add(new Livro(3l, "Steve Jobs - A Biografia", "Livraria Cultura", new BigDecimal(49.90), "Walter Isaacson"));
livros.add(new Livro(4l, "Use a cabeça! Padrões de Projetos", "Livraria Cultura", new BigDecimal(142.89), "Eric Freeman, Elisabeth Freeman"));
}
public Livro buscaPorId(Long id) {
for(Livro livro : livros) {
if(livro.getId().equals(id)){
return livro;
}
}
return null;
}
}
É boa prática sempre criar interfaces então criei a LivroDaoI
public interface LivroDaoI {
public void salva(Livro livro);
public ListlistaTodos();
public void remove(Livro livro);
public Livro buscaPorId(Long id);
}
Lembrete: Esses livros do exemplo existem e recomendo.
Passo 5:
Criei uma camada de business ondem a lógica de negócio será mantida separada da DAO e da camada de View, também está mapeada com @Component, como o foco não é o Spring não utilizei o @Autowired para injetar dependências, mas você pode utilizá-lo.
Comparativo:
No Spring utilizávamos a anotação @Service.
LivroService
@Component
public class LivroService implements LivroServiceI{
private LivroDaoI livroDao;
public LivroService(){
if(livroDao==null){
livroDao = new LivroDao();
}
}
public void salva(Livro livro) {
livroDao.salva(livro);
}
public ListlistaTodos() {
return livroDao.listaTodos();
}
public void remove(Livro livro) {
livroDao.remove(livro);
}
public Livro buscaPorId(Long id) {
return livroDao.buscaPorId(id);
}
}
LivroServiceI
public interface LivroServiceI {Passo 6:
public void salva(Livro livro);
public ListlistaTodos();
public void remove(Livro livro);
public Livro buscaPorId(Long id);
}
Para evitar acessar diretamente o Bean e se por ventura necessitar colocar algum atributo de tela criei um Form onde conterá o Bean e os demais atributos de tela caso necessário.
LivroForm
public class LivroForm {
private Livro livro = new Livro();
//getters and setters
}
Passo 7:
Criei uma classe Controller assim como no Spring o padrão adotado é NomeClasseController, utilizaremos aqui a anotação @Resource TODOS seus controllers deverão ter essa anotação.
@Resource - O VRaptor saberá através dessa anotação qual a convençao para criar a URI exemplo: /nomeController/nomeMetodo.
Temos também a anotação @Post e @Path("/livro/{id}").
@Post - Aqui poderíamos criar comportamentos REST, iremos receber nosso form completamente populado.
@Path("/livro/{id}") - Aqui receberemos no nosso bean livro o atributo id preenchido, essa anotação muda a URI que acessará o método.
Foi utilizado também a Classe Result que tem como objetivo retornar um ou mais objetos, assim como mensagens, dentro outas coisas vale a pena ler aqui.
Validação:
validator.checking(new Validations(){{
that(livroForm.getLivro().getPreco().doubleValue() > 0,"erro", "livro.preco.invalido");
}});
validator.onErrorUsePageOf(this).formulario();
Para validar os dados de retorno no método basta chamar o validator.checking, instanciar Validations, dentro do that você colocará a validação, a categoria e a mensagem.
O validator.onErrorUsePageOf(this).formulario(); é utilizado para fazer o direcionamento, dentro passo um this informando que é essa classe (LivroController) que ele vai utilizar no método formulario, ou seja ele irá redirecionar para o formulário com as mensagens de erro.
No JSP para exibir a mensagem basta colocar:
[c:forEach var="error" items="${errors}"]
${error.category} - ${error.message}[br /]
[/c:forEach]
Comparação:
No Spring utilizamos as anotações: @Controller, @RequestMapping, @RequestParam(value = "produto.id") que fariam as mesmas coisas acima.
No caso do Result seria a utilização do ModelAndView quem traz a mesma idéia de enviar um ou mais objetos.
Validação:
No Spring utilizamos no parametro do método do Controller um @Valid e quem trata o erro e adiciona as mensagens após a verificação por um if ou pelo HibernateValidator é o BindingResult.
No JSP colocaríamos por exemplo:
[form:errors path="nome" /]LivroController
@Resource
public class LivroController {
private final Result result;
private final LivroServiceI livroService;
private final Validator validator;
public LivroController(LivroServiceI livroService, Result result, Validator validator) {
this.livroService = livroService;
this.result = result;
this.validator = validator;
}
public void formulario(){
}
public void consulta(){
}
@Post
public void adiciona(final LivroForm livroForm){
validator.checking(new Validations(){{
that(livroForm.getLivro().getPreco().doubleValue() > 0,"erro", "livro.preco.invalido");
that(!livroForm.getLivro().getTitulo().isEmpty(), "erro", "livro.titulo.nao.informado");
that(!livroForm.getLivro().getLoja().isEmpty(), "erro", "livro.loja.nao.informado");
}});
validator.onErrorUsePageOf(this).formulario();
livroService.salva(livroForm.getLivro());
result.redirectTo(this).lista();
}
public void remove (Livro livro){
livroService.remove(livro);
result.nothing();
}
public Listlista() {
return livroService.listaTodos();
}
@Post
public void pesquisa(LivroForm livroForm) {
result.redirectTo(this).exibe(livroForm.getLivro().getId());
}
@Path("/livro/{id}")
public LivroForm exibe(Long id){
LivroForm livroForm = new LivroForm();
livroForm.setLivro(livroService.buscaPorId(id));
return livroForm;
}
}
Assim como no Spring, no VRaptor um método terá um JSP que o representa, assim o VRaptor por convenção o redirecionará.
Passo 8:
Os JSPs devem estar dentro da pasta WEB-INF -> jsp -> nomeDoQueEleRepresenta -> nomeMetodoQueEleRepresenta.
Exemplo:
Simples se o controller vai criar a URI, nossa estrutura do JSP deverá estar representando esse acesso, nosso controller chama-se LivroController e dentro há um método exibe sua url ficará /livro/exibe, dentro da pasta jsp (padrão) deverá conter a pasta livro (LivroController, remove-se do nome Controller), exibe (Método que há dentro de LivroController), por convenção ele saberá se achar e fazer a escolha do jsp para abrir no browser.
No exemplo para download tem todos JSPs, acesso via EL aos valores ea única taglib que utilizei foi a de formatação já citada no exemplo Spring MVC.
Comparação:
No caso do Spring é necessário configurar pelo menos 1 XML que representará onde ele encontrará os JSPs e também terá a configuração para ele achar os pacotes que contenham os mapeamentos, isso NÃO é feito no VRaptor, não existe essa configuração, o VRaptor por suas convenções é mais inteligente.
Passo 9:
web.xml
[?xml version="1.0" encoding="UTF-8"?]Notem que a configuração do web.xml é muito mais simples do que a configuração que fazemos no Spring.
[web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"]
[display-name]projetoVRaptor[/display-name]
[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]
Passo 10:
Para internacionalização das mensagens de erro criei um message.properties
livro.preco.invalido=preço deve ser maior que 0.Espero que tenham gostado, o VRaptor é um poderoso framework MVC, para quem já utiliza Spring MVC é muito fácil entender como o VRaptor funciona, também torna bem mais simples a vida do desenvolvedor pois o único XML configurado é o web.xml, isso é uma enorme vantagem, as convenções também tornam o trabalho muito rápido e produtivo facilitando muito nossa vida.
livro.titulo.nao.informado=O título é obrigatória.
livro.loja.nao.informado=A Loja de venda é obrigatória.
Mais Informações:
Blog da Caelum - Links de Artigos e Cursos
Macelo Madeira - Vantagens do VRaptor
Lucas Toniazzo - Iniciando com VRaptor
Washington Botelho - Posts sobre Vraptor
Revistas:
Mundo Java (Mundo J) - Ediçoes: 61, 93, 94, 96, 98
Java Magazine - Ediçoes: 17, 38
Um Feliz Ano Novo para todos.