GenericController para Crud no VRaptor3

59 respostas
rafaelunp

Amigos,

Caso eu quisesse fazer um GenericController para utilizar em 80% das minhas telas de CRUD, como eu poderia generalizar os @Path?

No Spring MVC eu faria nos métodos da classe Genérica:
@RequestMapping(value=“new”, method = RequestMethod.GET)
@RequestMapping(value="/", method = RequestMethod.GET)
@RequestMapping(value="/save", method = RequestMethod.POST)

e
@RequestMapping("/cliente") na classe filha

Abs

59 Respostas

G

Desculpe fugir um pouco da tua pergunta, afinal realmente não sei como fazer um controller genérico.

Mas… você realmente precisa disso? Penso nisso porque muitos cadastro as vezes parecem iguais, mas nem sempre são. Você pode pensar que são apenas essas 4 operações básicas (listar, exibir, gravar, excluir), mas no futuro pode ser que isso mude. Além disso você precisa de validações diferentes para as entidades, então penso o quanto pode ser perigoso fazer coisas genéricas.

Obvio que você precisa sempre pensar em ter o mínimo de trabalho, escrever menos códigos, mas nem sempre generalizar ajuda nisso. Além disso como ficam as validações? São genéricas também? No caso todos possuem os mesmos campos?

Abraços

rafaelunp

garcia-jj:
Desculpe fugir um pouco da tua pergunta, afinal realmente não sei como fazer um controller genérico.

Mas… você realmente precisa disso? Penso nisso porque muitos cadastro as vezes parecem iguais, mas nem sempre são. Você pode pensar que são apenas essas 4 operações básicas (listar, exibir, gravar, excluir), mas no futuro pode ser que isso mude. Além disso você precisa de validações diferentes para as entidades, então penso o quanto pode ser perigoso fazer coisas genéricas.

Obvio que você precisa sempre pensar em ter o mínimo de trabalho, escrever menos códigos, mas nem sempre generalizar ajuda nisso. Além disso como ficam as validações? São genéricas também? No caso todos possuem os mesmos campos?

Abraços

Eu teria as validações do Hibernate Validator e teria também um metodo beforeCreateImpl (por exemplo) no GenericController, onde nas classes filhas eu poderia implementar a respectiva validação.
Até este ponto não vejo nenhum problema em se fazer o GenericController.
Como eu disse são 80% dos casos (no caso do meu sistema).

Lucas_Cavalcanti

você pode tranquilo gerar um controlador genérico:

//não coloque @Resource aqui
public class GenericController<T> {
    @Get public void novo() {...}
    @Get public void mostra(T entidade) {...}
    ...
}

e criar os controllers:

@Resource
public class ProdutoController extends GenericController<Produto> {...}

as urls vão seguir o padrão: /produto/novo, /produto/mostra…

mas cuidado com os nomes de parâmetro, vc vai ter que colocar um nome genérico e usar em todos os lugares…

a gente está pensando em gerar algum jeito de colocar convenções para que as operações básicas do CRUD funcionem mais fácil… mais isso só pra depois da versão 3.1

G

Lucas, veja bem como funciona quando o cara desconhece a coisa…

Eu estava a pouco revisando o código do vraptor para propor uma solução daquelas mirabulosas de sobrescrever o tradutor de rotas -> controller, e blah blah blah…

Mas… a coisa é beeeem mais simples do que a gente imagina. :oops:

A propósito, quando sai aquela sugestão do laviery para a annotation @Path funcionar a nivel de classe?

Lucas_Cavalcanti

Tá marcado pro próximo release (3.0.3)… mas a gente não sabe ainda quando vai lançar :wink:

lscosta

Buenas! Estou tentado obter o seguinte:

/funcionario/edit/15

ou

/funcionario/delete/15

com a seguinte rota genérica:

Meu controller genérico tem:

public void edit(Long id) {
		result.include(entityName, repository.findById(id));
		viewForm();
	}

	public void delete(Long id) {
		repository.delete(id);
		viewList();
	}

Mas recebo este erro:

java.lang.NullPointerException java.lang.String.replace(String.java:2207) br.com.caelum.vraptor.http.route.PatternBasedType.apply(PatternBasedType.java:70) br.com.caelum.vraptor.http.route.PatternBasedStrategy.resourceMethod(PatternBasedStrategy.java:68) br.com.caelum.vraptor.http.route.DefaultRouter.parse(DefaultRouter.java:99) br.com.caelum.vraptor.http.DefaultResourceTranslator.translate(DefaultResourceTranslator.java:53) br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:64) br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:45) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:60) br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91) br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55) br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88) com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129) com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)

Esse mapeamento genérico de rotas funciona com passagem de parâmetros? Essa forma está correta?

Lucas_Cavalcanti

troca a linha do router por:

