22Migrando do VRaptor2 para o VRaptor3
web.xml
Para migrar aos poucos, basta colocar no seu web.xml:
<context-param>
<param-name>br.com.caelum.vraptor.packages</param-name>
<param-value>br.com.caelum.vraptor.vraptor2</param-value>
</context-param>
<filter>
<filter-name>vraptor</filter-name>
<filter-class>br.com.caelum.vraptor.VRaptor</filter-class>
</filter>
<filter-mapping>
<filter-name>vraptor</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
e colocar os JARs da pasta lib/mandatory e lib/containers/
Lembre-se de tirar a declaração antiga do VRaptorServlet do VRaptor2, e o seu respectivo mapping.
Migrando de @org.vraptor.annotations.Component para @br.com.caelum.vraptor.Resource
O correspondente ao @Component do VRaptor2 é o @Resource do VRaptor3. Portanto, para disponibilizar os métodos de uma classe como lógicas é só anotá-las com @Resource (removendo o @Component).
As convenções usadas são um pouco diferentes:
No VRaptor 2:
@Component
public class ClientsLogic {
public void form() {
}
}
No VRaptor 3:
@Resource
public class ClientsController {
public void form() {
}
}
O método form estará acessível pela uri: "/clients/form", e a view padrão será a WEB-INF/jsp/clients/form.jsp. Ou seja, o sufixo Controller é removido do nome da classe e não tem mais o sufixo .logic na URI. Não é colocado o resultado "ok" ou "invalid" no nome do JSP.
@In
O VRaptor3 gerencia as dependências para você; logo, o que você usava como @In no vraptor2, basta receber pelo construtor:
No VRaptor 2:
@Component
public class ClientsLogic {
@In
private ClientDao dao;
public void form() {
}
}
No VRaptor 3:
@Resource
public class ClientsController {
private final ClientDao dao;
public ClientsController(ClientDao dao) {
this.dao = dao;
}
public void form() {
}
}
E, para que isso funcione, você só precisa que o seu ClientDao esteja anotado com o @br.com.caelum.vraptor.ioc.Component do VRaptor3.
@Out e getters
No VRaptor2 você usava a anotação @Out ou um getter para disponibilizar um objeto para a view. No VRaptor3 basta retornar o objeto, se for um só, ou usar um objeto especial para expor os objetos para a view. Este objeto é o Result:
No VRaptor 2:
@Component
public class ClientsLogic {
private Collection<Client> list;
public void list() {
this.list = dao.list();
}
public Collection<Client> getClientList() {
return this.list;
}
@Out
private Client client;
public void show(Long id) {
this.client = dao.load(id);
}
}
No VRaptor 3:
@Resource
public class ClientsController {
private final ClientDao dao;
private final Result result;
public ClientsController(ClientDao dao, Result result) {
this.dao = dao;
this.result = result;
}
public Collection<Client> list() {
return dao.list(); // o nome será clientList
}
public void listaDiferente() {
result.include("clients", dao.list());
}
public Client show(Long id) {
return dao.load(id); // o nome será "client"
}
}
Quando você usa o retorno do método, o vraptor usa o tipo do retorno para determinar qual vai ser o seu nome na view. No caso de uma classe normal, o nome do objeto será o nome da classe com a primeira letra minúscula. No caso de ser uma Collection, o nome será o nome da classe, com a primeira minuscula, seguido da palavra List.
views.properties
No VRaptor3 não existe o arquivo views.properties, embora ele seja suportado no modo de compatibilidade com o VRaptor2. Todos os redirecionamentos são feitos na própria lógica, usando o Result:
@Resource
public class ClientsController {
private final ClientDao dao;
private final Result result;
public ClientsController(ClientDao dao, Result result) {
this.dao = dao;
this.result = result;
}
public Collection<Client> list() {
return dao.list();
}
public void save(Client client) {
dao.save(client);
result.redirectTo(ClientsController.class).list();
}
}
Se o redirecionamento for para uma lógica, você pode referenciá-la diretamente, e os parâmetros passados para o método serão usados para chamar a lógica.
Se for para uma JSP direto você pode usar:
result.forwardTo("/WEB-INF/jsp/clients/save.ok.jsp");
Validação
Você não precisa criar um método validateNomeDaLogica para fazer a validação, basta receber no construtor um objeto do tipo br.com.caelum.vraptor.Validator, e usá-lo para sua validação, especificando qual é a lógica para usar quando a validação dá errado:
@Resource
public class ClientsController {
private final ClientDao dao;
private final Result result;
private final Validator validator;
public ClientsController(ClientDao dao, Result result, Validator validator) {
this.dao = dao;
this.result = result;
this.validator = validator;
}
public void form() {
}
public void save(Client client) {
if (client.getName() == null) {
validator.add(new ValidationMessage("erro","nomeInvalido"));
}
validator.onErrorUse(Results.page()).of(ClientsController.class).form();
dao.save(client);
}
}
Colocando objetos na sessão
No VRaptor2 bastava colocar um @Out(ScopeType.SESSION) para que o objeto fosse colocado na sessão. Isso não funciona no VRaptor3, pois você perde totalmente o controle sobre as variáveis que estão anotadas desse jeito.
Para colocar objetos na sessão no VRaptor3 você deve fazer uma das duas coisas:
O objeto vai ser acessível apenas por lógicas e componentes da aplicação, não pelos JSPs:
@Component
@SessionScoped
public class MeuObjetoNaSessao {
private MeuObjeto meuObjeto;
//getter e setter para meuObjeto
}
E nas classes onde você precisa do MeuObjeto basta receber no construtor o MeuObjetoNaSessao e usar o getter e setter pra manipular o MeuObjeto.
O objeto vai ser acessível nos jsps também:
@Component
@SessionScoped
public class MeuObjetoNaSessao {
private HttpSession session;
public MeuObjetoNaSessao(HttpSession session) {
this.session = session;
}
public void setMeuObjeto(MeuObjeto objeto) {
this.session.setAttribute("objeto", objeto);
}
public MeuObjeto getMeuObjeto() {
return this.session.getAttribute("objeto");
}
}
E nas classes basta receber o MeuObjetoNaSessao no construtor e usar o getter e o setter.