BT

Java na Web com VRaptor 4

Postado por Rodrigo Turini em 13 Mai 2014 |

Trabalhar com Java na web apresenta diversas possibilidades com frameworks MVC baseados em ações. O VRaptor é um desses frameworks, e em sua versão 4 utiliza o CDI 1.1 como base. Veremos neste artigo alguns dos princípios do framework e uma seleção de novidades da nova versão.

Controllers e Convenções

Tudo que se precisa fazer para criar um controller do VRaptor é adicionar a anotação @Controller. A partir daí o framework já utiliza suas convenções de URLs e JSPs, exigindo o mínimo de configurações. Veja um exemplo:

@Controller
public class UsuarioController {
 	public void lista() {
... 
}
}

A convenção de URLs do VRaptor é nomeDoController/nomeDoMetodo; portanto o método lista() seria mapeado para a URL /usuario/lista. Repare que o sufixo Controller não é considerado na rota.

Outra convenção importante é da página JSP pra a qual o VRaptor vai fazer o dispatch. Ela é bem parecida com a convenção de URLs.O VRaptor procura a JSP no diretório:

WEB-INF/jsp/nomeDoController/nomeDoMetodo.jsp, 

que neste caso será:

WEB-INF/jsp/usuario/lista.jsp.

Todos os métodos públicos dos controllers serão mapeados seguindo essas convenções, e passam a atender requests independente do verbo HTTP utilizado.

Pode-se explicitamente declarar qual tipo de requisição cada método vai atender, por exemplo utilizando a anotação @Get. Há ainda as anotações @Post, @Put e @Delete. Se preferir não utilizar a convenção de URLs, você pode passar a URL como value dessas anotações de verbo, ou utilizar a anotação @Path se o verbo for indiferente:

@Get("alguma/outra/url")
public void lista(){ ... }

Recebimento de parâmetros

Pode-se receber parâmetros nos métodos do seu controller. De acordo com os parâmetros da requisição o VRaptor tenta popular esses valores. Isso pode ser feito com valores simples, como um long no caso do seguinte método:

@Get
public void busca(long id){
…
}

Se o request tiver algum parâmetro cujo nome seja id, ou seja, igual ao do parâmetro do método, o VRaptor tenta converter esse valor para o tipo esperado.

O método busca(), na primeira forma que foi escrito, pode ser acessado pela URL /usuario/busca?id=1, por exemplo. Há ainda como fazer isso utilizando uma URL parametrizada:

@Get("usuario/busca/{id}")
public void busca(long id){ 
…
}

Neste caso um exemplo de URL seria /usuario/busca/1.

Também podemos receber objetos mais complexos, como no caso do método adiciona() que recebe um objeto Usuario:

@Post
public void adiciona(Usuario usuario){ ... }

Na view teríamos o formulario.jsp parecido com:

<form action=”/usuario/adiciona” method=”post”>
	<input type=”text” name=”usuario.nome”/>
	<input type=”text” name=”usuario.email”/>
<input type=”submit”  value=”Adicionar”>
</form>

 

Exemplos de parâmetros do request para este formulário seriam:

usuario.nome = Rodrigo Turini
usuario.email = rodrigoatturini@caelum.com.br
...

Manipulação do resultado

Para deixar os objetos dos métodos acessíveis pela página JSP podemos simplesmente retorná-los - da seguinte forma:

@Get
public List<Usuario> lista(){
	return usuarioDao.lista();
}

Como estamos retornando um List<Usuario>, o nome da variável acessada em sua view será ${usuarioList}. Se o retorno fosse um único objeto, a variável seria apenas ${usuario}.

Há outra forma de retornar objetos para a view: utilizando a interface especialista Result. Podemos pedir esse bean injetado em nosso controller e utilizar seu método include():

@Controller
public class UsuarioController {
	@Inject private Result result;
	@Inject private UsuarioDao usuarioDao;
	@Get
	public void lista(){
		List<Usuario> lista = usuarioDao.lista();
		result.include(lista);
		result.include("usuarios", lista);
	}
}

