VRaptor 3.0.2 lançado

34 respostas
Lucas_Cavalcanti

Olá,

com a contribuição da comunidade, apontando diversos bugs e dando sugestões, foi lançado o VRaptor 3.0.2,
com vários bugfixes e um jeito mais fácil de gerar JSON e XML como resultado das lógicas:

import static br.com.caelum.vraptor.view.Results.*;
//...
result.use(json()).from(usuario).include("roles").exclude("password").serialize();

vai gerar uma saída parecida com:

{"usuario": {
   "login": "lucascs"
   "email": "[email removido]"
   "roles": ["ADMIN", "USER"]  
}}

o método include e o exclude são opcionais, e por padrão o VRaptor vai serializar só os campos primitivos
(String, números, datas).

Esse suporte a JSON e XML ainda é inicial e básico, idéias para melhorá-lo são muito bem vindas.

Além disso foram criados CustomProviders para o Hibernate e JPA, que já registram as fábricas de
Session/EntityManager, e um interceptador que controla transações, chamados HibernateCustomProvider e JPACustomProvider.
Para usá-los, basta colocar no web.xml:

<context-param>
	<param-name>br.com.caelum.vraptor.provider</param-name>
	<param-value>br.com.caelum.vraptor.util.hibernate.HibernateCustomProvider</param-value>
</context-param>

ou para JPA:

<context-param>
	<param-name>br.com.caelum.vraptor.provider</param-name>
	<param-value>br.com.caelum.vraptor.util.jpa.JPACustomProvider</param-value>
</context-param>

Dentre os bugfixes podemos destacar:

  • suporte a containers servlet 2.4, como Oracle Container 10.1.3.1
  • Results.referer() agora implementa View
  • content-type agora é exposto pelo File/InputStream Download
  • o retorno do método agora é incluido no result quando acontece um forward.
  • os parâmetros da requisição são mantidos quando acontece um erro de validação.
  • lançando exceção quando o paranamer não consegue achar os metadados dos parâmetros,
    assim é possível se recuperar desse problema.

Mais uma vez gostaria de agradecer a todos os que mandaram sugestões e apontaram bugs, principalmente ao
garcia-jj, lavieri e Mário Peixoto.

Downloads em: http://vraptor.caelum.com.br/download.jsp
Documentação em: http://vraptor.caelum.com.br/documentacao

[]'s

34 Respostas

G

Hmm, cada dia melhor :slight_smile:

Só não entendi o “Results.referer() agora implementa View”. Qual a mudança que tem ao que era antes, que eu poderia fazer redirect/forward para o referer?

Lucas_Cavalcanti

O problema é que você só pode usar

result.use(algumaclasse)

se essa classe implementar View… e o RefererResult (Results.referer()) não implementava View…

G

Lucas, nessa nova versão esse hack aqui pode ser removido?

public void intercept(InterceptorStack stack, ResourceMethod method, Object instance)
        throws InterceptionException {
        // TODO: remove hack
        if (!accepts(method)) {
            stack.next(method, instance);
            return;
        }

        JSONObject json = (JSONObject) info.getResult();

        try {
            response.setContentType("application/json");
            PrintWriter out = response.getWriter();
            out.print(json.toString());
            out.flush();
            out.close();
        } catch (IOException e) {
            throw new InterceptionException(e);
        }
    }

Isso está em um componente meu para JSON que copiei do download interceptor.

Lucas_Cavalcanti

Esse interceptor não foi adicionado =(

a serialização para json só é feita via

result.use(json()).from(objeto).include(“path de fields nao primitivos”).exclude(“path de fields primitivos”).serialize();

se isso for mais fácil do que gerar o JSONObject pra vc… senão a gente pode integrar isso na próxima versão…

[]'s

G

Lucas, desculpa, o que eu queria dizer era sobre esse hack que estava com TODO para remover.

if (!accepts(method)) {  
    stack.next(method, instance);  
    return;  
}

Copiei isso do DownloadInterceptor. Mas fiz uns testes e pelo comportamento já dá para remover.

Lucas_Cavalcanti

Ah sim, isso foi corrigido sim =)

o VRaptor agora chama o accepts sempre…

juniorsatanas

lucascs Bom dia Mano !

Pelo que andei lendo tu sabe muito de Vraptor ! o que ta faltando é um exemplo completo… tipo loja virtual !

