--- title: O guia inicial de 10 minutos --- #Começando o projeto: uma loja virtual ##Um cadastro de produtos Para começar o sistema, vamos começar com cadastro de produtos. Precisamos de uma classe que vai representar o produto, e vamos usá-la para guardar produtos no banco, usando o JPA/Hibernate: ~~~ #!java @Entity public class Produto { @Id @GeneratedValue private Long id; private String nome; private String descricao; private Double preco; //getter e setters e métodos de negócio que julgar necessário } ~~~ Precisamos também de uma classe que vai controlar o cadastro de produtos, tratando requisições web. Essa classe vai ser o Controller de produtos: ~~~ #!java public class ProdutosController {} ~~~ A classe `ProdutosController` vai expor URIs para serem acessadas via web, ou seja, vai expor recursos da sua aplicação. E, para indicar isso, você precisa anotá-la com com `@Controller`: ~~~ #!java @Controller public class ProdutosController {} ~~~ Ao colocar essa anotação na classe, todos os métodos públicos dela serão acessíveis pela web. Por exemplo, se tivermos um método lista na classe: ~~~ #!java @Controller public class ProdutosController { public List lista() { return new ArrayList(); } } ~~~ O VRaptor automaticamente redirecionará todas as requisições à URI `/produtos/lista` para esse método. Ou seja, a convenção para a criação de URIs é `//`. Ao terminar a execução do método, o VRaptor fará o dispatch da requisição para o JSP `/WEB-INF/jsp/produtos/lista.jsp`. Ou seja, a convenção para a view padrão é `/WEB-INF/jsp//.jsp`. O método `lista` retorna uma lista de produtos, mas como acessá-la no JSP? No VRaptor, o retorno do método é exportado para a JSP por meio de atributos da requisição. No caso do método lista, vai existir um atributo chamado `produtoList` contendo a lista retornada: ~~~ #!jsp
  • ${produto.nome} - ${produto.descricao}