routeFor("/{webLogic}/{webMethod}/{id}").is(type("br.com.company.app.controller.{webLogic}Controller"), method("{webMethod}"));

e use as URIs do seguinte jeito:

/Funcionario/edit/23
/Gerente/edit/24

etc

essa parte de rotas genéricas está beeeem simples, então ela não consegue fazer os lowercases da vida…

lscosta
putz, mas que falta de atenção...  =P

quanto aos lowercases da vida, tbm parece ser beeem simples... eu tenho como mudar isso?

valeu Lucas!

putz, mas que falta de atenção… =P

quanto aos lowercases da vida, tbm parece ser beeem simples… eu tenho como mudar isso?

valeu Lucas!

Lucas_Cavalcanti

não sem mudar um monte de coisa =(

essa parte não evoluiu mto pq não tinha ninguém usando… então ficou zuadinha…

abre uma issue no github (http://github.com/caelum/vraptor/issues) sobre como vc quer essa feature, ou explica ela aqui nesse tópico que eu abro a issue, por favor?

lscosta

Cara, seria basicamente o nome do controlador ser tratado de modo case insensitive dentro do método routeFor

De modo que para o controller GerenteMuthafuckerController eu pudesse invocar “/gerenteMuthafucker/edit/15” ou “/GerenteMuthafucker/edit/15” ou “/gerentemuthafucker/edit/15”

Falando assim parece simples, claro que não sei qual o impacto no código…

lscosta

Lucas, criei a issue no github!

Valeu!

G

Lucas, uma sugestão minha, já que será mexido nessas lógicas, uma forma que pudesse ser confugurável via parametro ou sobrescrita de classe que pudessemos tratar os urls como upper, lower, camel-case ou com hifenização. O vraptor poderia ter uma padrão, que atualmente é camel-case, e que pudessemos então sobrescrever uma classe qualquer a forma que quisessemos que fosse feito.

O que você acha?

Lucas_Cavalcanti

obrigado por abrir a issue =)

o chato de tentar todas as possibilidades é que o VRaptor faz um Class.forName na string
br.com.company.app.controller.{webLogic}Controller
substituindo o {webLogic} pelo que vc passou na URI.

se seu nome de controller tiver 10 ele vai ter que dar Class.forName em até 2^10 classes, o que é completamente inviável…

o máximo que pode fazer é colocar a primeira letra para maiúsculo, sempre…

@garcia-jj
dá pra vc sobrescrever o PathAnnotationRoutesParser.extractControllerNameFrom(Class<?> type) e colocar qualquer estratégia =)

G

No meu caso eu queria todas as URIs com hifenização, exemplo, /user/store-groups, então eu implementei a interface RoutesParser. O problema é que eu tive que implementar toda ela, pois os métodos de PathAnnotationRoutesParser (implementação padrão usada no vraptor3) são todos privados. Acho que uma solução boa era que o método getURIsFor (e seus dependentes) fosse possível sobrescrever, assim eu posso fazer minha própria nomenclatura para os URIs.

Lucas_Cavalcanti

tenta isso:

public class HifenizadorRoutesParser extends PathAnnotationRoutesParser {
   @Override
   protected String defaultUriFor(String controllerName, String methodName) {
		return hifeniza(controllerName) + "/" + hifeniza(methodName);
	}
}
lscosta

Lucas,

O que pensei é que somente dentro do método routeFor a string pudesse ser convertida para lowercase. Assim seria compatível com qualquerCoisaQueEuPassasse…

“gerentegeral” == “GerenteGeral”.toLowerCase()

Certamente não tentaria “2^N Class.forName”… =)

A hifenização ao modo rails também é uma alternativa, e talvez mais fácil de implementar: “/gerente-geral/edit/15”

Lucas_Cavalcanti

só que a alternativa rails fica difícil de fazer o class.forName (do jeito que tá o codigo)

vou refatorar pra deixar mais personalizável

G

Lucas, não pude usar esse método porque eu preciso de mais um um padrão de URL para os metodos. Por exemplo os métodos de listagem aceitam tanto um /user/ como um /user/page-x/.

Abraços

G
lscosta:
A hifenização ao modo rails também é uma alternativa, e talvez mais fácil de implementar: "/gerente-geral/edit/15"

Hifenização, na minha opinião, seria algo perfeito, e foi o que eu tentei fazer no meu projeto. O problema se isso entra no padrão do vraptor é quebrae a compatibilidade, já que atualmente é camel-case.

No meu projeto os URIs ficaram como /pacote/classe/metodo/, sendo por exemplo:

package br.com.caelum.security;

public class UserController {
    public void list(); //acessado via /security/user/list/
    public void edit(Long id); //acessado via /security/user/edit/{id}/
}
lscosta