Eu fiz a loja todinha no VRaptor2, no 3 eu estou perdido !

   já li a documentação toda...  mais não saiu do lugar... 2 horas por dia eu estudo Vraptor 3 estou no 5 dia e estou frustrado !

Você não poderia disponibilizar um CRUD ?

Abraço Jr

Paulo_Silveira

Oi Junior!

Se voce baixar o mydvds, la tem mais que um CRUD.

E poste sua dificuldade do que nao esta funcionando em outra thread que a gente ve junto com voce.

abracos

Lucas_Cavalcanti

Olá junior,

vc chegou a ver o mydvds? Ele tem um CRUD lá, e mais algumas coisas…

http://vraptor3.googlecode.com/files/vraptor-mydvds-3.0.2.zip

Vc pode ser mais específico sobre quais são as suas dificuldades, por favor? para que a gente possa melhorar a documentação e exemplos

[]'s

juniorsatanas

Antes de mais nada parabéns pelo Vraptor 3 !

lucascs e Paulo Bom Dia !

Estou com um sistema em Vraptor2, feito por mim, (Contas a pagar).. a NUTEC, me convidou para iniciar um trabalho: 4 sistemas delphi para fazer em java + (Qual quer Framework).     Dentre GWT, jsf, VRaptor os Programadores aqui optaram por sugestão minha o mais simples de usar: VRAPTOR2, mas eu gostaria de fazer no Vraptor 3.

    que nos queríamos fazer tudo usando AJAX ! é possível ? tipo GWT ?

   Pegando o Mydvds do VRaptor 3 que  vem configurado posso fazer em cima, usando a estrutura dele ?


Como ficou as mudanças tipo :

/ (VRAPTOR)
|
| HibernateUtil (logica para configurar o hibernate) ----> hibernate.cfg.xml
| |
| |
| | |-------->Dao<T>(para não precisar construir varios Daos)
| | |-------->ClassisLogic (Logica para action)
| | | |
| | | |-------->Intereceptor (cria um DaoFactory e injeta na classe.)
| | | | |
| | | | |-------->UsuarioDao (em casos especiais.)
| | | |
| |-----------|--------------->DaoFactory (Construtor de Daos/Transações.)
| |
| |Classes com get e set etc…, (entidades)
|

Os Arquivos de Configuração ficam aonde ?

Obrigado e Grande Abraço !

Lucas_Cavalcanti

vc já deu uma olhada nessa página da doc? http://vraptor.caelum.com.br/documentacao/migrando-do-vraptor2-para-o-vraptor3/

usando o VRaptor3 vc não precisa dessa estrutura toda…

coloque isso no seu web.xml:

<context-param>
    <param-name>br.com.caelum.vraptor.provider</param-name>
    <param-value>br.com.caelum.vraptor.util.hibernate.HibernateCustomProvider</param-value>
</context-param>

E você não vai precisar do HibernateUtil nem do interceptor.

O nome das classes de lógica terão o sufixo Controller, e não Logic

Você não precisa ter um DaoFactory, basta anotar seus daos com @Component e recebê-los no construtor dos seus controllers

mas se ainda assim vc quiser um DaoFactory, basta anotá-lo com @Component e recebê-lo no construtor dos seus controllers. Receba uma Session do hibernate no construtor do DaoFactory (ou dos seus daos) e o VRaptor já vai te dar uma Session…

Lucas_Cavalcanti

ah, já ia me esquecendo: não tem arquivos de configuração no VRaptor3… vc só tem que cadastrar o filtro do Vraptor no web.xml

juniorsatanas

Veja como fica no Netbeans ! ta funcionando na boa ! mais como eu uso no postgresQL ?

&lt;?xml version='1.0' encoding='utf-8'?&gt;
&lt;!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&gt;
	
