Announcement Announcement Module
Collapse
No announcement yet.
getBean from within a proxied bean Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • getBean from within a proxied bean

    Hi i'm having the following problem
    Given the following classes:
    - StudentDao -> target of TransactionProxyFactoryBean
    - SequenceDao -> idem StudentDao

    SequenceDao is used from StudentDao to obtain the next value in a sequece for autoincremental primary key value. The problem is that when i call getBean from the ApplicationContext i get a Proxy object that can't be casted to SequenceDao because a ClassCastException is thrown. Can somebody tell me what's wrong?

    When obtained with getBean from outside StudentDao, the SequenceDao proxy can be casted without exceptions being thrown

  • #2
    Can you please post class definitions (without the body code) and config, so it's easier to figure out what's going on and I can reproduce this scenario? I can't see any potential cause of a problem so far...

    Comment


    • #3
      Here goes the code
      applicationContext.xml
      Code:
      <beans>
          <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
              <property name="locations">
                  <list>
                      <value>WEB-INF/jdbc.properties</value>
                  </list>
              </property>
          </bean>
      
          <bean id="citFacade" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
              <property name="transactionManager">
                  <ref bean="transactionManager"/>
              </property>
              <property name="target">
                  <bean class="com.sep.padron.business.facade.CITFacade">
                      <property name="entityDao">
                          <ref bean="entityDao"/>
                      </property>
                  </bean>
              </property>
              <property name="transactionAttributes">
                  <props>
                      <prop key="*">PROPAGATION_REQUIRED,-com.sep.padron.business.exception.SystemException</prop>
                  </props>
              </property>
          </bean>
      
          <bean id="sequenceDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
              <property name="transactionManager">
                  <ref bean="transactionManager"/>
              </property>
              <property name="target">
                  <ref bean="sequenceDaoTarget"/>
              </property>
              <property name="transactionAttributes">
                  <props>
                      <prop key="*">PROPAGATION_REQUIRES_NEW</prop>
                  </props>
              </property>
          </bean>
      </beans>
      dataAccessContext.xml
      Code:
      <beans>
      
          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
              <property name="jndiName">
                  <value>$&#123;dataSource.jndiName&#125;</value>
              </property>
          </bean>
      
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource">
                  <ref local="dataSource"/>
              </property>
          </bean>
      
          <bean id="sqlMap" class="org.springframework.orm.ibatis.SqlMapFactoryBean">
              <property name="configLocation">
                  <value>/WEB-INF/sql-map-config.xml</value>
              </property>
          </bean>
      
          <bean id="entityDao" class="com.sep.padron.persistence.ibatis.SqlMapEntityDao">
              <property name="dataSource">
                  <ref local="dataSource"/>
              </property>
              <property name="sqlMap">
                  <ref local="sqlMap"/>
              </property>
              <property name="sequenceDaoName">
                  <value>sequenceDao</value>
              </property>
          </bean>
      
          <!-- Sequence generator -->
          <bean id="sequenceDaoTarget" class="com.sep.padron.persistence.ibatis.SqlMapSequenceDao">
              <property name="dataSource">
                  <ref local="dataSource"/>
              </property>
              <property name="sqlMap">
                  <ref local="sqlMap"/>
              </property>
          </bean>
      </beans>
      SqlMapSequenceDao
      Code:
      public class SqlMapSequenceDao extends SqlMapDaoSupport implements SequenceDAO&#123;
          public Integer getNextValue&#40;String sequenceName&#41;&#123;
             // fetch next sequence value from 'SEQUENCE' table
          &#125;
      &#125;
      SqlMapEntityDao
      Code:
      public class SqlMapEntityDao extends SequenceDependentDao implements EntityDAO&#123;
          public String insertRow&#40;Entity entity&#41; &#123;
              entity.setEntityId&#40;
                      super.getSequenceDao&#40;&#41;.getNextValue&#40;"C_ENTIDAD.ENTIDAD_ID"&#41;.toString&#40;&#41;&#41;;
              super.getSqlMapTemplate&#40;&#41;.executeUpdate&#40;"insertEntity", entity&#41;;
      
              return entity.getEntityId&#40;&#41;;
          &#125;
      &#125;
      SequenceDependentDao
      Code:
      1 -public class SequenceDependentDao extends SqlMapDaoSupport implements ApplicationContextAware&#123;
      2 -    private String sequenceDaoName;
      3 -    private ApplicationContext applicationContext;
      4 -
      5 -    public SqlMapSequenceDao getSequenceDao&#40;&#41;&#123;
      6 -        return &#40;SqlMapSequenceDao&#41; this.applicationContext.getBean&#40;this.sequenceDaoName&#41;; 
      7 -    &#125;
      8 -
      9 -    public void setSequenceDaoName&#40;String sequenceDaoName&#41;&#123;
      10-        this.sequenceDaoName = sequenceDaoName;
      11-    &#125;
      12-
      13-    public void setApplicationContext&#40;ApplicationContext applicationContext&#41; throws BeansException&#123;
      14-        this.applicationContext = applicationContext;
      15-    &#125;
      16-&#125;
      In line 6 is where i get a ClassCastException because the object returned by getBean is an instance of Proxy

      I hope this can help you help me :P

      Comment


      • #4
        Thanks. The problem is that you're trying to cast the proxy to SqlMapSequenceDao, which is a class. By default Spring AOP uses JDK dynamic proxies, which can only proxy interfaces. Thus your proxy is only implementing the interface SequenceDAO. The AOP framework assumes that you won't try to cast to the actual implementing class.

        You can easily do what you want to do. You simply need to force the TransactionProxyFactoryBean to use CGLIB proxying, by setting its "proxyTargetClass" property to true. You will then need to add the CGLIB Jar from the Spring distribution to your application classpath, if it's not there already (for example, if you use Hibernate as well as Spring).

        Rgds
        Rod

        Comment


        • #5
          Rod, thank you very much.
          It finally worked.

          Comment

          Working...
          X