Acho que não deveria quebrar… Visto que no java não podemos criar classes ou pacotes com hifem, bastaria um tratamento a mais: SE houver hifen, remove e dá um upper no caracter seguinte… Meio braçal, mas resolve em uma linha. Parece ser o mais simples.

Não sei se prefiro a hifenização, mas de qualquer forma, é uma boa convenção. Acho que o ideal seria que, sendo uma url, pudesse ser acessada de forma cAsE iNsEnSiTiVe…

Qualquer refatoração alí será bem-vinda! Mas como usuário, prefiro seguir uma convenção/facilidade do framework mais que ter flexibilidade de escrever meu prórprio mecanismo.
E o vRaptor tem mandado bem nesse sentido!

Valeu!

G

lscosta:
garcia-jj:

Hifenização, na minha opinião, seria algo perfeito, e foi o que eu tentei fazer no meu projeto. O problema se isso entra no padrão do vraptor é quebrae a compatibilidade, já que atualmente é camel-case.

Acho que não deveria quebrar… Visto que no java não podemos criar classes ou pacotes com hifem, bastaria um tratamento a mais: SE houver hifen, remove e dá um upper no caracter seguinte… Meio braçal, mas resolve em uma linha. Parece ser o mais simples.

Não sei se prefiro a hifenização, mas de qualquer forma, é uma boa convenção. Acho que o ideal seria que, sendo uma url, pudesse ser acessada de forma cAsE iNsEnSiTiVe…

O que eu quero dizer que hoje se você não coloca @Path o padrão é nomeDoController/meuMetodo. Se você passar a tratar por padrão tudo com hifens os links de aplicações já prontas não funcionariam mais. Por exemplo, um URI que era antes tratado conforme meu exemplo agora será tratado como nome-do-controller/meu-metodo. Sendo assim os links se quebram mandando a retrocompatibilidade pro buraco.

Lucas_Cavalcanti

o que dá pra fazer é deixar um componente que já faz a hifenização disponível se vc quiser usar… mas por padrão não usar esse componente…
trocar a convenção agora é meio inviável…

quanto a só pegar a URI com hifens e transformar em camel-case antes de procurar um método que trate, não tem um jeito fácil de fazer isso…
precisa refatorar um pouco a estrutura interna… mas nada mto mirabolante :stuck_out_tongue:

G

Pois é Lucas, foi isso que pensei, uma forma de flexibilizar apenas. O resto a gente faz customizado.

Abraços

rafaelunp

Amigos,

Ainda sobre o GenericController...

Eu fiz o seguinte:

public class GenericController<T> {
	@Post
	public void save(final T obj) {

		try {
			dao.saveOrUpdate(obj);
			result.include("mensagem", "Operação efetuada com sucesso.");
		} catch (Exception e) {
			e.printStackTrace();
			validator.add(new ValidationMessage(e.getMessage(), "error"));
		}

		validator.onErrorUse(Results.page()).of(getClass()).form();
		result.use(Results.logic()).redirectTo(getClass()).list();

	}
}

Quando eu chamo através do formulário, o metodo save, com o objeto populado, eu recebo essa exception:

java.lang.IllegalArgumentException: Unable to identify field T of type sun.reflect.generics.reflectiveObjects.TypeVariableImpl
	br.com.caelum.vraptor.http.asm.AsmBasedTypeCreator.typeFor(AsmBasedTypeCreator.java:96)
	br.com.caelum.vraptor.reflection.CacheBasedTypeCreator.typeFor(CacheBasedTypeCreator.java:54)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createViaOgnl(OgnlParametersProvider.java:122)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createRoot(OgnlParametersProvider.java:116)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.getParametersFor(OgnlParametersProvider.java:92)
	br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:63)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:45)
	br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
	com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)

Alguma sugestão de onde estou errando?

lscosta

:shock:
Podia jurar que essa era a saída mais simples… Se transformar a uri hifenizada em CamelCase não dá pra usar a solução que tem hoje??

Acho que to precisando espiar o código pra não falar besteira, pq essa literalmente, me parece um “if” em meio ao que já tem… =)

lscosta

@rafaelunp

Tu está estendendo a GenericController? A "olho nú" parece que tu estás submetendo direto pra ela...

Se for isso, tu podia inclusive tornar ela abstrata...

tipo:

public abstract class GenericController<T> { ... }

e
 
public class PessoaController extends GenericController<Pessoa> { ... }

Dessa forma, tu deveria submeter para o PessoaController... Está parecido com isso? Se sim, deveria funcionar...

rafaelunp
lscosta:
public abstract class GenericController<T> { ... }
e
public class PessoaController extends GenericController<Pessoa> { ... }

Dessa forma, tu deveria submeter para o PessoaController... Está parecido com isso? Se sim, deveria funcionar...

Eu fiz:

public abstract class GenericController<T> {
}

e