&lt;hibernate-configuration&gt;

	&lt;session-factory&gt;
	
		&lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.HSQLDialect&lt;/property&gt;
		&lt;property name="hibernate.connection.url"&gt;jdbc:hsqldb:mem:mydvdsDB&lt;/property&gt;
		&lt;property name="hibernate.connection.driver_class"&gt;org.hsqldb.jdbcDriver&lt;/property&gt;
		&lt;property name="hibernate.connection.username"&gt;sa&lt;/property&gt;
		&lt;property name="hibernate.connection.password"&gt;&lt;/property&gt;

		&lt;property name="hibernate.show_sql"&gt;false&lt;/property&gt;
		&lt;property name="hibernate.hbm2ddl.auto"&gt;update&lt;/property&gt;
		&lt;property name="hibernate.cache.provider_class"&gt;org.hibernate.cache.HashtableCacheProvider&lt;/property&gt;

 		&lt;mapping class="br.com.caelum.vraptor.mydvds.model.Dvd" /&gt;
 		&lt;mapping class="br.com.caelum.vraptor.mydvds.model.DvdCopy" /&gt;
 		&lt;mapping class="br.com.caelum.vraptor.mydvds.model.User" /&gt;

	&lt;/session-factory&gt;

&lt;/hibernate-configuration&gt;

ficaria assim !

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&gt;
&lt;hibernate-configuration&gt;
&lt;session-factory&gt;
&lt;property name="hibernate.connection.driver_class"&gt;com.mysql.jdbc.Driver&lt;/property&gt;
&lt;property name="hibernate.connection.password"&gt;123456&lt;/property&gt;
&lt;property name="hibernate.connection.url"&gt;jdbc:mysql://localhost:3306/lojavirtual&lt;/property&gt;
&lt;property name="hibernate.connection.username"&gt;root&lt;/property&gt;
&lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.MySQLDialect&lt;/property&gt;
&lt;property name="hibernate.show_sql"&gt;true&lt;/property&gt;
&lt;property name="hibernate.format_sql"&gt;true&lt;/property&gt;
&lt;mapping class="br.com.caelum.lojavirtual.modelo.Usuario"/&gt;
&lt;mapping class="br.com.caelum.lojavirtual.modelo.Cd"/&gt;
&lt;mapping class="br.com.caelum.lojavirtual.modelo.Musica"/&gt;
&lt;mapping class="br.com.caelum.lojavirtual.modelo.Venda"/&gt;
&lt;/session-factory&gt;
&lt;/hibernate-configuration&gt;
&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"&gt;
&lt;log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"&gt;
        
        &lt;appender name="stdout" class="org.apache.log4j.ConsoleAppender"&gt;
                &lt;layout class="org.apache.log4j.PatternLayout"&gt;
                        &lt;param name="ConversionPattern" 
                                value="%d{HH:mm:ss,SSS} %5p [%-20c{1}] %m%n"/&gt;
                &lt;/layout&gt;
        &lt;/appender&gt;

        &lt;category name="br.com.caelum.vraptor"&gt;
	        &lt;priority value="DEBUG" /&gt;
	        &lt;appender-ref ref="stdout" /&gt;
	    &lt;/category&gt;
	    &lt;category name="br.com.caelum.vraptor.interceptor.multipart"&gt;
	        &lt;priority value="ERROR" /&gt;
	        &lt;appender-ref ref="stdout" /&gt;
	    &lt;/category&gt;

        &lt;category name="org.hibernate"&gt;
                &lt;priority value="WARN" /&gt;
                &lt;appender-ref ref="stdout" /&gt;
        &lt;/category&gt;

&lt;/log4j:configuration&gt;

Lucas_Cavalcanti

só configurar o banco no hibernate.cfg.xml

juniorsatanas

o log4 nao precisa ?
Você viu que fica tudo doido no netBeans ? deu maior trabalho para importar ! aff

Eu acho que na nova apostila da Caelum vocês tem que por essas mudanças, e rodar ele no Eclipse e no Netbeans… pois nos Usuarios do Netbeans sofremos muito para rodar coisas feitas no Eclipse…

1 * mudanças de configuração
   2 *estrutura das pastas - eclipse - netbeans
   3* arquivos de configuração

etc…
Estou tentando rodar o Mydvds no NetBeans com o Banco PostgreSQL/Mysql/Firebird para testar !

Grande Abraço…

Lucas_Cavalcanti

se vc quiser ver logs precisa…
mas não é obrigatório…

juniorsatanas

Por que mudou tanto o VRaptor ? por causa do Spring e do Pico ? estruturalmente !

Tenho maior vontade de mexer no miolo do vraptor para aprender mais falta tempo.

Valeu Abraço lucascs.

Lucas_Cavalcanti

O VRaptor mudou tanto pois foi rescrito do zero. Ele agora está usando muitas idéias que ainda não eram mto usadas qdo o vraptor 2 foi feito…

