--- title: Componentes --- #O que são componentes? Componentes são instâncias de classes que seu projeto precisa para executar tarefas ou armazenar estados em diferentes situações. Exemplos clássicos de uso de componentes seriam os DAOs, enviadores de email etc. A sugestão de boa prática indica sempre criar uma interface para seus componentes. Dessa maneira seu código também fica mais fácil de ser testado unitariamente. O exemplo a seguir mostra um componente a ser gerenciado pelo VRaptor: ~~~ #!java @RequestScoped public class ClienteDao { private Session session; // o CDI obriga que você tenha o construtor padrão protected ClienteDao() { } @Inject public ClienteDao(Session session) { this.session = session; } public void adiciona(Cliente cliente) { session.save(cliente); } } ~~~ Todos os componentes do VRaptor são gerenciados pelo CDI (Context Dependency Injection) do Java EE 7. Desta forma todas as funcionalidades presentes no CDI estão presentes no VRaptor. Nos links abaixo você pode obter mais informações sobre o CDI: - Use CDI no seu próximo projeto Java - Customizando a produção de dependências no CDI - 4 recursos novos do CDI 1.1 ##Escopos Assim como os recursos, os componentes vivem em um escopo específico e seguem as mesmas regras, por padrão pertencendo ao escopo de requisicão, isto é, a cada nova requisição seu componente será novamente instanciado. O exemplo a seguir mostra o fornecedor de conexões com o banco baseado no Hibernate. Esse fornecedor está no escopo de aplicacação, portanto será instanciado somente uma vez por contexto: ~~~ #!java @ApplicationScoped public class HibernateControl { private final SessionFactory factory; public HibernateControl() { this.factory = new AnnotationConfiguration().configure().buildSessionFactory(); } public Session getSession() { return factory.openSession(); } } ~~~ Os escopos implementados são: ~~~ * @ApplicationScoped - component é um singleton, apenas um por aplicação. * @SessionScoped - o componente é o mesmo durante uma http session. * @ConversationScoped - a instância do componente é mantida durante uma conversation. * @RequestScoped - o componente é o mesmo durante uma requisição. * @Dependent - component é instanciado sempre que requisitado. ~~~ Você pode pesquisar mais sobre os [escopos do CDI aqui](http://docs.oracle.com/javaee/7/tutorial/doc/cdi-basic008.htm). ##Fabricando componentes Muitas vezes você quer receber como dependência da sua classe alguma classe que não é do seu projeto, como por exemplo uma Session do Hibernate ou um EntityManager da JPA. Para poder fazer isto, basta criar um `Produces`: ~~~ #!java @RequestScoped public class SessionCreator { @Inject private SessionFactory sessionFactory; @Produces @RequestScoped public Session getSession() { return sessionFactory.openSession(); } public void close(@Disposes Session session) { if (session.isOpen()) { session.close(); } } } ~~~ Você pode também adicionar os listeners `@PostConstruct`, `@PreDestroy` e `@Disposes` para controlar a criação e destruição dos recursos que você usa. Isso funciona para qualquer componente que você registrar no VRaptor. ##Injeção de dependências O VRaptor utiliza o CDI para controlar o que é necessário para instanciar cada um de seus componentes e recursos. Sendo assim, os dois exemplos anteriores permitem que quaisquer um dos seus recursos ou componentes recebam um `ClienteDao` em seu construtor, por exemplo: ~~~ #!java @Controller public class ClienteController { private ClienteDao dao; @Inject public ClienteController(ClienteDao dao) { this.dao = dao; } @Post public void adiciona(Cliente cliente) { this.dao.adiciona(cliente); } } ~~~ ## Disparando eventos Para disparar eventos você pode usar a anotação `@Observes`, que é usada quando um evento inicia. Se você quiser, por exemplo, imprimir uma mensagem na inicialização da aplicação, você pode fazer o seguinte código: ~~~ #!java @ApplicationScoped public class PrintLog { public void observesContext(@Observes ServletContext context) { System.out.println("My application is UP"); } ~~~ ## Sobrescrevendo componentes A maioria dos comportamentos e convenções do VRaptor são personalizáveis. E a forma de personalizar é bem fácil: criar um componente que estende uma das classes internas do VRaptor e anotá-las com `@Specializes`. Ao fazer isso, o VRaptor vai usar a implementação personalizada ao invés da padrão. Caso você quiser implementar alguma interface basta você usar a anotação: ~~~ #!java @Priority(Interceptor.Priority.LIBRARY_BEFORE + 10) ~~~ ##Mudando a view renderizada por padrão Se você precisa mudar a view renderizada por padrão, ou mudar o local em que ela é procurada, basta criar a seguinte classe: ~~~ #!java @Specializes public class CustomPathResolver extends DefaultPathResolver { @Override protected String getPrefix() { return "/pasta/raiz/"; } @Override protected String getExtension() { return "ftl"; // ou qualquer outra extensão } @Override protected String extractControllerFromName(String baseName) { return //sua convenção aqui //ex.: Em vez de redirecionar UserController para 'user' //você quer redirecionar para 'userResource' //ex.2: Se você sobrescreveu a conveção para nome dos Controllers para XXXResource //e quer continuar redirecionando para 'user' e não para 'userResource' } } ~~~ Se você precisa mudar mais ainda a convenção basta implementar a interface `PathResolver`. ##Mudando a URI padrão Por padrão, a URI para o método `ClientesController.lista()` é `/clientes/lista`, ou seja, `nome_do_controller/nome_do_metodo`. Para sobrescrever essa convenção, basta criar a classe: ~~~ #!java @Specializes @ApplicationScoped public class MeuRoutesParser extends PathAnnotationRoutesParser { //delegate constructor protected String extractControllerNameFrom(Class type) { return //sua convenção aqui } protected String defaultUriFor(String controllerName, String methodName) { return //sua convenção aqui } } ~~~ Se você precisa mudar mais ainda a convenção, basta implementar a interface `RoutesParser`. ##Mudando o encoding da sua aplicação Se você quiser que todas as requisições da sua aplicação sejam de um encoding determinado, para evitar problemas de acentuação por exemplo, você pode colocar o seguinte parâmetro no seu web.xml: ~~~ #!xml br.com.caelum.vraptor.encoding UTF-8 ~~~ Assim, todas as suas páginas e dados passados para formulário usarão o encoding UTF-8, evitando problemas de acentuação.