@Resource
public class LivroController extends GenericController<Livro> {


	public LivroController(LivroDAO dao, Result result, Validator validator) {
		super(dao, result, validator);
	}

}

O erro que falei acima, continua...
Inclusive no debug, não entra nem no metodo save...

lscosta

É verdade, isso não está funcionando…

Para testes, eu ‘generifiquei’ um controlador que já tinha, e por descuido estava chamando o save do original… Agora que ajustei, obtive o mesmo erro. =P

Lucas_Cavalcanti

@rafaelunp
O VRaptor usa o tipo do parâmetro pra fazer algumas lógicas…
qdo vc usa um tipo genérico (T) ele não tem como descobrir esse tipo em Runtime =(
ou pelo menos, precisa fazer umas mágicas com genericSuperclasss. mas isso não tá implementado ainda…

@lscosta
seria simples como um if mesmo… mas na situação do código atual não dá pra fazer essa extensão facilmente…
não posso transformar por padrão as URIs com hifen pra camel case, pois a pessoa pode criar URIs do tipo:

@Path("/abc-${def}-ghi-${jkl}

e se eu transformo pra camelCase esse path nunca vai ser chamado

existe uma outra saída, que é implementar o ResourceNotFoundHandler, pra qdo não encontrar um recurso, tentar
trocar hifens por camel-cases e procurar de novo…

rafaelunp

lucascs:
@rafaelunp
O VRaptor usa o tipo do parâmetro pra fazer algumas lógicas…
qdo vc usa um tipo genérico (T) ele não tem como descobrir esse tipo em Runtime =(
ou pelo menos, precisa fazer umas mágicas com genericSuperclasss. mas isso não tá implementado ainda…

Entao é inviável o GenericController utilizando metodos tipo:

?

Lucas_Cavalcanti

no momento é inviável pq não tá implementado :stuck_out_tongue:

mas eu vou criar uma issue pra suportar classes genéricas…

G

Essas coisas de usar generics para tornar algo “genérico” dá mais problemas do que solução. Não vejo muito uma razão sustentável para você ter um controller genérico. No próprio padrão MVC o controller é algo específico. Não vejo como elegante generalizar isso. É que nem aquele exemplo de DAO genérico, que deveria chamar-se bizarre-generic-dao.

Aliás nenhum framework web faz isso.

Acho que implementar uma forma de deixar flexível a tradução/localização de URI para controller/método é muito boa,mas implementar um controller genérico ficou muito esquisito.

rafaelunp:
lucascs:
@rafaelunp
O VRaptor usa o tipo do parâmetro pra fazer algumas lógicas…
qdo vc usa um tipo genérico (T) ele não tem como descobrir esse tipo em Runtime =(
ou pelo menos, precisa fazer umas mágicas com genericSuperclasss. mas isso não tá implementado ainda…

Entao é inviável o GenericController utilizando metodos tipo:

?

lscosta
rafaelunp:
lucascs:
@rafaelunp O VRaptor usa o tipo do parâmetro pra fazer algumas lógicas... qdo vc usa um tipo genérico (T) ele não tem como descobrir esse tipo em Runtime =( ou pelo menos, precisa fazer umas mágicas com genericSuperclasss. mas isso não tá implementado ainda...

Entao é inviável o GenericController utilizando metodos tipo:

public void save(final T obj) {}

?

Se você achar que vale a pena, pode fazer assim até que a issue seja implementada:

@Resource  
public class LivroController extends GenericController<Livro> {  
  
    public LivroController(LivroDAO dao, Result result, Validator validator) {  
        super(dao, result, validator);  
    }  

	@Override
	@Path(value = "/livro/save", priority = 1)
	public void save(Livro obj) {
		super.save(obj);
	}
	
}
No meu caso não vale a pena pq além de isso ser meio bisonho, tenho 1 ou 2 linhas de código nas actions de CRUD.

[]'s

Lucas_Cavalcanti

nessa solução do lscosta, acho que nem precisa do @Path

lscosta

Humn… Cara, eu sou totalmente a favor de REUSO. Bizarro, ao meu ver, é ter código duplicado.

Todos meus controladores de CRUD precisam ter (pelo menos) os esses métodos:

public void list()

public void save(E entity)

public void edit(Long id)

public void add()

public void delete(Long id)

public void search(E entity)

public void form()

Além disso, é esperado que haja um comportamento padrão de relacionamento entre esses métodos…

É mais ‘elegante’ eu reescrever sempre tudo isso em vez de ter um “AbstractCRUDController” que eu pudesse estender e especializar ao meu gosto? A minha resposta é NÃO!

De repente vc viu algum exemplo feio de DAO genérico… O que eu uso (baseado nos exemplos do site do hibernate) me poupa tranquilamente uns 70% de trabalho ao criar um novo cadastro. Se eu não precisar reescrever os métodos do Controlador, minha produtividade aumentará ainda mais. Frameworks existem para cuidar da parte chata. E devemos tirar o máximo deles.

Dont Repeat Yourself

rafaelunp
lscosta:
@Resource  
public class LivroController extends GenericController<Livro> {  
  
    public LivroController(LivroDAO dao, Result result, Validator validator) {  
        super(dao, result, validator);  
    }  

	@Override
	@Path(value = "/livro/save", priority = 1)
	public void save(Livro obj) {
		super.save(obj);
	}
	
}

[]'s

Luciano,

Realmente havia pensado nisso também. Apesar de não ser a melhor saida, mas quebraria o galho inicialmente.
Contudo, com esta implementação, está ocorrendo essa exceção na hora de levantar a aplicação:

SEVERE: Exception starting filter vraptor
java.lang.IllegalStateException: Paranamer were not able to find your parameter names. You must compile your code with debug information (javac -g) or register another name provider. Try to use br.com.caelum.vraptor.http.DefaultParameterNameProvider instead.
	at br.com.caelum.vraptor.http.ParanamerNameProvider.parameterNamesFor(ParanamerNameProvider.java:58)
	at br.com.caelum.vraptor.http.route.DefaultTypeFinder.getParameterTypes(DefaultTypeFinder.java:41)
	at br.com.caelum.vraptor.http.route.RouteBuilder.addParametersInfo(RouteBuilder.java:170)
	at br.com.caelum.vraptor.http.route.RouteBuilder.is(RouteBuilder.java:162)
	at br.com.caelum.vraptor.http.route.PathAnnotationRoutesParser.registerRulesFor(PathAnnotationRoutesParser.java:90)
	at br.com.caelum.vraptor.http.route.PathAnnotationRoutesParser.rulesFor(PathAnnotationRoutesParser.java:68)
	at br.com.caelum.vraptor.http.route.DefaultRouter.register(DefaultRouter.java:141)
	at br.com.caelum.vraptor.ioc.ResourceHandler.handle(ResourceHandler.java:44)
	at br.com.caelum.vraptor.ioc.spring.StereotypedBeansRegistrar.handleRefresh(StereotypedBeansRegistrar.java:59)
	at br.com.caelum.vraptor.ioc.spring.StereotypedBeansRegistrar.onApplicationEvent(StereotypedBeansRegistrar.java:47)
	at org.springframework.context.event.SimpleApplicationEventMulticaster$1.run(SimpleApplicationEventMulticaster.java:78)
	at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:76)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:275)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:737)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:384)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.start(SpringBasedContainer.java:66)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.start(SpringProvider.java:77)
	at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:107)
	at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:100)
	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
	at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3800)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4450)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:722)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:583)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Lucas_Cavalcanti