a principal é a de Injeção de Dependências, e pra isso o Spring é usado… Isso torna muitas coisas bem mais simples de fazer

juniorsatanas
Lucas, É possivel usar o VR3 para produzir páginas do tigo GWT, que são ajax ? ou essa integração ficaria a cabo do JQuery/Scriptaculos/Dojo/etc..
Como ficaria isso ? a Lógica ? pois JSF/GWT/ etc.. tem esses recursos.

Eu uso o JQuery, para mostra telas thichibox etc… mas para postar dados, recuperar dados, mostrar numa grid, tudo usando ajax eu nem tenho ideia se da para fazer usando VRaptor !

ps: claro que cada sistema tem seu caso. flw

Lucas_Cavalcanti

O Vraptor é capaz de gerar e consumir JSon, então é só você integrar isso com o plugin do JQuery/Dojo/etc ou com os componentes visuais do GWT

juniorsatanas

JSon - e mesmo…
fontes: http://blog.caelum.com.br/2006/11/08/ajax-no-vraptor-json-da-maneira-facil/

Lucas_Cavalcanti

Não é mais assim que se faz…

é assim:
http://vraptor.caelum.com.br/documentacao/view-e-ajax/

juniorsatanas

Lucas, eu faço as tags no js, mando elas ser recuperadas via JSON e mostro é isso ?

JSP <-------------------------json-------------------------xml---------------------------------java

OU eu estou errado !?

Lucas_Cavalcanti

via ajax, você pode tanto pedir um pedaço de página, ou um JSON… vc nunca vai escrever JSP via javascript…

a sequência:

browser --> ajax --> java --> json --> javascript --> html

o browser manda uma requisição ajax pra sua aplicação, que vai retornar um json, que vc vai ler e gerar/modificar um pedaço da sua página usando javascript

ou:
browser --> ajax --> java --> html snippet --> javascript --> html
mesmo acima, só que vc recebe um pedaço de html e coloca direto na página

[]'s

juniorsatanas

lucascs Obrigado péla dica !

Agora Clareou a Dúvida !

browser --&gt; ajax --&gt; java --&gt; json --&gt; javascript --&gt; html

          browser --&gt; ajax --&gt; java --&gt; html snippet --&gt; javascript --&gt; html

Mais não achei nem 1 exemplo usando isso ! acho que ninguém usa AJAX + Vraptor com essa finalidade !

Você tem alguma coisa feita ai ?

Lucas_Cavalcanti

me fala o que vc quer fazer, que eu te dou um exemplo…

de qqer forma, esse projeto tem várias chamadas ajax e efeitos visuais, usando vários plugins do JQuery, se quiser dar uma olhada:

http://calopsita.caelum.com.br/ ==> em produção
http://github.com/caelum/calopsita ==> código fonte

juniorsatanas

Lucas, aqui somos 4 programadores, todos eles qurem fazer em php ou em jsf + myface, eu quero mostrar para eles um exemplo em VRaptor que seja todo em ajax…

Cadastrar Clientes
Autocompletar (sei fazer pelo mydvds)
Listar Usuario

Entendeu ?

juniorsatanas

Com este código da para entender muita coisa do VR3

http://github.com/caelum/calopsita ==> código fonte

Valeu Cara !

Lucas_Cavalcanti

qualquer dúvida mais específica diga...

um exemplo completo do autocomplete (tirado da apostila do curso do VRaptor na caelum):

[section Melhorando a busca: Autocomplete]

Podemos ainda melhorar nossa busca, mostrando dicas de produtos já existentes enquanto o usuário
está digitando. Queremos um resultado parecido com este:

<>

Para isso vamos usar um plugin do JQuery chamado AutoComplete
(http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/)
que faz ::autocomplete:: de campos de texto. Esse plugin faz uma requisição ajax para uma URL
que retorna um JSON com os dados que vão aparecer no autocomplete.

Por causa desse plugin, precisamos criar uma lógica que gere um JSON para nós. No VRaptor, gerar
JSON é bem simples:

import static br.com.caelum.vraptor.view.Results.*;
//...
	@Get @Path("/produtos/busca.json")
	public void buscaJson(String nome) {
		result.use(json()).from(dao.busca(nome)).serialize();
	}

