[RESOLVIDO] VRaptor 3 IOC

22 respostas
jvlouvem

Oi pessoal,
Achei este post http://www.guj.com.br/posts/list/15/149525.java que é parecido com o que eu preciso, mas não consegui resolver

Seguinte, as classes são bem simples

@Resource
public class ClienteController{
	private Result result;
	private ClienteDAO clienteDAO;
	
	public ClienteController(Result result, ClienteDAO clienteDAO) {
		this.result = result;
		this.clienteDAO = clienteDAO;
	}
@Component
public class ClienteDAO extends DAOGenerico<Cliente> {
	private EntityManagerFactory entityManagerFactory;
	
	public ClienteDAO(EntityManagerFactory entityManagerFactory) {
		this.entityManagerFactory = entityManagerFactory;
		setEntityManagerFactory(entityManagerFactory);
	}
}
public abstract class DAOGenerico<T> extends JpaDaoSupport {
	
	protected Class<T> classe;

	public void inserir(T obj) throws Exception {
		getJpaTemplate().persist(obj);
	}

Quando eu chamo qualquer action do controlador, vem a exceção abaixo:

org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class br.com.newsgd.controle.ClienteController]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
	org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:212)

22 Respostas

robson_costa

adiciona um construtor publico sem argumentos na classe ClienteDAO…

jvlouvem

Acabei de testar, dá o mesmo erro :frowning:

Lucas_Cavalcanti

o jeito mais fácil de resolver isso é o seguinte (com
atalhos do eclipse):

  • renomeie o ClienteDao para DefaultClienteDao
    (Alt+Shift+R ou Ctrl+3 Rename com o cursor no nome da classe)
  • extraia a interface ClienteDao
    (Alt+Shift+T Extract Interface, lembre-se de marcar o checkbox “Use extracted interface where possible”)

assim agora o seu ClienteDao é uma interface e seu controller vai depender da interface.

se vc sempre receber interfaces como dependência, esse erro da Cglib não vai acontecer.

dê uma olhada também nesse post: blog.caelum.com.br/2010/07/26/possibilidades-de-design-no-uso-do-seu-generic-dao/

jvlouvem

\o/ \o/ \o/ !!!

Funcionou ! Muito obrigado Lucas !

Aproveitando, você é um dos colaboradores do projeto num é ?
Sou meio resistente a criar interfaces para cada classe, no VRaptor 3 isto é obrigatório ?
Se for não tem problemas, estou perguntando, porque meu projeto antigo com o VRaptor 2, injetava tudo pelo Spring sem interface

jvlouvem

Hum tá esquisito esse ambiente aqui…

Acabei de fazer um teste, renomei DefaultClienteDAO para ClienteDAOImpl e o erro voltou, blz é só reverter isso num é
Reverti, ou seja de ClienteDAOImpl renomei para DefaultClienteDAO e o erro não saiu.

Parei o tomcat, dei clean-and-build no eclipse e nada adiantou

Lucas_Cavalcanti

não é obrigatório pro VRaptor… mas se vc usa a anotação @Transactional do spring - ou qqer outro componente do spring que use AOP - vc tem que usar interfaces…

uma alternativa a usar interfaces é não usar injeção por construtor, mudando pra init method, ou setter, ou field. No caso do seu DAO vc trocaria o

public class ClienteDAO extends DaoGenerico<Cliente> {

     public ClienteDAO(EntityManagerFactory entityManagerFactory) {  
        this.entityManagerFactory = entityManagerFactory;  
        setEntityManagerFactory(entityManagerFactory);  
    }  
}

por

public class ClienteDAO extends DaoGenerico<Cliente> {

     @Autowired
     public void init(EntityManagerFactory entityManagerFactory) {  
        this.entityManagerFactory = entityManagerFactory;  
        setEntityManagerFactory(entityManagerFactory);  
    }  
}

no caso específico do seu DAOGenérico vc pode tirar o construtor dos daos filhos e fazer isso:

public abstract class DAOGenerico<T> extends JpaDaoSupport {  

    //...
    @Autowired
    @Override
    public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
       super.setEntityManagerFactory(entityManagerFactory);
    }
}

não tenho certeza se o último funciona mas não custa tentar :wink:

prefiro as interfaces :wink:

Lucas_Cavalcanti

quanto ao erro que apareceu de novo: o seu controller tah recebendo a interface?

jvlouvem

Sim estou recebendo a interface, já conferi varias vezes o que pode ser, muito estranho isso…

Não no antigo projeto eu uso essa anotação e injeto todos via xml… O xml que dá essa possibilidade é isso ?

jvlouvem

Fiz um outro teste, só deixei no controlador a injeção do Result

O erro foi o mesmo

Could not generate CGLIB subclass of class [class br.com.newsgd.controle.ClienteController]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
	org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:212)
Lucas_Cavalcanti

vc tah usando @Transactional no controller? ou algum Aspect?

se sim vc vai ter que usar aquele init method que eu te falei =(

Lucas_Cavalcanti

de qqer forma evite fazer isso…

se vc quer usar um Aspect no controller, use um Interceptor ao invés disso…

se vc quiser o @Transactional no controller, tem um jeito mais legal (to procurando o tópico onde eu falo isso)

Lucas_Cavalcanti

http://guj.com.br/posts/list/224207.java#1148534

jvlouvem

Isso, achei nesse momento, hehe
Acabei “largando” um @Transactional no Controller, mas foi pra teste mesmo nunca uso lá, uso numa classe entre o controle e o dao que chamo de servico

Bom ainda não testei o @Autowired que voce falou, vou testar e posto aqui

Valeu a força Lucas, tomei seu tempo hoje o dia todo, hehe

Abração :wink:

jvlouvem

Cara tá tudo perfeito !!!

Aquela dica do @Autowire foi a que mais gostei, hehe. Só falta agora eu implementar a @Out que você me mostrou por onde seguir

Abração

jvlouvem

Pessoal,

estou voltando ao tópico, porque encontrei um detalhe.

É o seguinte, estou usando @Autowired nos meus Services e Daos.

Tudo funciona perfeitamente quando as classes a serem injetadas estão num projeto só.

Porém, ao usar um projeto Java para abrigar os Services e Daos, o @Autowired para de funcionar.

Resumindo, encontrei o seguinte comportamento

1 - Classes Service e Dao que usam @Autowired DEVEM ficar todas no projeto Web
2 - Classes Service e Dao PODEM ficar num projeto a parte, SE a injeção for via interface

Abração

Lucas_Cavalcanti

esse projeto java vc está exportando como um jar e colocando no projeto web?

jvlouvem

Sim, o jar do projeto fica no WEB-INF/lib da aplicação web

Lucas_Cavalcanti

o jar foi criado com entradas de diretório?
se vc criou no eclipse tem um checkbox “Include directory entries” que precisa estar checado.
se vc criou pelo ant é o padrão.

ou vc criou de outro jeito?

jvlouvem

Oi Lucas,
obrigado pela ajuda mais uma vez e desculpe a demora para responder, eu não estava em casa…

Bom, o eclipse exporta pra mim, não exporto na mão
No projeto Web, deixo marcado o checkbox que fica na opção Java EE Module Dependencies

Já conferi o jar em: eclipse.workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\ProjetoWeb\WEB-INF\lib
Até abri o jar e está integro, a estrutura está certa dentro dele

Como falei antes, quando uso interfaces, funciona perfeito, se o jar estivesse sendo referenciado erroneamente, daria erro com interfaces também

Tem dois dias que não testo, vou testar mais hoje, mais sem muita esperança, hehe

Lucas_Cavalcanti

é que o VRaptor (na verdade o Spring) não consegue procurar os componentes no jar se ele não estiver com entradas de diretório

Lucas_Cavalcanti

outra coisa: se os componentes estiverem em um jar vc precisa usar a configuração do packages no web.xml:

<context-param>
		<param-name>br.com.caelum.vraptor.packages</param-name>
		<param-value>br.com.suaapp.pacote.base.do.jar</param-value>
	</context-param>
jvlouvem

PERFEITO !!!

Funcionou 100%, nem ia imaginar que era pra registrar o pacote do jar como se faz com os componentes opcionais do VRaptor

You are the Master ! :wink:

Obrigado por mais essa Lucas

Abração

Criado 23 de dezembro de 2010
Ultima resposta 2 de jan. de 2011
Respostas 22
Participantes 3