@lscosta
Herança pra reuso de código é quase sempre ruim…
nesses casos, criar um controlador genérico em que vc use composição seria melhor… geralmente vc tem que execultar alguma lógica de validação ou coisa do tipo para entidades específicas…
com composição vc ainda garante o DRY…

@rafaelunp
como vc tá compilando suas classes? no eclipse? via ant? se vc não usar a opção de debug o vraptor não consegue recuperar os nomes dos parâmetros

G

lscosta, acho muito boa sua idéia, porém isso é muito bom na aplicação e não no framework.

Forçar um framework a ter isso por padrão não é legal, e eu não me sentiria nem um pouco confortável de usar o vraptor assim. DRY não significa generalizar tudo. Se fosse assim porque o Hibernate não possui então uma GenericDAO embeded?

O ponto que eu quero levar é que esse tipo de coisa não fica bacana estar forçado no core de um framework, mas sim em um componente customizado seu, na sua aplicação. Até porque você tem esses métodos aí nas suas classes, porém eu não tenho. Dessa forma eu vou ter de brinde sempre nos meus controllers um método delete? Mas na minha aplicação, por exemplo, um usuário nunca é excluído. Aí faço o que? Tenho que ter uma throws UnsupportedOperationException?

Bato de novo na tecla que é muito bom o vraptor deixar muito flexível essas formas de trabalhar com o URI X controller, mas jamais forçar como eu tenho meu controller.

Abraços

lscosta

Rafael,

Confere se nos jsp’s os nomes dos teus inputs são “obj.id”, “obj.descricao” e assim por diante… O mesmo nome do parâmetro na action…

No meu exemplo usei “entity.id”, “entity.name” e funcionou…

Quanto ao @Path, precisei informar com prioridade, pq deu um erro dizendo que haviam dois métodos que atendiam àquela url…

lscosta

@garcia-jj
Mas o que implementei é na minha aplicação, eu também não quero isso no vraptor! Só acho bom que ele suporte isso. E ele suporta… basta um ajuste pq isso não havia sido considerado ainda… Normal!

