vraptor3

download vraptor3

of 96

Transcript of vraptor3

VRaptor

http://vraptor.caelum.com.br

Automatically generated by Caelum Objects Tubaina 11 de abril de 2012

ndice

1 VRaptor3 - Guia de 1 minuto 1.1 Comeando um projeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Um Controller simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 VRaptor3 - o guia inicial de 10 minutos 2.1 Comeando o projeto: uma loja virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Um cadastro de produtos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Criando o ProdutoDao: injeo de Dependncias . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Formulrio de adio: redirecionamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Validao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 Usando o Hibernate para guardar os Produtos . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 1 1 4 4 4 6 7 8 9

2.7 Controlando transaes: Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.8 Carrinho de compras: Componentes na sesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.9 Um pouco de REST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.10 Arquivo de mensagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3 Resources-Rest 13

3.1 O que so Resources? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.2 Parmetros dos mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.3 Escopos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.4 @Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.5 Http Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.6 RoutesConguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

i

4 Componentes

21

4.1 O que so componentes? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.2 Escopos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.3 ComponentFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.4 Injeo de dependncias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5 Conversores 24

5.1 Padro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.2 Tipos primitivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.3 Wrappers de tipos primitivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.4 Enum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.5 BigInteger e BigDecimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5.6 BigDecimal, Double e Float localizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.7 Calendar e Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 5.8 LocalDate, LocalTime e LocalDateTime do joda-time . . . . . . . . . . . . . . . . . . . . . . . . . 25 5.9 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 5.10 Registrando um novo conversor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 6 Interceptadores 27

6.1 Para que interceptar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 6.2 Como interceptar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 6.3 Exemplo simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

6.4 Exemplo com Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 6.5 Como garantir ordem: after e before . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 6.6 Interagindo com os interceptors do VRaptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 7 Validao 31

7.1 Estilo clssico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 7.2 Estilo uente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 7.3 Validao com parmetros nas mensagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 7.4 Validao usando matchers do Hamcrest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 7.5 Bean Validation (JSR303) e Hibernate Validator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 7.6 Para onde redirecionar no caso de erro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 7.7 Atalhos no Validator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 7.8 L10N com o bundle do Localization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 7.9 Mostrando os erros de validao no JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 ii

8 View e Ajax

36

8.1 Compartilhando objetos com a view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 8.2 Custom PathResolver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 8.3 View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 8.4 Atalhos no Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 8.5 Redirecionamento e forward . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 8.6 Accepts e o parmetro _format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 8.7 Ajax: construindo na view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 8.8 Ajax: Verso programtica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 9 Injeo de dependncias 44

9.1 ComponentFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 9.2 Providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 9.3 Spring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 9.4 Google Guice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 9.5 Pico Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 10 Download e Upload 49

10.1 exemplo de 1 minuto: download . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 10.2 Adicionando mais informaes no download . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

10.3 Upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 10.4 exemplo de 1 minuto: upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 10.5 Mais sobre Upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 10.6 Sobrescrevendo as conguraes de upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 10.7 Alterando o formulrio de envio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 10.8 Validando o upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 11 Componentes Utilitrios Opcionais 52

11.1 Registrando um componente opcional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 11.2 Componentes opcionais disponveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 11.3 JPA EntityManager e EntityManagerFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 12 Conguraes avancadas: sobrescrevendo as convenes e comportamento do VRaptor 12.1 Mudando a view renderizada por padro 56

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

12.2 Mudando a URI padro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 12.3 Mudando o encoding da sua aplicao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 iii

13 Spring, Joda Time, Hibernate

58

13.1 Integrao com Hibernate ou JPA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 13.2 Integrao com Spring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 13.3 Conversores para Joda Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 14 Google App Engine 59

14.1 Comeando um projeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 14.2 Congurao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 14.3 Limitaes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 14.4 Problemas comuns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 14.5 JPA 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 15 Testando componentes e controllers 60

15.1 MockResult . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 15.2 MockValidator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 16 Scala 62

16.1 Dependncias e Congurao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 16.2 Exemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 17 Otimizaes 64

17.1 Commons Upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 17.2 Anotao @Lazy em Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 18 VRaptor Scaffold 65

18.1 Instalao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 18.2 Comeando um projeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 18.3 Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 18.4 Build: Maven, Gradle ou Ivy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

18.5 ORM: JPA ou Hibernate, connection pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 18.6 Freemarker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 18.7 Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 18.8 Tipos de atributos suportado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 18.9 Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 18.10 jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 18.11 Heroku . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 iv

18.12 Comando Help

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

18.13 Contribuindo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 19 Exception handling 20 Como contribuir com o VRaptor 69 70

20.1 Participando das listas de discusso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 20.2 Colaborando com documentao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

20.3 Reportando bugs e sugerindo novas funcionalidades . . . . . . . . . . . . . . . . . . . . . . . . . 70 20.4 Colaborando com cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 20.5 Montando o ambiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 21 ChangeLog 71

21.1 3.4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 21.2 3.4.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 21.3 3.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 21.4 3.3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 21.5 3.2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 21.6 3.1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 21.7 3.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 21.8 3.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 21.9 3.1.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 21.10 3.0.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 21.11 3.0.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 21.12 3.0.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 21.13 3.0.0-rc-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

21.14 3.0.0-beta-5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 21.15 3.0.0-beta-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 21.16 3.0.0-beta-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 22 Migrando do VRaptor2 para o VRaptor3 85

22.1 web.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 22.2 migrando de @org.vraptor.annotations.Component para @br.com.caelum.vraptor.Resource 22.3 @In . . . 85

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

22.4 @Out e getters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

v

22.5 views.properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 22.6 Validao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 22.7 Colocando objetos na sesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Version: 14.7.11

vi

C APTULO

1

VRaptor3 - Guia de 1 minutoO VRaptor 3 foca em simplicidade e, portanto, todas as funcionalidades que voc ver tm como primeira meta resolver o problema do programador da maneira menos intrusiva possvel em seu cdigo. Tanto para salvar, remover, buscar e atualizar ou ainda funcionalidades que costumam ser mais complexas como upload e download de arquivos, resultados em formatos diferentes (xml, json, xhtml etc), tudo isso feito atravs de funcionalidades simples do VRaptor 3, que sempre procuram encapsular HttpServletRequest, Response, Session e toda a API do javax.servlet.

1.1- Comeando um projetoVoc pode comear seu projeto a partir do vraptor-blank-project, que contem as dependncias necessrias e a congurao no web.xml. Ele pode ser baixado em http://vraptor.caelum.com.br/download. jsp . O projeto vraptor-blank-project congurado para a IDE Eclipse. Se voc usa Netbeans, possvel importar o projeto facilmente conforme a documentao disponvel em http://netbeans.org/kb/docs/java/ import-eclipse.html . Se voc utiliza a IDE IntelliJ IDEA voc pode importar o projeto seguindo o guia disponvel em http://www.jetbrains.com/idea/webhelp/importing-eclipse-project-to-intellij-idea.html . Se voc quiser usar o Maven, voc pode adicionar o artefato do VRaptor como dependncia no seu pom.xml:

br.com.caelum vraptor 3.2.0

1.2- Um Controller simplesChamaremos de Controller as classes contendo a lgica de negcio do seu sistema. So as classes que alguns frameworks podem vir a chamar de actions ou services, apesar de no signicarem exatamente a mesma coisa. Com o VRaptor congurado no seu web.xml, basta criar os seus controllers para receber as requisies e comear a construir seu sistema. Um controller simples seria:

/* * anotando seu controller com @Resource, seus mtodos pblicos ficaro disponveis * para receber requisies web. */ @Resource public class ClientsController {

1

Caelum VRaptor

private ClientDao dao; /* * Voc pode receber as dependncias da sua classe no construtor, e o VRaptor vai * se encarregar de criar ou localizar essas dependncias pra voc e us-las pra * criar o seu controller. Para que o VRaptor saiba como criar o ClientDao voc * deve anot-lo com @Component. */ public ClientsController(ClientDao dao) { this.dao = dao; } /* * Todos os mtodos pblicos do seu controller estaro acessveis via web. * Por exemplo, o mtodo form pode ser acessado pela URI /clients/form e * vai redirecionar para a jsp /WEB-INF/jsp/clients/form.jsp */ public void form() { // cdigo que carrega dados para checkboxes, selects, etc } /* * Voc pode receber parmetros no seu mtodo, e o VRaptor vai tentar popular os * campos dos parmetro de acordo com a requisio. Se houver na requisio: * custom.name=Lucas * custom.address=R.Vergueiro * ento teremos os campos name e address do Client custom estaro populados com * Lucas e R.Vergueiro via getters e setters * URI: /clients/add * view: /WEB-INF/jsp/clients/add.jsp */ public void add(Client custom) { dao.save(custom); } /* * O retorno do seu mtodo exportado para a view. Nesse caso, como o retorno * uma lista de clientes, a varivel acessvel no jsp ser ${clientList}. * URI: /clients/list * view: /WEB-INF/jsp/clients/list.jsp */ public List list() { return dao.listAll(): } /* * Se o retorno for um tipo simples, o nome da varivel exportada ser o nome da * classe com a primeira letra minscula. Nesse caso, como retornou um Client, a * varivel na jsp ser ${client}. * Devemos ter um parmetro da requisio id=5 por exemplo, e o VRaptor vai * fazer a converso do parmetro em Long, e passar como parmetro do mtodo. * URI: /clients/view * view: /WEB-INF/jsp/clients/view.jsp */ public Client view(Long id) { return dao.load(id); }

}

Captulo 1 - VRaptor3 - Guia de 1 minuto - Um Controller simples 2

Repare como essa classe est completamente independente da API de javax.servlet. O cdigo tambm est extremamente simples e fcil de ser testado como unidade. O VRaptor j faz vrias associaes para as URIs como default:

/client/form invoca form() /client/add invoca add(client) populando o objeto client com os parmetros da requisio /clients/list invoca list() e devolve ${clientList} ao JSP /clients/view?id=3 invoca view(3l) e devolve ${client} ao JSPMais para a frente veremos como fcil trocar a URI /clients/view?id=3 para /clients/view/3, deixando a URI mais elegante. O ClientDao ser injetado pelo VRaptor, como tambm veremos adiante. Voc j pode passar para o Guia inicial de 10 minutos.

C APTULO

2

VRaptor3 - o guia inicial de 10 minutos2.1- Comeando o projeto: uma loja virtualVamos comear baixando o vraptor-blank-project, do site http://vraptor.caelum.com.br/download.jsp . Esse blank-project j possui a congurao no web.xml e os jars no WEB-INF/lib necessrios para comear a desenvolver no VRaptor. Como voc pode ver, a nica congurao necessria no web.xml o ltro do VRaptor:

vraptor br.com.caelum.vraptor.VRaptor vraptor /* FORWARD REQUEST Voc pode facilmente importar esse projeto no Eclipse, e roda-lo clicando com o boto da direita e escolhendo Run as... / Run on server.... Escolha ento um servlet container (ou faa o setup de um novo) e ento acesse http://localhost:8080/vraptor-blank-project/. Voc pode escolher, nas propriedades do projetor, dentro de Web Project Settings, o nome do contexto para algo melhor, como onlinestore. Agora se voc rodar esse exemplo deve ser possvel acessar http://localhost: 8080/onlinestore e ver It works! no navegador. Nota Se voc est usando um container de servlet 3.0 (java EE 6), voc nem precisa de web.xml, pois o VRaptor vai congurar esse ltro atravs do novo recurso de web-fragments.

2.2- Um cadastro de produtosPara comear o sistema, vamos comear com cadastro de produtos. Precisamos de uma classe que vai representar o produto, e vamos us-la para guardar produtos no banco, usando o Hibernate:

@Entity public class Produto { @Id @GeneratedValue private Long id;4

Caelum VRaptor

private String nome; private String descricao; private Double preco; } // getter e setters e mtodos de negcio que julgar necessrio

Precisamos tambm de uma classe que vai controlar o cadastro de produtos, tratando requisies web. Essa classe vai ser o Controller de produtos:

public class ProdutosController { }A classe ProdutosController vai expor URIs para serem acessadas via web, ou seja, vai expor recursos da sua aplicao. E para indicar isso, voc precisa anot-la com com @Resource:

@Resource public class ProdutosController { }Ao colocar essa anotao na classe, todos os mtodos pblicos dela sero acessveis via web. Por exemplo, se tivermos um mtodo lista na classe:

@Resource public class ProdutosController { public List lista() { return new ArrayList(); } }o VRaptor automaticamente redireciona todas as requisies URI /produtos/lista para esse mtodo. Ou seja, a conveno para a criao de URIs // Nome:
Descrio:
Preo:
O formulrio vai salvar o Produto pela URI /produtos/adiciona, ento precisamos criar esse mtodo no nosso controller:

@Resource public class ProdutosController { //... public void adiciona() { } }Repare nos nomes dos nossos inputs: produto.nome, produto.descricao e produto.preco. Se recebermos um Produto no mtodo 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 captulo de converters. Ento, usando os nomes corretamente nos inputs do form, basta criar seu mtodo adiciona:

@Resource public class ProdutosController { //... public void adiciona(Produto produto) { dao.adiciona(produto); }

Captulo 2 - VRaptor3 - o guia inicial de 10 minutos - Formulrio de adio: redirecionamento 7

Caelum VRaptor

}Geralmente depois de adicionar algo no sistema queremos voltar para a sua listagem, ou para o formulrio 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 responsvel por adicionar atributos na requisio, e por mudar a view a ser carregada. Se eu quiser uma instncia de Result, basta receb-lo no construtor:

@Resource public class ProdutosController { public ProdutosController(ProdutoDao dao, Result result) { this.dao = dao; this.result = result; } }E para redirecionar para a listagem basta usar o result:

result.redirectTo(ProdutosController.class).lista();Podemos ler esse cdigo como: Como resultado, redirecione para o mtodo lista do ProdutosController. A congurao de redirecionamento 100% java, sem strings envolvidas! Fica explcito no seu cdigo que o resultado da sua lgica no o padro, e qual resultado voc est usando! Voc no precisa car se preocupando com arquivos de congurao! Mais ainda, se eu quiser mudar o nome do mtodo lista, eu no preciso car rodando o sistema inteiro procurando onde esto redirecionando pra esse mtodo, basta usar o refactor do eclipse, por exemplo, e tudo continua funcionando! Ento nosso mtodo adiciona caria:

public void adiciona(Produto produto) { dao.adiciona(produto); result.redirectTo(ProdutosController.class).lista(); }Mais informaes sobre o Result no captulo Views e Ajax.

2.5- ValidaoNo faz muito sentido adicionar um produto sem nome no sistema, nem um produto com preo negativo. Antes de adicionar o produto, precisamos vericar se um produto vlido, com nome e preo positivo, e caso no seja vlido voltamos para o formulrio com mensagens de erro. Para fazermos isso, podemos usar um componente do VRaptor: o Validator. Voc pode receb-lo no construtor do seu Controller, e us-lo da seguinte maneira:

@Resource public class ProdutosController { public ProdutosController(ProdutoDao dao, Result result, Validator validator) { //... this.validator = validator; } public void adiciona(Produto produto) {Captulo 2 - VRaptor3 - o guia inicial de 10 minutos - Validao 8

Caelum VRaptor

validator.checking(new Validations() {{ that(!produto.getNome().isEmpty(), "produto.nome", "nome.vazio"); that(produto.getPreco() > 0, "produto.preco", "preco.invalido"); }}); validator.onErrorUsePageOf(ProdutosController.class).form(); dao.adiciona(produto); result.redirectTo(ProdutosController.class).lista();

}

}

Podemos ler as validaes da seguinte maneira: Valide que o nome do produto no vazio e que o preo do produto maior que zero. Se acontecer um erro, use como resultado a pgina do form do ProdutosController. Ou seja, se por exemplo o nome do produto for vazio, vai ser adicionada a mensagem de erro para o campo produto.nome, com a mensagem nome.vazio internacionalizada. Se acontecer algum erro, o sistema vai voltar pra pgina do formulrio, com os campos preenchidos e com mensagens de erro que podem ser acessadas da seguinte maneira:

${error.category} ${error.message}
Mais informaes sobre o Validator no captulo de Validaes. Com o que foi visto at agora voc j consegue fazer 90% da sua aplicao! As prximas sesses desse tutorial mostram a soluo para alguns problemas frequentes que esto nos outros 10% da sua aplicao.

2.6- Usando o Hibernate para guardar os ProdutosAgora vamos fazer uma implementao de verdade do ProdutoDao, usando o Hibernate para persistir os produtos. Para isso nosso ProdutoDao precisa de uma Session. Como o VRaptor usa injeo de dependncias, basta receber uma Session no construtor!

@Component public class ProdutoDao { private Session session; public ProdutoDao(Session session) { this.session = session; } public void adiciona(Produto produto) { session.save(produto); } //...

}

Mas pera, para o VRaptor precisa saber como criar essa Session, e eu no posso simplesmente colocar um @Component na Session pois uma classe do Hibernate! Para isso existe a interface ComponentFactory, que voc pode usar pra criar uma Session. Mais informaes de como fazer ComponentFactories no captulo de Componentes. Voc pode ainda usar os ComponentFactories que j esto disponveis para isso no VRaptor, como mostra o captulo de Utils.Captulo 2 - VRaptor3 - o guia inicial de 10 minutos - Usando o Hibernate para guardar os Produtos 9

Caelum VRaptor

2.7- Controlando transaes: InterceptorsMuitas vezes queremos interceptar todas as requisies (ou uma parte delas) e executar alguma lgica, como acontece com o controle de transaes. Para isso existem os Interceptors no VRaptor. Saiba mais sobre eles no captulo de Interceptors. Existe um TransactionInterceptor j implementado no VRaptor, saiba como us-lo no captulo de Utils.

2.8- Carrinho de compras: Componentes na sessoSe quisermos criar um carrinho de compras no nosso sistema, precisamos de alguma forma manter os itens do carrinho na Sesso do usurio. Para fazer isso, podemos criar um componente que est no escopo de sesso, ou seja, ele vai ser nico na sesso do usurio. Para isso basta criar um componente anotado com @SessionScoped:

@Component @SessionScoped public class CarrinhoDeCompras { private List itens = new ArrayList(); public List getTodosOsItens() { return itens; } public void adicionaItem(Produto item) { itens.add(item); }

}

Como esse carrinho de compras um componente, podemos receb-lo no construtor do controller que vai cuidar do carrinho de compras:

@Resource public class CarrinhoController { private final CarrinhoDeCompras carrinho; public CarrinhoController(CarrinhoDeCompras carrinho) { this.carrinho = carrinho; } public void adiciona(Produto produto) { carrinho.adicionaItem(produto); } public List listaItens() { return carrinho.getTodosOsItens(); }

}

Alm do escopo de sesso existe o escopo de Aplicao com a anotao @ApplicationScoped. Os componentes anotados com @ApplicationScoped sero criados apenas uma vez em toda a aplicao.

Captulo 2 - VRaptor3 - o guia inicial de 10 minutos - Controlando transaes: Interceptors 10

Caelum VRaptor

2.9- Um pouco de RESTSeguindo a idia REST de que URIs devem identicar recursos na rede para ento podermos fazer valer as diversas vantagens estruturais que o protocolo HTTP nos proporciona, note o quo simples ca mapear os diversos mtodos HTTP para a mesma URI, e com isso invocar diferentes mtodos, 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 informaes do produto com o id passado DELETE /produtos/{id} - remove o produto com o id passadoPara criar esse comportamento REST no VRaptor podemos usar as anotaes @Path - que muda qual a uri que vai acessar o determinado mtodo, e as anotaes com os nomes dos mtodos HTTP @Get, @Post, @Delete, @Put, que indicam que o mtodo anotado s pode ser acessado se a requisio estiver com o mtodo HTTP indicado. Ento uma verso REST do nosso ProdutosController seria:

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 parmetros nas URIs. Por exemplo se chamarmos a URI GET /produtos/5, o mtodo visualiza ser invocado, e o parmetro produto vai ter o id populado com 5. Mais informaes sobre isso no captulo de Resources-REST.

2.10- Arquivo de mensagensInternacionalizao (i18n) um recurso poderoso, e que est presente em quase todos os frameworks Web hoje em dia. E no diferente no VRaptor3. Com i18n podemos fazer com que nossa aplicao suporte vrias lnguas (francs, portugus, espanhol, ingls, etc) de uma maneira que no nos cause muito esforo, bastando apenas fazermos a traduo das mensagens da nossa aplicao. Para isso s criarmos um arquivo chamado messages.properties e disponibiliz-lo no classpath da nossa aplicao (WEB-INF/classes). O contedo desse arquivo so vrias linhas compostas por um conjunto de chaves/valor, como por exemplo:

Captulo 2 - VRaptor3 - o guia inicial de 10 minutos - Um pouco de REST 11

campo.nomeUsuario = Nome de Usurio campo.senha = SenhaAt ento est fcil, mas e se quisermos criar esses arquivos para vrias lnguas, como por exemplo, ingls? Simples, basta criarmos um outro arquivo properties chamado messages_en.properties. Repare no suxo _en no nome do arquivo. Isso indica que quando o usurio acessar sua aplicao atravs de uma mquina congurada com locale em ingls as mensagens desse arquivo sero utilizadas. O contedo desse arquivo ento caria:

campo.nomeUsuario = Username campo.senha = PasswordRepare que as chaves so mantidas, mudando apenas o valor para a lngua escolhida. Para usar essas mensagens em seus arquivos JSP, voc pode utilizar a JSTL. Dessa forma, o cdigo caria:


C APTULO

3

Resources-Rest3.1- O que so Resources?Resources so o que poderamos pensar como recursos a serem disponibilizados para acesso pelos nossos clientes. No caso de uma aplicao Web baseada no VRaptor, um recurso deve ser anotado com a anotao @Resource. Assim que o programador insere tal anotao em seu cdigo, todos os mtodos pblicos desse recurso se tornam acessveis atravs de chamadas do tipo GET a URIs especcas. O exemplo a seguir mostra um recurso chamado ClienteController que possui mtodos para diversas funcionalidades ligadas a um cliente. Simplesmente criar essa classe e os mtodos faz com que as urls /cliente/adiciona, /cliente/lista, /cliente/visualiza, /cliente/remove e /cliente/atualiza sejam disponibilizadas, cada uma invocando o respectivo mtodo em sua classe.

@Resource public class ClienteController { public void adiciona(Cliente cliente) { } public List lista() { return ... } public Cliente visualiza(Cliente perfil) { return ... } public void remove(Cliente cliente) { ... } public void atualiza(Cliente cliente) { ... } }

3.2- Parmetros dos mtodosVoc pode receber parmetros nos mtodos dos seus controllers, e se o objeto usar a conveno de java 13

Caelum VRaptor

beans (getters e setters para os atributos da classe), voc pode usar pontos para navegar entre os atributos. Por exemplo, no mtodo:

public void atualiza(Cliente cliente) { //... }voc pode passar como parmetro na requisio:

cliente.id=3 cliente.nome=Fulano cliente.usuario.login=fulanoe os campos correspondentes, navegando via getters e setters a partir do cliente, sero setados. Se um atributo do objeto ou parmetro do mtodo for uma lista (List ou array), voc pode passar vrios parmetros usando colchetes e ndices:

cliente.telefones[0]=(11) 5571-2751 #no caso de ser uma lista de String cliente.dependentes[0].id=1 #no caso de ser qualquer objeto, voc pode continuar a navegao cliente.dependentes[3].id=1 #os ndices no precisam ser sequenciais cliente.dependentes[0].nome=Cicrano #se usar o mesmo ndice, vai ser setado no mesmo objeto clientes[1].id=23 #funciona se voc receber uma lista de clientes no mtodoReection no nome dos parmetros Infelizmente, o Java no realiza reection em cima de parmetros, esses dados no cam disponveis em bytecode (a no ser se compilado em debug mode, porm algo opcional). Isso faz com que a maioria dos frameworks que precisam desse tipo de informo criem uma anotao prpria para isso, o que polui muito o cdigo (exemplo no JAX-WS, onde comum encontrar um mtodo como o acima com a assinatura void add(@WebParam(name="cliente) Cliente cliente). O VRaptor tira proveito do framework Paranamer (http://paranamer.codehaus.org), que consegue tirar essa informao atravs de pr compilao ou dos dados de debug, evitando criar mais uma anotao. Alguns dos desenvolvedores do VRaptor tambm participam no desenvolvimento do Paranamer.

3.3- EscoposPor vezes voc deseja compartilhar um componente entre todos os usurios, entre todas as requisies de um mesmo usurio ou a cada requisio de um usurio. Para denir em que escopo o seu componente vive, basta utilizar as anotaes @ApplicationScoped, @SessionScoped e @RequestScoped. Caso nenhuma anotao seja utilizada, o VRaptor assume que seu componente car no escopo de request, isto , voc ter um novo componente a cada nova requisio.

Captulo 3 - Resources-Rest - Escopos 14

Caelum VRaptor

3.4- @PathA anotao @Path permite que voc customize as URIs de acesso a seus mtodos. O uso bsico dessa anotao feito atravs de uma URI xa. O exemplo a seguir mostra a customizao de uma URI para um mtodo, que somente receber requisies do tipo POST na URI /cliente:

@Resource public class ClienteController { @Path("/cliente") @Post public void adiciona(Cliente cliente) { } }Se voc anotar o ClienteController com @Path, o valor especicado vai ser usado como prexo para todas as URIs desse controller:

@Resource @Path("/clientes") public class ClienteController { //URI: /clientes/lista public void lista() {...} //URI: /clientes/salva @Path("salva") public void adiciona() {...} //URI: /clientes/todosOsClientes @Path("/todosOsClientes") public void listaTudo() {...}

}

3.5- Http MethodsO ideal denir uma URI especca para diversos mtodos HTTP diferentes, como GET, POST, PUT etc. Para atingir esse objetivo, utilizamos as anotaes @Get, @Post, @Delete etc que tambm permitem congurar uma URI diferente da URI padro, da mesma forma que a anotao @Path. O exemplo a seguir altera os padres de URI do ClienteController para utilizar duas URIs distintas, com diversos mtodos HTTP:

@Resource public class ClienteController { @Post("/cliente") public void adiciona(Cliente cliente) { } @Path("/") public List lista() { return ...Captulo 3 - Resources-Rest - @Path 15

Caelum VRaptor

} @Get("/cliente") public Cliente visualiza(Cliente cliente) { return ... } @Delete("/cliente") public void remove(Cliente cliente) { ... } @Put("/cliente") public void atualiza(Cliente cliente) { ... } }Como voc pode notar, utilizamos os mtodos HTTP + uma URI especca para identicar cada um dos mtodos de minha classe Java. No momento de criar os links e formulrios HTML devemos tomar um cuidado muito importante pois os browsers s do suporte aos mtodos POST e GET atravs de formulrios hoje em dia. Por isso, voc dever criar as requisies para mtodos do tipo DELETE, PUT etc atravs de JavaScript ou passando um parmetro extra, chamado _method. O ltimo s funciona em requisies POST. Esse parmetro sobrescrever o mtodo HTTP real sendo invocado. O exemplo a seguir mostra um link para o mtodo visualiza de cliente:

ver cliente 5Agora um exemplo de como invocar o mtodo de adicionar um cliente:

E, note que para permitir a remoo atravs do mtodo DELETE, temos que usar o parmetro _method, uma vez que o browser no suporta ainda tais requisies:

remover cliente 5

Paths com expresses regularesVoc pode restringir o valor dos parmetros da sua URI com expresses regulares, dessa maneira:

@Path("/cor/{cor:[0-9A-Fa-f]{6}}") public void setCor(String cor) { //... }

Captulo 3 - Resources-Rest - Http Methods 16

Caelum VRaptor

Tudo que estiver depois do : ser tratado como uma regex, e a URI s vai casar se o parmetro casar com a regex:

/cor/a0b3c4 => casa /cor/AABBCC => casa /cor/branco => no casa

Path com injeo de variveisEm diversos casos desejamos que a uri que identica meu recurso tenha como parte de seu valor, por exemplo, o identicador nico de meu recurso. Suponha o exemplo de um controle de clientes onde meu identicador nico (chave primria) um nmero, podemos ento mapear as uris /cliente/{cliente.id} para a visualizao de cada cliente. Isto , se acessarmos a uri /cliente/2, o mtodo visualiza ser invocado e o parmetro cliente.id ser setado para 2. Caso a uri /cliente/1717 seja acessada, o mesmo mtodo ser invocado com o valor 1717. Dessa maneira criamos uris nicas para identicar recursos diferentes do nosso sistema. Veja o exemplo citado:

@Resource public class ClienteController { @Get @Path("/cliente/{cliente.id}") public Cliente visualiza(Cliente cliente) { return ... } }Voc pode ir alm e setar diversos parmetros atravs da uri:

@Resource public class ClienteController { @Get @Path("/cliente/{cliente.id}/visualiza/{secao}") public Cliente visualiza(Cliente cliente, String secao) { return ... } }

Vrios paths para a mesma lgicaVoc pode setar mais de um path pra mesma lgica fazendo:

@Resource public class ClienteController { @Path({"/cliente/{cliente.id}/visualiza/{secao}", "/cliente/{cliente.id}/visualiza/"})Captulo 3 - Resources-Rest - Http Methods 17

Caelum VRaptor

public Cliente visualiza(Cliente cliente, String secao) { return ... } }

Paths com *Voc tambm pode utilizar o * como mtodo de seleo para a sua uri. O exemplo a seguir ignora qualquer coisa aps a palavra foto/ :

@Resource public class ClienteController { @Get @Path("/cliente/{cliente.id}/foto/*") public File foto(Cliente cliente) { return ... } }E agora o mesmo cdigo, mas utilizado para baixar uma foto especca de um cliente:

@Resource public class ClienteController { @Get @Path("/cliente/{cliente.id}/foto/{foto.id}") public File foto(Cliente cliente, Foto foto) { return ... } }Por vezes voc deseja que o parmetro a ser setado inclua tambm /s. Para isso voc deve utilizar o padro {...*}:

@Resource public class ClienteController { @Get @Path("/cliente/{cliente.id}/download/{path*}") public File download(Cliente cliente, String path) { return ... } }

Denindo prioridades para seus paths possvel que algumas das nossas URIs possa ser tratada por mais de um mtodo da classe:Captulo 3 - Resources-Rest - Http Methods 18

Caelum VRaptor

@Resource public class PostController { @Get @Path("/post/{post.autor}") public void mostra(Post post) { ... } @Get @Path("/post/atual") public void atual() { ... }

}

A uri /post/atual pode ser tratada tanto pelo mtodo mostra, quanto pelo atual. Mas eu quero que quando seja exatamente /post/atual o mtodo executado seja o atual. O que eu quero que o VRaptor teste primeiro o path do mtodo atual, para no correr o risco de cair no mtodo mostra. Para fazer isso, podemos denir prioridades para os @Paths, assim o VRaptor vai testar primeiro os paths com maior prioridade, ou seja, valor menor de prioridade:

@Resource public class PostController { @Get @Path(value = "/post/{post.autor}", priority=Path.LOW) public void mostra(Post post) { ... } @Get @Path(value = "/post/atual", priority=Path.HIGH) public void atual() { ... }

}

Assim, o path /post/atual vai ser testado antes do /post/{post.autor}, e o VRaptor vai fazer o que a gente gostaria que ele zesse. Voc no precisa denir prioridades se tivermos as uris: /post/{post.id} e /post/atual, pois na /post/{post.id} o vraptor s vai aceitar nmeros.

3.6- RoutesCongurationPor m, a maneira mais avanada de congurar rotas de acesso aos seus recursos atravs de um RoutesConguration. Esse componente deve ser congurado no escopo de aplicao e implementar o mtodo cong:

@Component @ApplicationScoped public class CustomRoutes implements RoutesConfiguration { public void config(Router router) { } }De posse de um Router, voc pode denir rotas para acesso a mtodos e, o melhor de tudo, que a

Captulo 3 - Resources-Rest - RoutesConguration 19

congurao refactor-friendly, isto , se voc alterar o nome de um mtodo, a congurao tambm altera, mas mantem a mesma uri :

@Component @ApplicationScoped public class CustomRoutes implements RoutesConfiguration { public void config(Router router) { new Rules(router) { public void routes() { routeFor("/").is(ClienteController.class).list(); routeFor("/cliente/random").is(ClienteController.class).aleatorio(); } }; } }Voc pode tambm colocar parmetros na uri e eles vo ser populados diretamente nos parmetros do mtodo. Voc pode ainda adicionar restries para esses parmetros:

// O mtodo mostra recebe um Cliente que tem um id routeFor("/cliente/{cliente.id}").is(ClienteController.class).mostra(null); // Se eu quiser garantir que o parametro seja um nmero: routeFor("/cliente/{cliente.id}").withParameter("cliente.id").matching("\\d+") .is(ClienteController.class).mostra(null);

C APTULO

4

Componentes4.1- O que so componentes?Componentes so instncias de classes que seu projeto precisa para executar tarefas ou armazenar estados em diferentes situaes. Exemplos clssicos de uso de componentes seriam os Daos, enviadores de email etc. A sugesto de boa prtica indica sempre criar uma interface para seus componentes. Dessa maneira seu cdigo tambm ca mais fcil de testar unitariamente. O exemplo a seguir mostra um componente a ser gerenciado pelo vraptor:

@Component public class ClienteDao { private final Session session; public ClienteDao(Session session) { this.session = session; } public void adiciona(Cliente cliente) { session.save(cliente); } }

4.2- EscoposAssim como os recursos, os componentes vivem em um escopo especco e seguem as mesmas regras, por padro pertencendo ao escopo de requisico, isto , a cada nova requisio seu componente ser novamente instanciado. O exemplo a seguir mostra o fornecedor de conexoes com o banco baseado no hibernate. Esse fornecedor esta no escopo de aplicacao, portanto ser instanciado somente uma vez por contexto:

@ApplicationScoped @Component public class HibernateControl { private final SessionFactory factory; public HibernateControl() { this.factory = new AnnotationConfiguration().configure().buildSessionFactory(); } public Session getSession() { return factory.openSession();21

Caelum VRaptor

} }Os escopos implementados so:

@RequestScoped - o componente o mesmo durante uma requisio @SessionScoped - o componente o mesmo durante uma http session @ApplicationScoped - component um singleton, apenas um por aplicao @PrototypeScoped - component instanciado sempre que requisitado.

4.3- ComponentFactoryMuitas vezes voc quer receber como dependncia da sua classe alguma classe que no do seu projeto, como por exemplo uma Session do hibernate ou um EntityManager da JPA. Para poder fazer isto, basta criar um ComponentFactory:

@Component public class SessionCreator implements ComponentFactory { private final SessionFactory factory; private Session session; public SessionCreator(SessionFactory factory) { this.factory = factory; } @PostConstruct public void create() { this.session = factory.openSession(); } public Session getInstance() { return session; } @PreDestroy public void destroy() { this.session.close(); } }Note que voc pode adicionar os listeners @PostConstruct e @PreDestroy para controlar a criao e destruio dos recursos que voc usa. Isso funciona para qualquer componente que voc registrar no VRaptor.

4.4- Injeo de dependnciasO VRaptor utiliza um de seus provedores de injeo de dependncias para controlar o que necessrio para instanciar cada um de seus componentes e recursos.

Captulo 4 - Componentes - ComponentFactory 22

Sendo assim, os dois exemplos anteriores permitem que qualquer um de seus recursos ou componentes receba um ClienteDao em seu construtor, por exemplo:

@Resource public class ClienteController { private final ClienteDao dao; public ClienteController(ClienteDao dao) { this.dao = dao; } @Post public void adiciona(Cliente cliente) { this.dao.adiciona(cliente); } }

C APTULO

5

Conversores5.1- PadroPor padro o VRaptor j registra diversos conversores para o seu uso no dia a dia.

5.2- Tipos primitivosTodos os tipos primitivos (int, long etc) so suportados. Caso o parametro da requisio seja nulo ou a string vazia, variveis de tipo primitivo sero alterados para o valor padro como se essa varivel fosse uma varivel membro, isto :

boolean - false short, int, long, double, oat, byte - 0 char - caracter de cdigo 0

5.3- Wrappers de tipos primitivosTodos os wrappers dos tipos primitivos (Integer, Long, Character, Boolean etc) so suportados.

5.4- EnumTodas as enumeraes so suportadas atravs do nome do elemento ou de seu ordinal. No exemplo a seguir, tanto o valor 1 como o valor DEBITO so traduzidos para Tipo.DEBITO:

public enum Tipo { CREDITO, DEBITO }

5.5- BigInteger e BigDecimalAmbos so suportados utilizando o padro de localizao da virtual machine que serve a sua aplicao.

5.6- BigDecimal, Double e Float localizadosA partir da verso 3.1.2 o VRaptor suporta esses tipos baseados na localizao da virtual machine. Para ativar esses componentes necessrio adicionar as seguintes linhas no seu web.xml:

br.com.caelum.vraptor.packages 24

Caelum VRaptor

...valor anterior..., br.com.caelum.vraptor.converter.l10n A localizao dos componentes pode ser alterada utilizando a seguinte congurao no web.xml:

javax.servlet.jsp.jstl.fmt.locale pt_BR

5.7- Calendar e DateLocaleBasedCalendarConverter e LocaleBasedDateConverter utilizam o locale do usurio, denido seguindo o padro do jstl para entender a formatao que foi utilizada no parmetro. Por exemplo, se o locale pt-br, o formato 18/09/1981 representa 18 de setembro de 1981 enquanto para o locale en, o formato 09/18/1981 representa a mesma data.

5.8- LocalDate, LocalTime e LocalDateTime do joda-timeExistem conversores para esses dois tipos no VRaptor e eles s sero carregados se voc tiver o jodatime.jar no seu classpath

5.9- InterfaceTodos os conversores devem implementar a interface Converter do vraptor. A classe concreta denir o tipo que ela capaz de converter, e ser invocada com o valor do parmetro do request, o tipo alvo e um bundle com as mensagens de internacionalizao para que voc possa retornar uma ConversionException no caso de algum erro de converso.

public interface Converter { T convert(String value, Class result.use(page()).forward(/some/uri); result.redirectTo(/some/uri) ==> result.use(page()).redirect(/some/uri) result.permanentlyRedirectTo(/some/uri) ==> result.use(status()).movedPermanentlyTo(/some/uri); result.forwardTo(ClientController.class).list() ==> result.use(logic()).forwardTo(ClientController.class).list(); result.redirectTo(ClientController.class).list() ==> result.use(logic()).redirectTo(ClientController.class).list(); result.of(ClientController.class).list() ==> result.use(page()).of(ClientController.class).list(); result.permanentlyRedirectTo(Controller.class) ==> use(status()).movedPermanentlyTo(Controller.class); result.notFound() ==> use(status()).notFound() result.nothing() ==> use(nothing());Alm disso, se o redirecionamento para um mtodo do mesmo controller, podemos usar:

result.forwardTo(this).list() ==> result.use(logic()).forwardTo(this.getClass()).list(); result.redirectTo(this).list() ==> result.use(logic()).redirectTo(this.getClass()).list(); result.of(this).list() ==> result.use(page()).of(this.getClass()).list(); result.permanentlyRedirectTo(this) ==> use(status()).movedPermanentlyTo(this.getClass());

8.5- Redirecionamento e forwardNo VRaptor3, podemos tanto realizar um redirect ou um forward do usurio para uma outra lgica ou um jsp. Apesar de serem conceitos da API de Servlets, vale a pena relembrar a diferena: o redirecionamento acontece no lado do cliente, atravs de cdigos HTTP que faro o browser acessar uma nova URL; j o forward acontece no lado do servidor, totalmente transparente para o cliente/browser. Um bom exemplo de uso do redirect no chamado redirect-after-post. Por exemplo: quando voc adiciona um cliente e que, aps o formulrio submetido, o cliente seja retornado para a pgina de listagem de clientes. Fazendo isso com redirect, impedimos que o usurio atualize a pgina (F5) e reenvie toda a requisio, acarretando em dados duplicados.

Captulo 8 - View e Ajax - Atalhos no Result 38

Caelum VRaptor

No caso do forward, um exemplo de uso quando voc possui uma validao e essa validao falhou, geralmente voc quer que o usurio continue na mesma tela do formulrio com os dados da requisio preenchidos, mas internamente voc vai fazer o forward para outra lgica de negcios (a que prepara os dados necessrios para o formulrio). Escopo Flash automtico Se voc adicionar objetos no Result e zer um Redirect, esses objetos estaro disponveis na prxima requisio.

public void adiciona(Cliente cliente) { dao.adiciona(cliente); result.include("mensagem", "Cliente adicionado com sucesso"); result.redirectTo(ClientesController.class).lista();

}

lista.jsp:

... ${mensagem} ...

8.6- Accepts e o parmetro _formatMuitas vezes precisamos renderizar formatos diferentes para uma mesma lgica. Por exemplo queremos retornar um JSON, ao invs de um HTML. Para fazer isso, podemos denir o Header Accepts da requisio para que aceite o tipo desejado, ou colocar um parmetro _format na requisio. Se o formato for JSON, a view renderizada por padro ser: /WEB-INF/jsp/{controller}/{logic}.json.jsp, ou seja, em geral ser renderizada a view: /WEB-INF/jsp/{controller}/{logic}.{formato}.jsp. Se o formato for HTML voc no precisa coloc-lo no nome do arquivo. O parmetro _format tem prioridade sobre o header Accepts.

8.7- Ajax: construindo na viewPara devolver um JSON na sua view, basta que sua lgica disponibilize o objeto para a view, e dentro da view voc forme o JSON como desejar. Como no exemplo, o seu /WEB-INF/jsp/clients/load.json.jsp:

{ nome: '${client.name}', id: '${client.id}' }E na lgica:

@Resource public class ClientsController { private final Result result; private final ClientDao dao;

Captulo 8 - View e Ajax - Accepts e o parmetro _format 39

Caelum VRaptor

public ClientsController(Result result, ClientDao dao) { this.result = result; this.dao = dao; } public void load(Client client) { result.include("client", dao.load(client)); }

}

8.8- Ajax: Verso programticaSe voc quiser que o VRaptor serialize automaticamente seus objetos para xml ou json, voc pode escrever em sua lgica:

import static br.com.caelum.vraptor.view.Results.*; @Resource public class ClientsController { private final Result result; private final ClientDao dao; public ClientsController(Result result, ClientDao dao) { this.result = result; this.dao = dao; } public void loadJson(Cliente cliente) { result.use(json()).from(cliente).serialize(); } public void loadXml(Cliente cliente) { result.use(xml()).from(cliente).serialize(); }

}

Os resultados vos ser parecidos com:

{"cliente": { "nome": "Joao" }} Joao Por padro, apenas campos de tipos primitivos sero serializados (String, nmeros, enums, datas), se voc quiser incluir um campo de tipo no primitivo voc precisa inclu-lo explicitamente:

result.use(json()).from(cliente).include("endereco").serialize();vai resultar em algo parecido com:

Captulo 8 - View e Ajax - Ajax: Verso programtica 40

Caelum VRaptor

{"cliente": { "nome": "Joao", "endereco" { "rua": "Vergueiro" } }}Voc pode tambm excluir os campos de tipo primitivo da serializao:

result.use(json()).from(usuario).exclude("senha").serialize();vai resultar em algo parecido com:

{"usuario": { "nome": "Joao", "login": "joao" }}Ou ainda voc pode serializar recursivamente (cuidado com ciclos):

result.use(json()).from(usuario).recursive().serialize(); result.use(xml()).from(usuario).recursive().serialize();A implementao padro baseada no XStream, ento possvel congurar a serializao via anotaes ou conguraes diretas ao XStream, bastando criar a classe:

@Component public class CustomXMLSerialization extends XStreamXMLSerialization { //or public class CustomJSONSerialization extends XStreamJSONSerialization { //delegate constructor @Override protected XStream getXStream() { XStream xStream = super.getXStream(); //suas configuraes ao XStream aqui return xStream; }

}

Serializando CollectionsAo serializar colees, o padro colocar a tag list em volta dos elementos:

List clientes = ...; result.use(json()).from(clientes).serialize(); //ou result.use(xml()).from(clientes).serialize();vai resultar em algo como:

Captulo 8 - View e Ajax - Ajax: Verso programtica 41

Caelum VRaptor

{"list": [ { "nome": "Joao" }, { "nome": "Maria" } ]}ou

Joao Maria possvel personalizar o elemento de fora usando o mtodo:

List clientes = ...; result.use(json()).from(clientes, "clientes").serialize(); //ou result.use(xml()).from(clientes, "clientes").serialize();vai resultar em algo como:

{"clientes": [ { "nome": "Joao" }, { "nome": "Maria" } ]}ou

Joao Maria Os includes e excludes funcionam como se voc os estivesse aplicando num elemento de dentro da lista. Por exemplo se voc quiser incluir o endereo no cliente:

List clientes = ...; result.use(json()).from(clientes).include("endereco").serialize();com resultado:Captulo 8 - View e Ajax - Ajax: Verso programtica 42

{"list": [ { "nome": "Joao", "endereco": { "rua": "Vergueiro, 3185" } }, { "nome": "Maria", "endereco": { "rua": "Vergueiro, 3185" } } ]}

Serializando JSON sem elemento razSe voc quiser serializar um objeto em JSON sem dar nomes a eles, pode fazer isso com o mtodo withoutRoot:

result.use(json()).from(carro).serialize(); //=> {'carro': {'cor': 'azul'}} result.use(json()).withoutRoot().from(carro).serialize(); //=> {'cor': 'azul'}

C APTULO

9

Injeo de dependnciasO VRaptor est fortemente baseado no conceito de injeo de dependncias uma vez que chega at mesmo a utilizar dessa idia para juntar seus componentes internos. O conceito bsico por trs de Dependency Injection (DI) que voc no deve buscar aquilo que deseja acessar mas tudo o que deseja acessar deve ser fornecido para voc. Isso se traduz, por exemplo, na passagem de componentes atravs do construtor de seus controladores. Imagine que seu controlador de clientes necessita acessar um Dao de clientes. Sendo assim, especique claramente essa necessidade:

@Resource public class ClienteController { private final ClienteDao dao; public ClienteController(ClienteDao dao) { this.dao = dao; } @Post public void adiciona(Cliente cliente) { this.dao.adiciona(cliente); } }E anote tambm o componente ClienteDao como sendo controlado pelo vraptor:

@Component public class ClienteDao { }A partir desse instante, o vraptor fornecer uma instncia de ClienteDao para seu ClienteController sempre que precisar instanci-lo. Vale lembrar que o VRaptor honrar o escopo de cada componente. Por exemplo, se ClienteDao fosse de escopo Session (@SessionScoped), seria criada uma nica instncia desse componente por sesso. (note que provavelmente errado usar um dao no escopo de session, isto um mero exemplo).

9.1- ComponentFactoryEm diversos momentos queremos que nossos componentes recebam componentes de outras bibliotecas. Nesse caso no temos como alterar o cdigo fonte da biblioteca para adicionar a anotao @Component (alm de possveis alteraes requeridas na biblioteca). O exemplo mais famoso envolve adquirir uma Session do Hibernate. Nesses casos precisamos criar um componente que possui um nico papel: fornecer instncias de Session para os componentes que precisam 44

Caelum VRaptor

dela. O VRaptor possui uma interface chamada ComponentFactory que permite que suas classes possuam tal responsabilidade. Implementaes dessa interface denem um nico mtodo. Veja o exemplo a seguir, que inicializa o Hibernate na construo e utiliza essa congurao para fornecer sesses para nosso projeto:

@Component @ApplicationScoped public class SessionFactoryCreator implements ComponentFactory { private SessionFactory factory; @PostConstruct public void create() { factory = new AnnotationConfiguration().configure().buildSessionFactory(); } public SessionFactory getInstance() { return factory; } @PreDestroy public void destroy() { factory.close(); } } @Component @RequestScoped public class SessionCreator implements ComponentFactory { private final SessionFactory factory; private Session session; public SessionCreator(SessionFactory factory) { this.factory = factory; } @PostConstruct public void create() { this.session = factory.openSession(); } public Session getInstance() { return session; } @PreDestroy public void destroy() { this.session.close(); } }Essas implementaes j esto disponveis no cdigo do VRaptor. Para us-la veja o captulo de utils.

Captulo 9 - Injeo de dependncias - ComponentFactory 45

Caelum VRaptor

9.2- ProvidersPor trs dos panos, o VRaptor utiliza um container de injeo de dependncias especco. Existem trs containers suportados pelo VRaptor:

Spring IoC: alm da injeo de dependncias, o Spring IoC possibilita usar qualquer outro componentedo Spring integrado com o VRaptor, sem precisar de conguraes

Google Guice: um container mais leve e rpido, que possibilita um melhor controle na ligao das dependncias, o uso da nova api de injeo de dependncias do java: o javax.inject e funcionalidades de AOP.

Pico container: um container leve e simples, pra quem no vai usar nada alm de injeo de dependncias. Para selecionar qualquer um desses containers basta colocars seus respectivos jars no classpath. Os jars esto disponveis na pasta lib/containers do zip do VRaptor. Por padro os containers vo considerar apenas as classes abaixo da pasta WEB-INF/classes da sua aplicao, mas possvel, ainda, colocar classes anotadas da sua aplicao dentro de jars, desde que os jars incluam as entradas de diretrio (Add directory entries no eclipse, ou ant sem a opo les only). Para isso necessrio usar o seguinte parmetro no web.xml:

br.com.caelum.vraptor.packages br.com.pacote.dentro.do.jar

9.3- SpringAo utilizar o Spring, voc ganha todas as caractersticas e componentes prontos do Spring para uso dentro do VRaptor, isto , todos os componentes que funcionam com o Spring DI/Ioc, funcionam com o VRaptor. Nesse caso, todas as anotaes. Para usar o spring adicione todos os jars da pasta lib/containers/spring na sua aplicao. O VRaptor vai usar suas conguraes do Spring, caso voc j o tenha congurado no seu projeto ( os listeners e o applicationContext.xml no classpath). Caso o VRaptor no tenha encontrado sua congurao, ou voc precise fazer alguma congurao mais avanada, voc pode estender o provider do Spring:

package br.com.suaaplicacao; public class CustomProvider extends SpringProvider { @Override protected void registerCustomComponents(ComponentRegistry registry) { registry.register(UmaClasse.class, ImplementacaoDessaClasse.class); //... } @Override protected ApplicationContext getParentApplicationContext(ServletContext context) { ApplicationContext context = //configure seu prprio application context return context; }

Captulo 9 - Injeo de dependncias - Providers 46

}e pra usar o seu provider, coloque no web.xml:

br.com.caelum.vraptor.provider br.com.suaaplicacao.CustomProvider

9.4- Google GuicePara habilitar o Google Guice basta colocar os jars que esto na pasta lib/containers/guice do zip do VRaptor. Ao usar o Guice voc pode escolher no usar a anotao @Component do VRaptor, e usar as anotaes do guice ou do javax.inject (@Inject, anotaes de escopo) para controlar a instanciao dos seus componentes. Se precisar fazer conguraes mais especcas crie uma classe que estende o provider do Guice:

public class CustomProvider extends GuiceProvider { @Override protected void registerCustomComponents(ComponentRegistry registry) { //binding s na UmaClasse registry.register(UmaClasse.class, ImplementacaoDessaClasse.class); //binding da classe e de todas as superclasses e interfaces registry.deepRegister(OutraClasse.class);

}

@Override protected Module customModule() { //voc precisa instalar esse modulo se quiser //habilitar o mtodo registerCustomComponents //e o classpath scanning final Module module = super.customModule(); return new AbstractModule() { public void configure() { module.configure(binder()); } // binds personalizados do Guice

}

}

};

e pra usar esse provider, coloque no web.xml:

br.com.caelum.vraptor.provider br.com.suaaplicacao.CustomProvider

Caelum VRaptor

9.5- Pico ContainerPara utilizar o Picocontainer como provider de sua aplicao, basta colocar os jars da pasta lib/containers/picocontainer do zip do VRaptor no classpath da sua aplicao.

Captulo 9 - Injeo de dependncias - Pico Container 48

C APTULO

10

Download e Upload10.1- exemplo de 1 minuto: downloadO exemplo a seguir mostra como disponibilizar o download para seu cliente. Note novamente a simplicidade na implementao:

@Resource public class PerfilController { public File foto(Perfil perfil) { return new File("/path/para/a/foto." + perfil.getId()+ ".jpg"); }

}

10.2- Adicionando mais informaes no downloadSe voc quiser adicionar mais informaes ao download voc pode retornar um FileDownload:

@Resource public class PerfilController { // dao ... public Download foto(Perfil perfil) { File file = new File("/path/para/a/foto." + perfil.getId()+ ".jpg"); String contentType = "image/jpg"; String filename = perfil.getNome() + ".jpg"; } return new FileDownload(file, contentType, filename);

}

Voc pode tambm usar a implementao InputStreamDownload para trabalhar diretamente com Streams ou ByteArrayDownload para array de bytes (desde a 3.2-snapshot).

10.3- UploadPara ativar o suporte a upload necessrio adicionar as bibliotecas commons-upload e commons-io em seu classpath. Na verso 3.2 do VRaptor, caso voc estiver em um container que implemente a JSR-315 (Servlet 3.0), no sero necessrios os jars commons-upload e commons-io, pois o prprio container j implementa a funcionalidade de upload.

49

Caelum VRaptor

10.4- exemplo de 1 minuto: uploadO primeiro exemplo ser baseado na funcionalidade de upload multipart.

@Resource public class PerfilController { private final PerfilDao dao; public PerfilController(PerfilDao dao) { this.dao = dao; } public void atualizaFoto(Perfil perfil, UploadedFile foto) { dao.atribui(foto.getFile(), perfil); }

}

10.5- Mais sobre UploadO UploadedFile retorna o arquivo como um InputStream. Se voc quiser copiar para um arquivo no disco facilmente, basta usar o IOUtils do commons-io:

public void atualizaFoto(Perfil perfil, UploadedFile foto) { File fotoSalva = new File(); IOUtils.copyLarge(foto.getFile(), new FileOutputStream(fotoSalva)); dao.atribui(fotoSalva, perfil); }

10.6- Sobrescrevendo as conguraes de uploadVoc pode alterar as conguraes de upload sobrescrevendo a classe MultipartConfig. No exemplo abaixo alterado o tamanho mximo de upload.

@Component @ApplicationScoped public class CustomMultipartConfig extends DefaultMultipartConfig { public long getSizeLimit() { return 50 * 1024 * 1024; // 50MB } }

10.7- Alterando o formulrio de envioPara que o browser possa fazer o upload corretamente voc precisa adicionar o atributo enctype para multipart/form-data:

Captulo 10 - Download e Upload - exemplo de 1 minuto: upload 50

10.8- Validando o uploadQuando o tamanho mximo para upload de arquivo exceder o valor congurado, o VRaptor adiciona uma mensagem no objeto Validator.

C APTULO

11

Componentes Utilitrios Opcionais11.1- Registrando um componente opcionalO VRaptor possui alguns componentes opcionais, que esto no pacote br.com.caelum.vraptor.util. Para registr-los voc pode adicionar seus pacotes no web.xml:

br.com.caelum.vraptor.packages br.com.caelum.vraptor.util.um.pacote, br.com.caelum.vraptor.util.outro.pacote ou voc pode criar um custom provider:

Crie uma classe lha do Provider que voc est usando:package br.com.nomedaempresa.nomedoprojeto; public class CustomProvider extends SpringProvider { }

Registre essa classe como provider no web.xml: br.com.caelum.vraptor.provider br.com.nomedaempresa.nomedoprojeto.CustomProvider

Sobrescreva o mtodo registerCustomComponents e adicione os componentes opcionais:package br.com.nomedaempresa.nomedoprojeto; public class CustomProvider extends SpringProvider { @Override protected void registerCustomComponents(ComponentRegistry registry) { registry.register(ComponenteOpcional.class, ComponenteOpcional.class); }

}

52

Caelum VRaptor

11.2- Componentes opcionais disponveis Hibernate Session e SessionFactorySe voc precisa de Sessions e SessionFactory nos seus componentes, voc geralmente vai precisar de um ComponentFactory para cri-los. Se voc usa entidades anotadas, e o hibernate.cfg.xml na raiz do WEBINF/classes, voc pode usar as ComponentFactorys para isso que j vm com o VRaptor. O VRaptor tambm tem um interceptor que abre a Session e comea uma transao no incio da requisio e fecha a Session (e commita ou d rollback na transao) no nal da requisio. Voc pode registrar esses componentes do VRaptor adicionando o pacote br.com.caelum.vraptor.util.hibernate no seu web.xml:

br.com.caelum.vraptor.packages br.com.caelum.vraptor.util.outros.pacotes..., br.com.caelum.vraptor.util.hibernate ou registr-los manualmente no custom provider:

@Override protected void registerCustomComponents(ComponentRegistry registry) { registry.register(SessionCreator.class, SessionCreator.class); //cria Session's registry.register(SessionFactoryCreator.class, SessionFactoryCreator.class); // cria uma SessionFactory registry.register(HibernateTransactionInterceptor.class, HibernateTransactionInterceptor.class); // open session and transaction in view }J existe um Provider que adiciona esses trs componentes opcionais. Voc pode apenas registr-lo no seu web.xml:

br.com.caelum.vraptor.provider br.com.caelum.vraptor.util.hibernate.HibernateCustomProvider

11.3- JPA EntityManager e EntityManagerFactorySe voc tiver um persistence.xml com o persistence-unit chamado default, voc pode usar os ComponentFactories para criar EntityManager e EntityManagerFactory j disponveis no vraptor, adicionando o pacote br.com.caelum.vraptor.util.jpa no web.xml:

br.com.caelum.vraptor.packages br.com.caelum.vraptor.util.outros.pacotes..., br.com.caelum.vraptor.util.jpa ou adicion-los manualmente no web.xml:Captulo 11 - Componentes Utilitrios Opcionais - Componentes opcionais disponveis 53

Caelum VRaptor

@Override protected void registerCustomComponents(ComponentRegistry registry) { registry.register(EntityManagerCreator.class, EntityManagerCreator.class); // cria EntityManager's registry.register(EntityManagerFactoryCreator.class, EntityManagerFactoryCreator.class); //cria uma EntityManagerFactory registry.register(JPATransactionInterceptor.class, JPATransactionInterceptor.class); //open EntityManager and transaction in view }J existe um Provider que adiciona esses trs componentes opcionais. Voc pode apenas registr-lo no seu web.xml:

br.com.caelum.vraptor.provider br.com.caelum.vraptor.util.jpa.JPACustomProvider

Converters LocalizadosExistem alguns converters para nmeros que so localizados, ou seja, que consideram o Locale atual para converter os parmetros. Voc pode registr-los adicionando o pacote br.com.caelum.vraptor.converter.l10n no seu web.xml:

br.com.caelum.vraptor.packages br.com.caelum.vraptor.util.outros.pacotes..., br.com.caelum.vraptor.converter.l10n

Instanciador de Parmetros Imutveis (beta)Se voc quiser trabalhar com objetos imutveis no seu projeto, voc pode usar um parameter provider que consegue popular seus objetos a partir dos parmetros do seu construtor:

@Resource public class CarrosController { public void lava(Carro carro) { } }

public class Carro { private final String cor; private final String modelo; public Car(String cor, String modelo) { this.cor = cor; this.modelo = modelo; } //getters

Captulo 11 - Componentes Utilitrios Opcionais - JPA EntityManager e EntityManagerFactory 54

}O carro ser populado com os request parameters normais: carro.cor e carro.modelo Para habilitar esse comportamento, voc pode adicionar o pacote br.com.caelum.vraptor.http.iogi ao seu web.xml:

br.com.caelum.vraptor.packages br.com.caelum.vraptor.util.outros.pacotes..., br.com.caelum.vraptor.http.iogi

Integrao com ExtJSExiste uma View do VRaptor que consegue gerar alguns formatos de JSON que o ExtJS espera. Para isso use:

result.use(ExtJSJson.class).....serialize();

Compatibilidade com VRaptor 2Se voc quer migrar do VRaptor 2 para o VRaptor 3 (veja o captulo Migrando do VRaptor 2 para o VRaptor 3):

br.com.caelum.vraptor.packages br.com.caelum.vraptor.util.outros.pacotes..., br.com.caelum.vraptor.vraptor2

C APTULO

12

Conguraes avancadas: sobrescrevendo as convenes e comportamento do VRaptorA maioria dos comportamentos e convenes do VRaptor so personalizveis. E a forma de personalizar bem fcil: criar um componente que implementa uma das interfaces internas do VRaptor. Ao fazer isso, o VRaptor vai usar a implementao personalizada ao invs da padro. Para saber qual a interface certa para personalizar um certo comportamento, pergunte na lista de desenvolvedores do vraptor: [email protected] ou no forum do guj: http://www.guj.com.br/forums/show/23.java

Abaixo veremos alguns exemplos de personalizao:

12.1- Mudando a view renderizada por padroSe voc precisa mudar a view renderizada por padro, ou mudar o local em que ela procurada, basta criar a seguinte classe:

@Component public class CustomPathResolver extends DefaultPathResolver { @Override protected String getPrefix() { return "/pasta/raiz/"; } @Override protected String getExtension() { return "ftl"; // ou qualquer outra extenso } @Override protected String extractControllerFromName(String baseName) { return //sua conveno aqui //ex.: Ao invs de redirecionar UserController para 'user' //voc quer redirecionar para 'userResource' //ex.2: Se voc sobrescreveu a conveo para nome dos Controllers para XXXResource //e quer continuar redirecionando para 'user' e no para 'userResource' } }Se voc precisa mudar mais ainda a conveno basta implementar a interface PathResolver.

56

12.2- Mudando a URI padroPor padro, a URI para o mtodo ClientesController.lista() /clientes/lista, nome_do_controller/nome_do_metodo. Para sobrescrever essa conveno, basta criar a classe: ou seja,

@Component @ApplicationScoped public class MeuRoutesParser extends PathAnnotationRoutesParser { //delegate constructor protected String extractControllerNameFrom(Class type) { return //sua conveno aqui } protected String defaultUriFor(String controllerName, String methodName) { return //sua conveno aqui

}

}

Se voc precisa mudar mais ainda a conveno basta implementar a interface RoutesParser.

12.3- Mudando o encoding da sua aplicaoSe voc quiser que todas as requisies da sua aplicao sejam de um encoding determinado, para evitar problemas de acentuao por exemplo, voc pode colocar o seguinte parmetro no seu web.xml:

br.com.caelum.vraptor.encoding UTF-8 Assim todas as suas pginas e dados passados para formulrio usaro o encoding UTF-8, evitando problemas de acentuao.

C APTULO

13

Spring, Joda Time, Hibernate13.1- Integrao com Hibernate ou JPAExistem ComponentFactories implementadas para Session, SessionFactory, EntityManager e EntityManagerFactory. Voc pode us-las ou se basear nelas para criar sua prpria ComponentFactory para essas classes. Alm disso existem interceptors implementados que controlam as transaes tanto na JPA quanto com o Hibernate. Para saber como fazer usar esses componentes veja o captulo de utils.

13.2- Integrao com SpringO VRaptor roda dentro do Spring, e usa o ApplicationContext da sua aplicao se disponvel. Logo todas as funcionalidades e mdulos do Spring funcionam com o VRaptor sem nenhuma congurao da parte do VRaptor!

13.3- Conversores para Joda TimeA api de datas do Java bem ruim, e por esse motivo existe o projeto joda-time (http://joda-time. sourceforge.net/) que tem uma api bem mais agradvel para trabalhar com datas. Se o jar do joda-time estiver no classpath, o VRaptor registra automaticamente os conversores para os tipos LocalDate, LocalTime e LocalDateTime, logo voc pode receb-los como parmetro sem problemas.

C APTULO

14

Google App Engine14.1- Comeando um projetoDevido s restries de segurana na sandbox do Google App Engine, alguns componentes do VRaptor3 precisam ser substitudos e uma seleo diferente de dependncias deve ser usada. Uma verso do blank project j contendo estas alteraes est disponvel em nossa pgina de downloads.

14.2- ConguraoPara habilitar os componentes do VRaptor para o Google App Engine voc precisa adicionar a seguinte congurao no seu web.xml:

br.com.caelum.vraptor.packages br.com.caelum.vraptor.gae

14.3- LimitaesUm detalhe importante que a injeo de dependncias no funciona no redirecionamento para lgicas; o controlador instanciado recebendo null em todos os seus parmetros. Sendo assim, deve-se evitar chamadas como:

result.use(Results.logic()).redirectTo(SomeController.class).someMethod(); validator.onErrorUse(Results.logic()).of(SomeController.class).someMethod();preferindo Results.page() - ou ento escrever seus controllers de forma a esperar pelos valores nulos.

14.4- Problemas comunsA ambiente de execuo do App Engine no habilita o suporte a Expression Language por padro, nem suporta a tag . Assim sendo, para habilitar o suporte a EL, necessrio adicionar a seguinte linha nos arquivos JSP:

14.5- JPA 2O VRaptor possui suporte ao JPA nas verses 1 e 2, porm o ambiente do Google App Engine suporta apenas JPA 1. Por isso voc deve evitar de copiar o jar jpa-api-2.0.jar para seu projeto.

C APTULO

15

Testando componentes e controllersCriar um teste unitrio do seu controller VRaptor costuma ser muito fcil: dado o desacoplamento das suas classes com a api javax.servlet e os parmetros serem populados atravs do request, seu teste ser como o de uma classe qualquer, sem mistrios. O VRaptor3 gerencia as dependncias da sua classe, ento voc no precisa se preocupar com a criao do seus componentes e controllers, basta receber suas dependncias no construtor que o VRaptor3 vai procur-las e instanciar sua classe. Na hora de testar suas classes voc pode aproveitar que todas as dependncias esto sendo recebidas no construtor, e passar implementaes falsas (mocks) dessas dependncias, para testar unitariamente sua classe. Mas os componentes do VRaptor3 que vo ser mais presentes na sua aplicao - o Result e o Validator - possuem a interface uente, o que diculta a criao de implementaes falsas (mocks). Por causa disso existem implementaes falsas j disponveis no VRaptor3: MockResult e MockValidator. Isso facilita em muito os seus testes que seriam mais complexos.

15.1- MockResultO MockResult ignora os redirecionamentos que voc zer, e acumula os objetos includos, para voc poder inspeciona-los e fazer as suas asseres. Um exemplo de uso seria:

MockResult result = new MockResult(); ClienteController controller = new ClienteController(..., result); controller.list(); // vai chamar result.include("clients", algumaCoisa); List clients = result.included("clients"); // o cast automtico Assert.assertNotNull(clients); // mais assertsQuaisquer chamadas do tipo result.use(...) vo ser ignoradas.

15.2- MockValidatorO MockValidator vai acumular os erros gerados, e quando o validator.onErrorUse for chamado, vai lanar um ValidationError caso haja algum erro. Desse jeito voc pode inspecionar os erros adicionados, ou simplesmente ver se deu algum erro:

@Test(expected=ValidationException.class) public void testaQueVaiDarErroDeValidacao() { ClienteController controller = new ClienteController(..., new MockValidator()); controller.adiciona(new Cliente());60

}ou

@Test public void testaQueVaiDarErroDeValidacao() { ClienteController controller = new ClienteController(..., new MockValidator()); try { controller.adiciona(new Cliente()); Assert.fail(); } catch (ValidationException e) { List errors = e.getErrors(); //asserts nos erros } }Se voc usa o Hibernate Validator e tem a chamada validator.validate(objeto) no mtodo do seu controller, voc pode usar a classe HibernateMockValidator, que validar o objeto com as regras denidas pelo HV.

C APTULO

16

ScalaO VRaptor3 tambm suporta controllers escritos em Scala. As conguraes necessrias e um exemplo so apresentadas neste captulo.

16.1- Dependncias e ConguraoOs seguintes jars precisam ser adicionados ao diretrio WEB-INF/lib da sua aplicao:

scala-library.jar (requerido, verso 2.8) vraptor-scala.jar (requerido) vraptor-scala-jsp.jar (opcional, para suporte ao uso de Expression Language sobre colees do Scalana view)

scalate.jar (requerido)Feito isso, preciso congurar o VRaptor para carregar os plugins. context-param como abaixo: No web.xml, dena a seo

br.com.caelum.vraptor.packages br.com.caelum.vraptor.scala Tambm adicione ao arquivo as conguraes necessrias para usar o Scalate como view:

TemplateEngineServlet org.fusesource.scalate.servlet.TemplateEngineServlet 1 TemplateEngineServlet *.ssp

16.2- ExemploUm controller do VRaptor3 escrito em Scala:

62

@Resource class MeuController { @Path(Array("/hello")) def minhaLogica = "Hello, world!" }

C APTULO

17

Otimizaes17.1- Commons UploadSe voc no for usar upload na sua aplicao, remova o jar do commons upload do classpath. Isso evita o carregamento do interceptor de upload, deixando o request mais rpido.

17.2- Anotao @Lazy em InterceptorsSe o mtodo accepts do seu interceptor no depende do seu estado interno voc pode anot-lo com @Lazy:

@Intercepts @Lazy public class MeuLazyInterceptor implements Interceptor { public MeuLazyInterceptor(Dependencia dependencia) { this.dependencia = dependencia; } public boolean accepts(ResourceMethod method) { // depende apenas do method return method.containsAnnotation(Abc.class); } public void intercepts(...) { //... } }Assim o VRaptor s vai instanciar esse interceptor se o mtodo accepts retornar true. Para fazer isso o VRaptor cria uma instncia no funcional do interceptor (todas as dependncias nulas) e chama o mtodo accepts, evitando uma chamada ao Container de DI desnecessria. Acessos ao estado interno do interceptor podem gerar NullPointerException. No use o @Lazy se o accepts trivial (apenas retorna true).

C APTULO

18

VRaptor ScaffoldO VRaptor 3 agora possui uma extenso chamada VRaptor Scaffold, que ter por nalidade facilitar a congurao de novos projetos e plugins.

18.1- InstalaoPara instalar o vraptor scaffold necessrio ter instalado o ruby e o rubygems. Voc pode encontrar informaes de instalao no seguinte endereo http://www.ruby-lang.org/pt/downloads . Tendo isso instalado basta executar o comando a seguir.

gem install vraptor-scaffold

18.2- Comeando um projetoAbra um terminal e digite

vraptor new onlinestoreEsse comando vai criar toda a estrutra da aplicao, aps isso entre na pasta onlinestore e execute a task jetty do ant

ant jetty.runAbra o browser no endereo http://localhost:8080 e voc deve ver It works!. Agora vamos criar um cadastro completo(CRUD) de produtos para nossa loja virtual, para isso basta executar

vraptor scaffold product name:string value:doubleExecute novamente

ant jetty.runAcesse http://localhost:8080/products

65

Caelum VRaptor

18.3- PackageO pacote raiz por padro app, para mudar isso crie a aplicao com o seguinte comando

vraptor new onlinestore --package=br.com.caelumVoc tambm pode congurar os pacotes de modelos, controllers e repositrios:

vraptor new onlinestore --package=br.com.caelum -m modelo -c controlador -r repositorio

18.4- Build: Maven, Gradle ou IvyO vraptor-scaffold gera um projeto com ant e ivy por padro, mas voc pode escolher outra ferramenta de build com um simples comando na hora de criar seu projeto:

# for maven vraptor new onlinestore --build-tool=mvn # for gradle vraptor new onlinestore --build-tool=gradleAo usar gradle, utilize

gradle jettyRunpara rodar a aplicao.

18.5- ORM: JPA ou Hibernate, connection poolUm projeto novo j vem por padro com o c3p0 congurado. Alm disso voc pode escolher entre JPA (EntityManager, padro), ou Hibernate (Session), ao criar seu projeto:

vraptor new onlinestore -o=jpa vraptor new onlinestore -o=hibernate

18.6- FreemarkerO template engine padro jsp, para utilizar o freemarker, crie a aplicao com

vraptor new onlinestore --template-engine=ftl

Captulo 18 - VRaptor Scaffold - Package 66

Caelum VRaptor

18.7- EclipseSe voc optou pelo maven execute

mvn eclipse:eclipsePara gerar os arquivos de congurao do eclipse, aps isso apenas faa a importao do projeto normalmente. Se voc optou pelo ant os arquivos de congurao sero gerados no momento em que criar o projeto, no se esquea de executar

ant compilepara baixar todas as dependncias antes de importar o projeto. possvel pular a criao desses arquivos com o comando

vraptor new onlinestore --skip-eclipse

18.8- Tipos de atributos suportado possvel gerar um CRUD com os seguintes atributos: boolean, double, float, short, integer, long, string e text.

18.9- PluginsPlugins do vraptor so facilmente instalados atravs do comando

vraptor plugin simple-email -v 1.0.0Voc pode encontrar uma lista de plugins disponveis em https://github.com/caelum/vraptor-contrib

18.10- jQueryA verso do jQuery sempre a ltima disponvel para download, para utilizar uma verso anterior use o comando:

vraptor new onlinestore -j 1.4.4

Captulo 18 - VRaptor Scaffold - Eclipse 67

18.11- HerokuAgora possvel fazer um deploy de qualquer aplicao java no Heroku com um simples:

git push heroku masterE o vrpator-scaffold j tem um comando que gera toda a aplicao do jeito que o Heroku espera. Para isso basta utilizar o comando:

vraptor new onlinestore --herokuDepois s fazer o deploy da sua aplicao seguindo os passos do Heroku. Para mais informaes acessehttp://www.heroku.com/java

18.12- Comando HelpPara visualizar a lista de comandos disponibilizados pelo vraptor-scaffold, execute:

vraptor -hvraptor new -h vraptor scaffold -h vraptor plugin -h

18.13- ContribuindoO projeto est sendo desenvolvido em ruby e o cdigo fonte est hospedado no github no seguinte endereo https://github.com/caelum/vraptor-scaffold . Voc pode colaborar com o projeto fazendo o fork e enviando seu path ou uma nova funcionalide. No se esquea dos testes.

C APTULO

19

Exception handlingA partir da verso 3.2 o VRaptor possui um Exception Handler, que captura as excees no tratadas em sua aplicao. O funcionamento do Exception Handler muito semelhante ao funcionamento do VRaptor Validator. No exemplo abaixo, se o mtodo addCustomer(Customer) lanar uma CustomerAlreadyExistsException ou qualquer exceo lha, o usurio ser redirecionado para o mtodo addCustomer().

@Get public void addCustomer() { // do something } @Post public void addCustomer(Customer newCustomer) { result.on(CustomerAlreadyExistsException.class).forwardTo(this).addCustomer(); } customerManager.store(newCustomer);

C APTULO

20

Como contribuir com o VRaptor20.1- Participando das listas de discussoVoc pode responder s dvidas dos outros usurios no sub-frum Frameworks e Bibliotecas brasileiros no GUJ [1] ou no Google Groups [2].

20.2- Colaborando com documentaoVoc pode ajudar escrevendo Javadocs, melhorando o contedo do site, com alguma receita ou com algum artigo em seu blog.

20.3- Reportando bugs e sugerindo novas funcionalidadesSe voc encontrou um bug, avise a equipe de desenvolvimento do VRaptor usando as listas de discusses para usurios [2] ou a lista de desenvolvedores [3]. Voc tambm pode cadastrar uma issue no Github [4].

20.4- Colaborando com cdigoSe voc tem alguma melhoria que gostaria de ver no VRaptor, envie sua sugesto para os desenvolvedores na lista de discusso [3]. Se voc j implementou a melhoria, envie seu pull request atravs do Github. Voc pode resolver umas das issues cadastradas no Github [4], enviando-nos um pull request com as suas alteraes. O VRaptor um Framework Web MVC focado em simplicidade e facilidade de uso. Quando voc implementar algo, cuide para seguir as boas prticas de Orientao a Objetos e baixo acoplamento, uso de composio ao invs de herana, conveno ao invs de conguraes e um cdigo bem estruturado. No deixe tambm de escrever os Javadocs e classes de testes unitrios. Contribuies de funcionalidades como segurana, paginao, multitenant, e outros so muito bem vindos atravs de plugins e contribuies para o vraptor-contrib [5], ou extenses para o vraptor-scaffold [6].

20.5- Montando o ambienteTodos os mdulos do VRaptor possuem os arquivos classpath-example e project-example, facilitando a importao do projeto para quem usa Eclipse. Neste caso basta renomear os arquivos para .classpath e .project respectivamente. Se voc utiliza outra IDE, basta montar os diretrios src/main/java, src/test/java, src/test/resources e src/main/resources como source folders. As bibliotecas utilizadas cam no diretrio lib. [1] http://guj.com.br/forums/show/23.java [2] http://groups.google.com/group/caelum-vraptor [3] http: [4] http://github.com/caelum/vraptor/issues [5] http:// github.com/caelum/vraptor-contrib [6] https://github.com/caelum/vraptor-scaffold//groups.google.com/group/caelum-vraptor-dev

C APTULO

21

ChangeLog21.1- 3.4.1 PicoProvider agora tambm seta atributos do request e da session com os nomes dos componentes, damesma forma que o Guice e o Spring

SpringProvider agora emula o comportamento do ContextLoaderListener, melhorando a integrao comos componentes do Spring sem precisar registrar o listener no web.xml.

melhor serializao com o XStream, suportando mais casos. correo do plugin do GAE. Locale based converters para tipos primitivos (by Rafael Dipold) Mudana de padro IOGI como instanciador de objetos padro, ao invs do OGNL suporte a @Consumes(application/x-www-form-urlencoded) (by Celso Da