Ou seja, você passa para o método %%from()%% o que você quer serializar em JSON. Pode ser um objeto
qualquer, mas no nosso caso vai ser uma lista. Ao chamarmos a URI desse método no browser, passando
um nome qualquer, por exemplo %%http://localhost:8080/goodbuy/produtos/busca.json?nome=a%% é retornado
um JSON parecido com:

{"list": [
  {
    "id": 1,
    "nome": "Sabonete",
    "descricao": "Um sabonete com perfume de lavanda",
    "preco": "3.53"
  },
  {
    "id": 3,
    "nome": "Sapato",
    "descricao": "um sapato de couro",
    "preco": "132.00"
  }
]}

Mas como vamos buscar os produtos apenas por nome, não precisamos de todas essas informações, só
precisamos de uma lista de nomes, talvez com o preço. Para isso podemos excluir as outras propriedades:

import static br.com.caelum.vraptor.view.Results.*;
//...
	@Get @Path("/produtos/busca.json")
	public void buscaJson(String nome) {
		result.use(json()).from(dao.busca(nome))
			.exclude("id", "descricao")
			.serialize();
	}
Gerando o seguinte json:
{"list": [
  {
    "nome": "Sabonete",
    "preco": "3.53"
  },
  {
    "nome": "Sapato",
    "preco": "132.00"
  }
]}

Agora estamos prontos para usar o plugin de ::autocomplete::. Para isso, abra o arquivo "header.jspf",
e adicione o javascript e o css do plugin. Use o mesmo lugar do plugin Puts:

<link href="<c:url value="/javascripts/jquery.autocomplete.css"/>" 
				rel="stylesheet" type="text/css" media="screen" />
<script type="text/javascript" 
			src="<c:url value="/javascripts/jquery.autocomplete.min.js"/>"></script>
...
<script type="text/javascript">
	$("#busca").puts("Busca produtos por nome");
	$("#busca").autocomplete('/goodbuy/produtos/busca.json');
</script>
[/xml]

Isso deveria ser o suficiente, mas o plugin AutoComplete espera que você mande os dados separados por pipe(|)
ou um dado por linha. Como queremos usar JSON, precisamos configurar isso no plugin:
[code]
$("#busca").autocomplete('/goodbuy/produtos/busca.json', {
		dataType: "json", // pra falar que vamos tratar um json
		parse: function(json) { // para tratar o json
			// a função map vai iterar por toda a lista, 
			// e transformar os dados usando a função passada
			return $.map(json.list, function(produto) {
				return  {
					data: produto, // todos os dados do produto
					value: produto.nome, // o valor lógico do produto
					result: produto.nome // o que vai aparecer ao selecionar
				};
			});
		},
		formatItem: function(produto) { // o que vai aparecer na lista de autocomplete
			return produto.nome + "(" + produto.preco + ")";
		}
});
Além disso, o plugin passa como parâmetro da requisição o que você digitou no input, numa variável chamada %%q%% então você precisa modicar a lógica de busca para o parâmetro se chamar %%q%%:
@Get @Path("/produtos/busca.json")
public void buscaJson(String q) {
	result.use(json()).from(dao.busca(q))
		.exclude("id", "descricao")
		.serialize();
}
G

Após o lançamento da versão o vraptor3 que faz a serialização transparente de XML/JSON vejo o vraptor como o melhor para trabalhar com Ajax.

Se você fazer um casamento com jquery ou prototype então nem se fala.

juniorsatanas

garcia-jj , então vale a pena ! Vou estudar bastante JSON.

valeu Galera !

H
Neste exemplo:
<div id="menu">
<ul>
<li><a href="<c:url value="/produtos/novo"/>">Novo Produto</a></li>
<li><a href="<c:url value="/produtos"/>">Lista Produtos</a></li>
<li><form action="<c:url value="/produto/busca"/>">
<input id="busca" name="nome"/>
</form>
<script type="text/javascript">
$("#busca").puts("Busca produtos por nome");
$("#busca").autocomplete(?/goodbuy/produtos/busca.json?, {
dataType: "json",
parse: function(data) {
return $.map(data.list, function(produto) {
return {
data: produto,
value: produto.nome,
result: produto.nome
};
});
},
formatItem: function(produto) {
return produto.nome + "(" + produto.preco + ")";
}
});
</script>
</li>
</ul>
</div>

Funciona perfeitamente o autocomplete, mas como eu faria para retirar os scripts desta página jsp e colocar em um arquivo separado?

Eu criei um arquivo busca_autocomplete.js, removi as tags