Vc entendeu? Eu não quero aqueles métodos no vraptor… Não quero nada ‘forçado’ alí… talvez eu não tenha me expressado direito…

@lucascs
Concordo plenamente quanto à Herança, e confesso que tbm tenho um certo vício quanto a isso! Mas acho que nesse caso ela atende bem à minha necessidade de reuso, dentro dessa aplicação.

G

lscosta:
@garcia-jj
Mas o que implementei é na minha aplicação, eu também não quero isso no vraptor! Só acho bom que ele suporte isso. E ele suporta… basta um ajuste pq isso não havia sido considerado ainda… Normal!

Vc entendeu? Eu não quero aqueles métodos no vraptor… Não quero nada ‘forçado’ alí… talvez eu não tenha me expressado direito…

:thumbup: Desculpe, acho que lí errado mesmo, haha. Isso que dá ficar com metade da tela no eclipse e outra metade no guj, hahahahaha.

lscosta

@garcia-jj
Beleza! :wink:

@lucascs
Desculpinha bem furada a minha né… =) Vou reescrever de forma decente! Valeu!

rafaelunp

lscosta:
@garcia-jj
Mas o que implementei é na minha aplicação, eu também não quero isso no vraptor! Só acho bom que ele suporte isso. E ele suporta… basta um ajuste pq isso não havia sido considerado ainda… Normal!

Vc entendeu? Eu não quero aqueles métodos no vraptor… Não quero nada ‘forçado’ alí… talvez eu não tenha me expressado direito…

@lucascs
Concordo plenamente quanto à Herança, e confesso que tbm tenho um certo vício quanto a isso! Mas acho que nesse caso ela atende bem à minha necessidade de reuso, dentro dessa aplicação.

@garcia-jj

Luciano falou exatamente o que eu ia dizer… Eu também não citei em nenhum momento que este codigo deveria estar implementado no Vraptor…
Estou tentando implementar na minha aplicação, para sanar determinado problema.
Se voce ler novamente os meus 2 primeiros posts vai ver qual era o problema inicial e o que estamos enfrentando no decorrer do desenvolvimento dentro de aplicação.

@lscosta
minhas páginas .jsp estão com os nomes dos inputs corretos, batendo com o metodo do controller… “obj.id”, “obj.descricao”.

@lucascs
Estou usando no eclipse, por enquanto…
Estava funcionando normalmente. Foi devido a esta herança que parou de funcionar?
Por causa disso preciso fazer alguma configuração no eclipse com relação ao debug?

Lucas_Cavalcanti

rafaelunp, se só está dando esse erro qdo vc usa a herança, o bug é outro… vou investigar aqui e já te falo…

solução para agora: não use herança, use composição:

public class UsuarioController {
   private GenericControler<Usuario> controller = ....

   public void salva(Usuario usuario) {
       controller.salva(usuario);
   }

   //etc
}
rafaelunp
lucascs:
rafaelunp, se só está dando esse erro qdo vc usa a herança, o bug é outro... vou investigar aqui e já te falo...

solução para agora: não use herança, use composição:

public class UsuarioController {
   private GenericControler<Usuario> controller = ....

   public void salva(Usuario usuario) {
       controller.salva(usuario);
   }

   //etc
}

Lucas,

Fiz usando composição. E voltou o erro do null pointer. Percebo que o objeto está vindo nulo, mesmo no form estando com o nome correto...

@Resource
public class LivroController {

	private CRUDLogic<Livro> controller = null;

	public LivroController(LivroDAO dao, Result result, Validator validator) {
		controller = new GenericLogic<Livro>(dao, result, validator);
	}

	@Post
	public void save(Livro livro) {
		controller.save(livro);
	}
}

Form:

<form method="post" action="../save">
	
		<label for="nome">Nome:</label>
		<input id="nome" type="text" name="livro.nome" value="$!livro.nome" />
		<label for="sinopse">Sinopse:</label>		
		<input id="sinopse" type="text" name="livro.sinopse" value="$!livro.sinopse" />
		<label for="preco">Preco:</label>		
		<input id="preco" type="text" name="livro.preco" value="$!livro.preco" />
		
		<input type="hidden" name="livro.id" value="$!livro.id" />
		<button type="submit" name="_method" value="POST" >Salvar</button>
		
	</form>
Lucas_Cavalcanti

o livro está vindo null? ou tá dando null pointer em algum outro lugar?

rafaelunp

O livro tá vindo null…

rafaelunp

Lucas,

Detalhe:

Eu implementei o RoutesConfiguration

@Component
@ApplicationScoped
public class CustomRoutes implements RoutesConfiguration{

