title: Abstract DAO pattern and Spring's "Proxy cannot be cast to ..." problem!
body: <p>I know this is very often asked , but I cannot find a working solution :</p>
  
  <p>This is my AbstractDAO :</p>
  
  <pre><code>public interface AbstractDao&lt;T&gt;
  {
    public T get(Serializable id);
    //other CRUD operations
  }
  </code></pre>
  
  <p>And this is my JPA's implementation:</p>
  
  <pre><code>public abstract class AbstractDaoJpaImpl&lt;T&gt; implements AbstractDao&lt;T&gt; , Serializable
  {
    protected EntityManager em;
  
    protected Class&lt;T&gt; clazz;
  
    @SuppressWarnings("unchecked")
    public AbstractDaoJpaImpl()
    {
      ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
      this.clazz = (Class&lt;T&gt;) genericSuperclass.getActualTypeArguments()[0];
    }
  
    public abstract void setEntityManager(EntityManager em);  
    //implementations skipped
  }
  </code></pre>
  
  <p>And this is one entity's dao :</p>
  
  <pre><code>public interface PersonDao extends AbstractDao&lt;Person&gt;
  {
    //empty
  }
  </code></pre>
  
  <p>Here is its implementation:</p>
  
  <pre><code>@Repository
  public class PersonDaoImpl extends AbstractDaoJpaImpl&lt;Person&gt; implements PersonDao , OtherInterface
  {
    @PersistenceContext(unitName="company")
    @Override
    public void setEntityManager(EntityManager em)
    {
      this.em = em;
    }
  
    @Override // implements OtherInterface.additionalMethods()
    public additionalMethods()
    {
      // implements...
    }
  }
  </code></pre>
  
  <p>The whole architecture is simple :</p>
  
  <p>Interface <strong>AbstractDao</strong> defines simple CRUD methods.</p>
  
  <p>Interface <strong>PersonDao</strong> extends AbstractDAO without any addon methods.</p>
  
  <p>class <strong>AbstractDaoJpaImpl</strong> defines JPA's implementation of AbstractDao</p>
  
  <p>class <strong>PersonDaoImpl</strong> extends AbstractDaoJpaImpl and implements PersonDao <strong>AND OtherInterface , which adds aditionalMethods()</strong>...</p>
  
  <p>IF , PersonDaoImpl only implements PersonDao , without implementing  OtherInterface.additionalMethods() , everything works fine.</p>
  
  <p>I can use </p>
  
  <pre><code>&lt;tx:annotation-driven transaction-manager="transactionManager" /&gt; 
  </code></pre>
  
  <p>in my spring's XML file.</p>
  
  <p>BUT , PersonDaoImpl implements OtherInterface(s) , when testing/running , I <strong>have to cast the DAO from PersonDao to PersonDaoImpl or OtherInterfaces</strong> , such as :</p>
  
  <pre><code>@RunWith(SpringJUnit4ClassRunner.class)
  @ContextConfiguration(locations={"classpath:app.xml"})
  @TransactionConfiguration(transactionManager="transactionManager" , defaultRollback=false)
  public class PersonDaoTest
  {
    @Inject 
    PersonDao dao;
  
    @Test
    public void testAdditionalMethod()
    {
      PersonDaoImpl impl = (PersonDaoImpl) dao;
      System.out.println(impl.additionalMethod(...));
    }
  }
  </code></pre>
  
  <p>The problem occurs when <code>(PersonDaoImpl) dao</code> , which throws "Proxy cannot be cast to PersonDaoImpl" exception:</p>
  
  <pre><code>java.lang.ClassCastException: $Proxy36 cannot be cast to foobar.PersonDaoImpl
      at foobar.PersonDaoTest.testAdditionalMethod(PersonDaoTest.java:36)
  </code></pre>
  
  <p>this is often asked when googleing , everyone suggest adding <code>proxy-target-class="true"</code> to <code>&lt;tx:annotation-driven&gt;</code> :</p>
  
  <pre><code>&lt;tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"  /&gt;
  </code></pre>
  
  <p>This will make use of CGLIB instead of JDK's dynamic proxy.</p>
  
  <p>BUT it throws another exception when initializing Spring :</p>
  
  <pre><code>Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
  </code></pre>
  
  <p>in AbstractDaoJpaImpl's constructor :</p>
  
  <pre><code>ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
  </code></pre>
  
  <p>Every question stops here ,  I cannot find any <strong>working</strong> solutions now.</p>
  
  <p>Can anyone give me a working solution ?
  Thanks a lot !</p>
  
  <p>Environment : Spring-3.0.4 , javaee-api-6.0 , javax.inject , cglib-2.2 , hibernate-jpa-2.0-api-1.0.0 , </p>