~~~ A convenção para o nome dos atributos exportados é bastante intuitiva: se for uma collection, como o caso do método acima, o atributo será `List`, `produtoList` no caso; se for uma classe qualquer vai ser o nome da classe com a primeira letra minúscula. Se o método retorna `Produto`, o atributo exportado será `produto`. Veremos em outro capítulo que podemos expor mais de um objeto sem usar o retorno, por meio do `Result`, onde podemos dar nome à variável exposta. ##Criando o ProdutoDao: Injeção de Dependências (DI) O VRaptor usa fortemente o conceito de Injeção de Dependências (DI) e Inversão de Controle (IoC). A ideia é que você não precise criar ou buscar as dependências da sua classe, você simplesmente as recebe e o VRaptor se encarrega de criá-las pra você. Estamos retornando uma lista vazia no nosso método `lista`. Seria muito mais interessante retornar uma lista de verdade, por exemplo todas os produtos cadastrados no sistema. Para isso vamos criar um DAO de produtos, para fazer a listagem: ~~~ #!java public class ProdutoDao { public List listaTodos() { return new ArrayList(); } } ~~~ E no nosso `ProdutosController` podemos usar o dao pra fazer a listagem de produtos: ~~~ #!java @Controller public class ProdutosController { @Inject private ProdutoDao dao; public List lista() { return dao.listaTodos(); } } ~~~ Podemos instanciar o `ProdutoDao` direto do controller, porém é muito mais interessante aproveitar o gerenciamento de dependências que o VRaptor faz e receber o DAO. E, para que isso seja possível, basta anotar o DAO com `@RequestScoped`, anotar o atributo `dao` do controller com `@Inject` e o VRaptor vai se encarregar de criá-lo e injetá-lo na sua classe: ~~~ #!java @RequestScoped public class ProdutoDao { //... } @Controller public class ProdutosController { //... @Inject private ProdutoDao dao; public List lista() { return dao.listaTodos(); } } ~~~ ##Formulário de adição: redirecionamento Temos uma listagem de produtos, mas ainda não temos como cadastrá-los. Vamos então criar um formulário de adição de produtos. Para não ter que acessar o JSP diretamente, vamos criar uma lógica vazia que só redireciona para o JSP: ~~~ #!java @Controller public class ProdutosController { //... public void form() { ... } } ~~~ Podemos acessar o formulário, que estará em `/WEB-INF/jsp/produtos/form.jsp`, pela URI `/produtos/form`: ~~~ #!jsp
Nome:
Descrição:
Preço:
~~~ Como o formulário vai salvar o produto pela URI `/produtos/adiciona`, precisamos criar esse método no nosso controller: ~~~ #!java @Controller public class ProdutosController { //... public void adiciona() { ... } } ~~~ Repare nos nomes dos nossos inputs: `produto.nome`, `produto.descricao` e `produto.preco`. Se recebermos um `Produto` no método adiciona com o nome `produto`, o VRaptor vai popular os seus campos `nome`, `descricao` e `preco`, usando os seus setters no `Produto`, com os valores digitados nos inputs. Inclusive o campo `preco`, vai ser convertido para `Double` antes de ser setado no produto. Veja mais sobre isso no capítulo de [converters](/pt/docs/conversores). Então, usando os nomes corretamente nos inputs do form, basta criar seu método adiciona: ~~~ #!java @Controller public class ProdutosController { //... public void adiciona(Produto produto) { dao.adiciona(produto); } } ~~~ Geralmente, depois de adicionar algo no sistema queremos voltar para a sua listagem, ou para o formulário novamente. No nosso caso, queremos voltar pra listagem de produtos ao adicionar um produto novo. Para isso existe um componente do VRaptor: o `Result`. Ele é responsável por adicionar atributos na requisição, e por mudar a view a ser carregada. Se eu quiser uma instância de `Result`, basta declarar o atributo no controller e anota-lo com `@Inject`: ~~~ #!java @Controller public class ProdutosController { @Inject private ProdutoDao dao; @Inject private Result result; //... } ~~~ E para redirecionar para a listagem basta usar o `result`: ~~~ #!java result.redirectTo(ProdutosController.class).lista(); ~~~ Podemos ler esse código como: Como resultado, redirecione para o método `lista` do `ProdutosController`. A configuração de redirecionamento é 100% java, sem strings envolvidas! Fica explícito no seu código que o resultado da sua lógica não é o padrão e qual resultado você está usando! Você não precisa ficar se preocupando com arquivos de configuração. Mais ainda, se eu quiser mudar o nome do método `lista`, eu não preciso ficar rodando o sistema inteiro procurando onde estão redirecionando pra esse método, basta usar o refactor do eclipse, por exemplo, e tudo continua funcionando! Então nosso método adiciona ficaria: ~~~ #!java public void adiciona(Produto produto) { dao.adiciona(produto); result.redirectTo(ProdutosController.class).lista(); } ~~~ Veja mais informações sobre o `Result` no capítulo [Views e Ajax](/pt/docs/trabalhando-com-a-view). ##Usando o JPA/Hibernate para guardar os Produtos Agora vamos fazer uma implementação de verdade do `ProdutoDao`, usando o JPA para persistir os produtos. Para isso, nosso `ProdutoDao` precisa de um `EntityManager`. Como o VRaptor usa injeção de dependências, basta declarar um atributo do tipo `EntityManager` e anota-lo com `@Inject`. ~~~ #!java public class ProdutoDao { @Inject private EntityManager manager; public void adiciona(Produto produto) { manager.persist(produto); } //... } ~~~ O VRaptor precisa saber como criar esse `EntityManager`, e eu não posso simplesmente colocar um `@RequestScoped` na `EntityManager` pois é uma classe da JPA. Para isso existe precisamos criar um `@Produces`. Veja mais informações de como fazer isso no capítulo de [Componentes](/pt/docs/componentes). Você pode, ainda, usar o plugin para JPA que já existe para o VRaptor. Veja mais sobre isso no capítulo de [Plugins](/pt/docs/plugins). ##Controlando transações: Interceptors Muitas vezes, queremos interceptar todas as requisições (ou uma parte delas) e executar alguma lógica, como acontece com o controle de transações. Para isso, existem os Interceptors no VRaptor. Saiba mais sobre eles no capítulo de [Interceptors](/pt/docs/interceptadores). ##Carrinho de compras: Componentes na sessão Se quisermos criar um carrinho de compras no nosso sistema, precisamos de alguma forma manter os itens do carrinho na sessão do usuário. Para fazer isso, podemos criar um componente que está no escopo de sessão, ou seja, ele vai ser único na sessão do usuário. Para isso, basta criar um componente anotado com `@SessionScoped`: ~~~ #!java @SessionScoped public class CarrinhoDeCompras implements Serializable{ private List itens = new ArrayList(); public List getTodosOsItens() { return itens; } public void adicionaItem(Produto item) { itens.add(item); } } ~~~ Essa classe precisa implementar Serializable já que o escopo dela é o `SessionScoped` e os objetos criados a partir dela podem ser serializados para manter o estado da sessão. Essa necessidade é descrita na especificação no CDI e deve ser respeitada. Caso contrário o container vai lançar uma exception no momento da inicialização. Como esse carrinho de compras é um componente, podemos recebê-lo no controller que vai cuidar do carrinho de compras: ~~~ #!java @Controller public class CarrinhoController { @Inject private CarrinhoDeCompras carrinho; public void adiciona(Produto produto) { carrinho.adicionaItem(produto); } public List listaItens() { return carrinho.getTodosOsItens(); } } ~~~ Além do escopo de sessão existe o escopo de Aplicação com a anotação `@ApplicationScoped`. Os componentes anotados com `@ApplicationScoped` serão criados apenas uma vez em toda a aplicação. ##Um pouco de REST Seguindo a idéia REST de que URIs devem identificar recursos na rede para então podermos fazer valer as diversas vantagens estruturais que o protocolo HTTP nos proporciona, note o quão simples fica mapear os diversos métodos HTTP para a mesma URI, e com isso invocar diferentes métodos. Por exemplo, queremos usar as seguintes URIs para o cadastro de produtos: | GET | /produtos | lista todos os produtos | | POST | /produtos | adiciona um produto | | GET | /produtos/{id} | visualiza o produto com o id passado | | PUT | /produtos/{id} | atualiza as informações do produto com o id passado | | DELETE | /produtos/{id} | remove o produto com o id passado | {: .content-table} Para criar esse comportamento REST no VRaptor, podemos usar as anotações `@Path` - que muda qual é a URI que vai acessar o determinado método, e as anotações com os nomes dos métodos HTTP `@Get`, `@Post`, `@Delete`, `@Put`, que indicam que o método anotado só pode ser acessado se a requisição estiver com o método HTTP indicado. Então, uma versão REST do nosso `ProdutosController` seria: ~~~ #!java public class ProdutosController { //... @Get @Path("/produtos") public List lista() { ... } @Post("/produtos") public void adiciona(Produto produto) { ... } @Get("/produtos/{produto.id}") public void visualiza(Produto produto) { ... } @Put("/produtos/{produto.id}") public void atualiza(Produto produto) { ... } @Delete("/produtos/{produto.id}") public void remove(Produto produto) { ... } } ~~~ Note que podemos receber parâmetros nas URIs. Por exemplo, se chamarmos a URI `GET /produtos/5`, o método `visualiza` será invocado, e o parâmetro `produto` vai ter o `id` populado com `5`. Mais informações sobre isso no capítulo de [Controllers-REST](/pt/docs/controllers-rest). ##Arquivo de mensagens Internacionalização (i18n) é um recurso poderoso, e que está presente em quase todos os frameworks Web hoje em dia. E não é diferente no VRaptor. Com i18n podemos fazer com que nossa aplicação suporte várias línguas (francês, português, espanhol, inglês etc) de uma maneira que não nos cause muito esforço, bastando apenas fazermos a tradução das mensagens da nossa aplicação. Para isso, é só criarmos um arquivo chamado `messages.properties` e disponibilizá-lo no classpath da nossa aplicação (`WEB-INF/classes`). Esse arquivo conterá várias linhas compostas por um conjunto de chave/valor, como por exemplo: ~~~ #!jsp campo.nomeUsuario = Nome de Usuário campo.senha = Senha ~~~ Até então está fácil, mas e se quisermos criar esses arquivos para várias línguas, como por exemplo, inglês? Simples, basta criarmos um outro arquivo properties chamado `messages_en.properties`. Repare no sufixo `_en` no nome do arquivo. Isso indica que quando o usuário acessar sua aplicação em uma máquina configurada com locale em inglês as mensagens desse arquivo serão utilizadas. O conteúdo desse arquivo então ficaria: ~~~ #!jsp campo.nomeUsuario = Username campo.senha = Password ~~~ Repare que as chaves são mantidas, mudando apenas o valor para a língua escolhida. Para usar essas mensagens em seus arquivos JSP, você pode utilizar a JSTL. Dessa forma, o código ficaria: ~~~ #!jsp
~~~ ##Próximos passos Continue explorando as próximas seções desta documentação, os Cookbooks, com soluções de problemas comuns e o Livro de VRaptor pela editora Casa do Código. Se você tiver dúvidas, procure ajuda no GUJ ou na nossa lista de discussão.