	public void config(Router router) {
		new Rules(router) {
		    @Override
			public void routes() {
		    	routeFor("/{webLogic}/{webMethod}/{id}").is(type("br.com.lojavirtual.controller.{webLogic}Controller"), method("{webMethod}"));
		    }
		};
	}

}

Então acesso a url com a Logica em Maiuscula...
Livro/form
Livro/save
Neste Livro/save é que o objeto está nulo.
Quando removo o CustomRoutes e acesso a url em minuscula
livro/form
livro/save
o objeto vem populado, mas ai recebo um nullpointer na linha do save, interno (dentro da composição):

validator.onErrorUse(Results.page()).of(getClass()).form();
O erro é este:
09/12/2009 15:02:27 org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet sitemesh-velocity threw exception
java.lang.NullPointerException
	at br.com.caelum.vraptor.interceptor.OutjectResult.accepts(OutjectResult.java:47)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:45)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:49)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
	at br.com.caelum.vraptor.view.DefaultPageResult$1.intercept(DefaultPageResult.java:126)
	at br.com.caelum.vraptor.proxy.AbstractCglibProxifier$2.intercept(AbstractCglibProxifier.java:33)
	at br.com.lojavirtual.controller.GenericLogic$$EnhancerByCGLIB$$b3cf20af.form(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at br.com.caelum.vraptor.view.ValidationPageResult$1.intercept(ValidationPageResult.java:75)
	at br.com.caelum.vraptor.proxy.AbstractCglibProxifier$2.intercept(AbstractCglibProxifier.java:33)
	at br.com.lojavirtual.controller.GenericLogic$$EnhancerByCGLIB$$b3cf20af.form(<generated>)
	at br.com.lojavirtual.controller.GenericLogic.save(GenericLogic.java:40)
	at br.com.lojavirtual.controller.LivroController.save(LivroController.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:50)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:72)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:45)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
	at java.lang.Thread.run(Thread.java:595)
09/12/2009 15:02:27 org.apache.catalina.core.ApplicationContext log
SEVERE: Unhandled exception occurred whilst decorating page
br.com.caelum.vraptor.InterceptionException: br.com.caelum.vraptor.view.ResultException: java.lang.reflect.InvocationTargetException
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:76)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:72)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:45)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
	at java.lang.Thread.run(Thread.java:595)
Caused by: br.com.caelum.vraptor.view.ResultException: java.lang.reflect.InvocationTargetException
	at br.com.caelum.vraptor.view.ValidationPageResult$1.intercept(ValidationPageResult.java:77)
	at br.com.caelum.vraptor.proxy.AbstractCglibProxifier$2.intercept(AbstractCglibProxifier.java:33)
	at br.com.lojavirtual.controller.GenericLogic$$EnhancerByCGLIB$$b3cf20af.form(<generated>)
	at br.com.lojavirtual.controller.GenericLogic.save(GenericLogic.java:40)
	at br.com.lojavirtual.controller.LivroController.save(LivroController.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:50)
	... 44 more
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at br.com.caelum.vraptor.view.ValidationPageResult$1.intercept(ValidationPageResult.java:75)
	... 53 more
Caused by: br.com.caelum.vraptor.proxy.ProxyInvocationException: java.lang.NullPointerException
	at br.com.caelum.vraptor.view.DefaultPageResult$1.intercept(DefaultPageResult.java:129)
	at br.com.caelum.vraptor.proxy.AbstractCglibProxifier$2.intercept(AbstractCglibProxifier.java:33)
	at br.com.lojavirtual.controller.GenericLogic$$EnhancerByCGLIB$$b3cf20af.form(<generated>)
	... 58 more
Caused by: java.lang.NullPointerException
	at br.com.caelum.vraptor.interceptor.OutjectResult.accepts(OutjectResult.java:47)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:45)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:49)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
	at br.com.caelum.vraptor.view.DefaultPageResult$1.intercept(DefaultPageResult.java:126)
	... 60 more
09/12/2009 15:02:27 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
br.com.caelum.vraptor.InterceptionException: br.com.caelum.vraptor.view.ResultException: java.lang.reflect.InvocationTargetException
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:76)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:72)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:45)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
	at java.lang.Thread.run(Thread.java:595)
Caused by: br.com.caelum.vraptor.view.ResultException: java.lang.reflect.InvocationTargetException
	at br.com.caelum.vraptor.view.ValidationPageResult$1.intercept(ValidationPageResult.java:77)
	at br.com.caelum.vraptor.proxy.AbstractCglibProxifier$2.intercept(AbstractCglibProxifier.java:33)
	at br.com.lojavirtual.controller.GenericLogic$$EnhancerByCGLIB$$b3cf20af.form(<generated>)
	at br.com.lojavirtual.controller.GenericLogic.save(GenericLogic.java:40)
	at br.com.lojavirtual.controller.LivroController.save(LivroController.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:50)
	... 44 more
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at br.com.caelum.vraptor.view.ValidationPageResult$1.intercept(ValidationPageResult.java:75)
	... 53 more