Na primeira chamada a include(), a variável incluída será ${usuarioList}, assim como no retorno do método. Porém repare que no segundo include() demos um nome para o objeto incluído; portanto será este o utilizado.

Existem diversos outros métodos no Result para nos auxiliar com o trabalho com a view. Por exemplo, veja como se pode devolver essa lista de objetos serializada em JSON:

@Get
public void listaEmJSON(){
	List<Usuario> usuarios = usuarioDao.lista();
	result.use(json()).from(usuarios).serialize();
}

O método json() vem da classe Results, que possui outros métodos para resultados comuns - como xml(), html() e jsonp(). Há ainda o método representation(), que retorna de acordo com o accept format do request.

Facilmente configurável

Tudo isso que vimos é facilmente configurável. Como suas classes são gerenciadas pelo CDI (managed beans) podemos especializar qualquer componente do VRaptor.

Por exemplo, para mudar a view renderizada por padrão, ou mudar o local em que é procurada, especializamos o DefaultPathResolver:

@Specializes
public class CustomPathResolver extends DefaultPathResolver {
    @Override
    protected String getPrefix() {
        return "/pasta/raiz/";
    }
}

Da mesma forma, pode-se mudar a convenção de URLs sobrescrevendo o PathAnnotationRoutesParser.

Integrando VRaptor com JPA

A integração com CDI também facilita o gerenciamento das classes que não são de nosso projeto. Integrar o VRaptor com JPA, por exemplo, é um processo simples. Pode-se escrever um producer para o EntityManager parecido com esse:

public class EntityManagerCreator {
	@Inject private EntityManagerFactory factory;
	@Produces @RequestScoped
	public EntityManager getEntityManager() {
		return factory.createEntityManager();
	}

	public void destroy(@Disposes EntityManager em) {
		if (em.isOpen()) {
			em.close();
		}
	}
}

Com isso, em qualquer bean da sua aplicação, é possível injetar esse objeto. Por exemplo:

public class UsuarioDao {
	@Inject private EntityManager em;
	public void adiciona(Usuario usuario) {
		em.getTransaction().begin();
		em.persist(usuario);
		em.getTransaction().commit();
	}
	...
}

Pode-se criar um interceptor simples para fazer o open transaction in view, mas isso e diferentes outros recursos já foram implementados nos diversos plugins para o VRaptor 4. Veja alguns desses plugins nessa página da documentação.

Mais sobre o Vraptor

Mais informações sobre o framework podem ser obtidas em sua documentação, que conta com guias de 1 e 10 minutos, cookbooks enviados por usuários e um guia rápido para auxiliar na migração de versões anteriores. Pode ser útil também ler mais sobre a especificação do CDI 1.1 e todos seus recursos, que se integram ao núcleo do Vraptor.

 

Sobre o autor

Rodrigo Turini é bacharel em Ciência da Computação, desenvolvedor e instrutor pela Caelum. Desenvolve sistemas em Java para web e atualmente foca seus estudos em programação funcional e Java 8, assuntos coberto no livro que escreveu com Paulo SIlveira.

Avalie esse artigo

Relevância
Estilo/Redação

Olá visitante

Você precisa cadastrar-se no InfoQ Brasil ou para enviar comentários. Há muitas vantagens em se cadastrar.

Obtenha o máximo da experiência do InfoQ Brasil.

Dê sua opinião

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão
Comentários da comunidade

VRaptor + JPA by Renan Batista

Gostaria de saber se esse exemplo de uso do JPA considera o Plugin do VRaptor para JPA, estou quebrando a cabeça nessa integração =/

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

1 Dê sua opinião
Feedback geral
Bugs
Publicidade
Editorial
Marketing
InfoQ Brasil e todo o seu conteúdo: todos os direitos reservados. © 2006-2016 C4Media Inc.
Política de privacidade
BT

We notice you’re using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.