Problema no VRaptor3 com herança de controllers

Olá,

Eu tenho um CrudController, que é uma classe concreta e implementa lógicas para os métodos de crud (Search, Create, edit, etc.) e um Controller específico que herda a primeira, adicionando outras lógicas.

Alo como:

@Resource
public class CrudController
@Get
@Path(priority = 0, value = “/vr/{entityName}/search”)
public void search(String entityName) {

}
.
.
.
}

e

@Resource
public class GroupController
@Post
@Path(priority = 0, value = “/vr/group/addUsers”)
public void addUsers(String[] userIds) {

}
.
.
.
}

O Problema é que o VRaptor considera que existem duas rotas para “vr/entityName/search” com a mesma prioridade(apesar de as duas apontarem para o mesmo método) e joga

java.lang.IllegalStateException: There are two rules that matches the uri ‘/vr/user/search’ with method GET: [[FixedMethodStrategy: uri /vr/{entityName}/search methods [GET]], [FixedMethodStrategy: uri /vr/{entityName}/search methods [GET]]] with same priority. Consider using @Path priority attribute.
at br.com.caelum.vraptor.http.route.DefaultRouter.checkIfThereIsAnotherRoute(DefaultRouter.java:106)
at br.com.caelum.vraptor.http.route.DefaultRouter.parse(DefaultRouter.java:97)
at br.com.caelum.vraptor.http.DefaultResourceTranslator.translate(DefaultResourceTranslator.java:53)
at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:64)
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:60)
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 org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
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:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Isso acontece para qualquer entidade.

Só para constar, ontem eu peguei a versão final. Até então estava usando a 3.0 RC1, se não me engano e funcionava conforme o esperado.

É isso mesmo ou posso considerar como um bug?

Abraços,

Gatto

Isso não é um bug, é de propósito…

se você tem 2 métodos que conseguem tratar a mesma URI, como o VRaptor vai saber qual usar?

no caso você tem o método da classe mãe e da classe filha que usam o mesmo @Path

e uma dica: não precisa colocar o priority no @Path… coloque somente quando for necessário, fica mais bonito =)

Outra coisa: porque você precisa da herança nesse caso?

Olá Lucas,

Então, na verdade eu nao tenho dois metodos apenas o da classe mae.

A classe filha herda os metodos de crud genericos da mae e extende com outros especificos para uma entidade em particular.
Mas o PathAnnotationRoutesParser registra 2 vezes os metodos da classe mae ( uma para a mae e outra para a filha).

Mas agora que falou, um workaround pode ser não usar herança.

Vou ver.

Obrigado

Creio que ele usou dessa forma com o propósito de economizar código. O mesmo principio da GenericDAO.

no seu caso o workaround É a herança :wink:

quando você cria uma classe filha, os métodos que ela tem são:

  • os métodos que ela definiu
  • os métodos que a mãe dela definiu

então pro VRaptor você tem 2 métodos mesmo…

não use herança… principalmente de Controllers, não vale a pena…

O VRaptor usa injeção de dependências e redirecionamentos inteligentes…
se você precisar executar uma lógica de outro controller, basta recebê-lo no construtor e executar…
se você precisa redirecionar para um outro controller, basta usar o result.use(logic()) que ele vai executar
o método que você passar…

[]'s

é, sem a herança funcionou.

Valeu Lucas.

Por quê não usar herança? http://www.berniecode.com/writing/inheritance/

Apesar do sensacionalismo dos artigos “is evil”, é um ótimo texto sobre por que favorecer composição à herança.

[]'s

[quote=wariows]Por quê não usar herança? http://www.berniecode.com/writing/inheritance/

Apesar do sensacionalismo dos artigos “is evil”, é um ótimo texto sobre por que favorecer composição à herança.

[]'s[/quote]

Bom artigo mesmo. É aquele bom exemplo da classe java.util.Properties. Properties deveria ter um Map, e não ser um Map (Hashtable na verdade).