Caused by: br.com.caelum.vraptor.proxy.ProxyInvocationException: java.lang.NullPointerException
	at br.com.caelum.vraptor.view.DefaultPageResult$1.intercept(DefaultPageResult.java:129)
	at br.com.caelum.vraptor.proxy.AbstractCglibProxifier$2.intercept(AbstractCglibProxifier.java:33)
	at br.com.lojavirtual.controller.GenericLogic$$EnhancerByCGLIB$$b3cf20af.form(<generated>)
	... 58 more
Caused by: java.lang.NullPointerException
	at br.com.caelum.vraptor.interceptor.OutjectResult.accepts(OutjectResult.java:47)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:45)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:49)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
	at br.com.caelum.vraptor.view.DefaultPageResult$1.intercept(DefaultPageResult.java:126)
	... 60 more
Lucas_Cavalcanti

esse nullPointer é um bug que foi corrigido… isso acontece qdo a jsp que vc tah apontando não existe… o form.jsp tá no lugar certo?

se no form() vc tah redirecionando pra outro lugar, vc precisa trocar o page()).of por logic()).forwardTo

Lucas_Cavalcanti

a URI
Livro/save
não casam com o padrão q vc colocou no customRoutes…
tá usando a convenção mesmo…

tenta acessar com letra minúscula, mesmo com o customRoutes

rafaelunp

Lucas, mais uma vez obrigado pelas respostas…

Eu já mexi em varias partes do codigo de forma que o erro já mudou, mas não necessariamente consegui corrigir :lol:
Ainda vou voltar nisso.
No momento, estou fazendo assim:

Usando composição, sem o CustomRoutes, o objeto está sendo populado e não está dando nullpointer na linha

nem aqui

Contudo, como não estou mais usando herança, não estou conseguindo redirecionar o erro ou ou a página correta, pois como está tentando usar a própria classe generica (getClass()) está dando

The selected route is invalid for redirection: br.com.lojavirtual.controller.GenericLogic.list

Como posso fazer para redirecionar para o list() ou form() da classe que está implementando a composição (LivroController), dinamicamente?

Lucas_Cavalcanti

geralmente this.getClass() é a classe do objeto atual… pra pegar a classe “dinamicamente” vc tem que passar a classe do controller no construtor do GenericLogic… não tem mto como descobrir (tem via stackTrace talvez… mas não é nem um pouco bonito)

rafaelunp

lucascs:
esse nullPointer é um bug que foi corrigido… isso acontece qdo a jsp que vc tah apontando não existe… o form.jsp tá no lugar certo?

se no form() vc tah redirecionando pra outro lugar, vc precisa trocar o page()).of por logic()).forwardTo

A versão 3.0.2 está com esse bug corrigido?
no form() funciona norma, e a form.jsp está exibindo corretamente. O problema só dá no save, quando chamo
((CRUDLogic) validator.onErrorUse(Results.logic()).forwardTo( clazz )).form();
Ai rola o nullpointer…

Lucas_Cavalcanti

o bug foi corrigido, mas só na versão nova (a 3.0.3 que não saiu ainda ;))

acho que ele tá usando a classe errada…

ve se esse clazz não é o genericCrud lah

rafaelunp

lucascs:
o bug foi corrigido, mas só na versão nova (a 3.0.3 que não saiu ainda ;))

acho que ele tá usando a classe errada…

ve se esse clazz não é o genericCrud lah

Já debuguei. o clazz tá vindo correto…

Lucas_Cavalcanti

o form está em /WEB-INF/jsp/livro/form.jsp e o controller se chama LivroController, com um método form()?
esse método form faz algum result.use(…)?

quer que eu te mande o jar do vraptor mais recente com o bug corrigido pra ver se resolve?

rafaelunp

lucascs:
o form está em /WEB-INF/jsp/livro/form.jsp e o controller se chama LivroController, com um método form()?

Isso. Vale salientar que estou usando composição. o metodo form chama o controller.form(), conforme topicos acima.

o controller.form() que na verdade é o GenericController, usa o result sim.

Mandae, pls

Lucas_Cavalcanti

http://www.linux.ime.usp.br/~lucascs/vraptor-3.0.3-SNAPSHOT.jar

baixa aí… me avisa qdo baixar, pra eu tirar :stuck_out_tongue:

rafaelunp

lucascs:
http://www.linux.ime.usp.br/~lucascs/vraptor-3.0.3-SNAPSHOT.jar

baixa aí… me avisa qdo baixar, pra eu tirar :P

Pode tirar… vou testar e ver no que dá

Criado 30 de novembro de 2009
Ultima resposta 10 de dez. de 2009
Respostas 59
Participantes 4