Spring retorna classe com proxy

boa tarde pessoal
estou sofrendo com uma coisa muito chata do spring. o proxy
é o seguinte, tenho minhas classes assim:

DAO.java

public interface DAO<T> {
    T create(T newInstance) throws Exception;
    T read(Long id);
    List<T> readAll();
    void delete(Long id);
}

e uma classe que implementa o DAO, a MidiaDAO

public class MidiaDAO extends HibernateDaoSupport implements DAO<Midia>{

	@Transactional
	public Midia create(Midia newInstance) throws Exception {
		getHibernateTemplate().saveOrUpdate(newInstance);
		return newInstance;
	}

	@Override
	public Midia read(Long id) {
		Midia m = getHibernateTemplate().get(Midia.class, id);
		return m;
	}

tenho uma classe abstrata, o Controlador:

public abstract class Controlador<T> {
	public abstract DAO<T> getDAO();

e uma implementação: o ControladorMidia

public class ControladorMidia extends Controlador<Midia> {

	public ControladorMidia() {}
@SuppressWarnings("unchecked")
	public DAO<Midia> getDAO() {
		return (DAO<Midia>) SpringORMApplicationContextUtils.getBean("midiaDAO");
	}

o problema é que eu tenho meu DAOs declarados no applicationContext.xml-hiberante.xml

<bean id="midiaDAO" class="br.com.athus.dao.MidiaDAO" > <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean>

até aqui legal, mas agora, eu preciso de um método chamado getByName, no dao MidiaDAO, mas como o ControladorMidia retorna um objeto DAO e não MidiaDAO, esse método não fica visivel no meu ControladorMidia.
quando eu troco a declaração do método no Controlador midia pela seguinte:

public MidiaDAO getDAO() { return (MidiaDAO) SpringORMApplicationContextUtils.getBean("midiaDAO"); }
o Spring lança uma exception, dizendo que eu estou tentando fazer um cast de $Proxy19 para MidiaDAO :S
tentei carregar o dao da seguinte forma:

SpringORMApplicationContextUtils.getBean("&midiaDAO");, onde de acordo com o que eu li, ele retorna o bean e não proxy, mas não mudou nada, mesmo erro
alguem tem alguma luz?
abraços

Tente usar CGLIB proxies ao invés de interface proxies… tem inúmeras vantagens…

Por default o Spring cria Interface proxies… dá uma olhada na documentaçao do spring para saber como configurar o CGLIB, nao é dificil

vou dar uma olhada, tem uma configuração no xml mesmo que diz isso.
mas por ora, eu tirei o @Transactional e funcionou, pq dai ele não passa mais pelo proxy, não há mais interceptação. mas eu preciso do transactional
cglib proxy vai deixar o cast acontecer?

opa, forum errado
algum admim move pra frameworks de persistencia?

O proxy se baseia na interface do teu bean, no caso a interface DAO. Vc só pode fazer cast para essa interface.
Uma opção, já dita é usar CGLib, ou talvez configurar o spring para interceptar o transactional usando AspectJ e não proxy, teria q olhar a documentação do spring.

Pergunta: vc quer usar um método do DAO q não esta na interface?
Não é uma opção criar uma interface específica para isso?

[quote=zorba]vou dar uma olhada, tem uma configuração no xml mesmo que diz isso.
mas por ora, eu tirei o @Transactional e funcionou, pq dai ele não passa mais pelo proxy, não há mais interceptação. mas eu preciso do transactional
cglib proxy vai deixar o cast acontecer?[/quote]

Sim…

Considere o opção do colega… de criar uma interface MidiaDAO

(Eu particularmente nao gosto muito de criar interfaces qeu só uma classe implementa… entao prefiriria nesse caso o CGLIB… aí vc nao precisa mais se preocupar com proxies…)

Aqui está a configuração para usar CGLib http://static.springsource.org/spring/docs/2.5.x/reference/aop.html#aop-proxying

utilizei o proxy do cglib

e foi um sucesso :smiley:
coloquei assim no controlador:

public MidiaDAO getDAO() { return (MidiaDAO) SpringORMApplicationContextUtils.getDAOBean(DAOs.MIDIA); } :smiley:
perfeito perfeito
achei isso aqui tambem, que ajudou:
http://springbrasil.ning.com/forum/topics/jdk-proxies-versus-cglib

valeu pessoal :smiley:

ele lança isso no console

WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.springframework.orm.hibernate3.HibernateTemplate org.springframework.orm.hibernate3.support.HibernateDaoSupport.getHibernateTemplate()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setSessionFactory(org.hibernate.SessionFactory)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.hibernate.SessionFactory org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSessionFactory()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setHibernateTemplate(org.springframework.orm.hibernate3.HibernateTemplate)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.dao.support.DaoSupport.afterPropertiesSet() throws java.lang.IllegalArgumentException,org.springframework.beans.factory.BeanInitializationException] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.springframework.orm.hibernate3.HibernateTemplate org.springframework.orm.hibernate3.support.HibernateDaoSupport.getHibernateTemplate()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setSessionFactory(org.hibernate.SessionFactory)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.hibernate.SessionFactory org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSessionFactory()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setHibernateTemplate(org.springframework.orm.hibernate3.HibernateTemplate)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.dao.support.DaoSupport.afterPropertiesSet() throws java.lang.IllegalArgumentException,org.springframework.beans.factory.BeanInitializationException] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.springframework.orm.hibernate3.HibernateTemplate org.springframework.orm.hibernate3.support.HibernateDaoSupport.getHibernateTemplate()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setSessionFactory(org.hibernate.SessionFactory)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.hibernate.SessionFactory org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSessionFactory()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setHibernateTemplate(org.springframework.orm.hibernate3.HibernateTemplate)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.dao.support.DaoSupport.afterPropertiesSet() throws java.lang.IllegalArgumentException,org.springframework.beans.factory.BeanInitializationException] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.springframework.orm.hibernate3.HibernateTemplate org.springframework.orm.hibernate3.support.HibernateDaoSupport.getHibernateTemplate()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setSessionFactory(org.hibernate.SessionFactory)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final org.hibernate.SessionFactory org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSessionFactory()] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setHibernateTemplate(org.springframework.orm.hibernate3.HibernateTemplate)] because it is final: All calls to this method via a proxy will be routed directly to the proxy. WARN [main] (Cglib2AopProxy.java:254) - Unable to proxy method [public final void org.springframework.dao.support.DaoSupport.afterPropertiesSet() throws java.lang.IllegalArgumentException,org.springframework.beans.factory.BeanInitializationException] because it is final: All calls to this method via a proxy will be routed directly to the proxy. INFO [main] (HibernateTransactionManager.java:415) - Using DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource@188f506] of Hibernate SessionFactory for HibernateTransactionManager
interfere em algo?

Recomendo que você use uma interface MidiaDAO ao invés da classe depender diretamente da implementação. Pode parecer chato usar interfaces, mas garante maior desacoplamento.

O Spring levanta três questões ao usar CGLib:

[quote] * final methods cannot be advised, as they cannot be overriden.
* You will need the CGLIB 2 binaries on your classpath, whereas dynamic proxies are available with the JDK. Spring will automatically warn you when it needs CGLIB and the CGLIB library classes are not found on the classpath.
* The constructor of your proxied object will be called twice. This is a natural consequence of the CGLIB proxy model whereby a subclass is generated for each proxied object. For each proxied instance, two objects are created: the actual proxied object and an instance of the subclass that implements the advice. This behavior is not exhibited when using JDK proxies. Usually, calling the constructor of the proxied type twice, is not an issue, as there are usually only assignments taking place and no real logic is implemented in the constructor.[/quote]

Agora vc precisa ver se nenhuma é problema para vc.

eu não gostaria de criar uma interface midia dao só para isso :frowning: esse sistema será um tanto quanto complexo, e gostaria de deixar o mais simples possivel :smiley:
eu acho que não é um problema isso, meu medo é que ele não esteja fazendo a transação devido ao ‘final’ ali