Announcement Announcement Module
Collapse
No announcement yet.
Don't repeat the DAO ! Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Don't repeat the DAO !

    Hi all,

    I've read this article which talks about a way to avoid duplicating DAO codes.
    Now i've troubles when implementing it. I've search this forum and found several threads describing the same problem :
    Especially the second threads details exactly the same problem I have, even the stack strace.

    To sum up:

    We have the following context configuration:
    Code:
    	<bean id="finderIntroductionAdvisor" class="dao.impl.hibernate.FinderIntroductionAdvisor"/>
    	<bean id="abstractDao" class="org.springframework.aop.framework.ProxyFactoryBean" abstract="true">
    	 	<property name="interceptorNames">
    			<list>
    				<value>finderIntroductionAdvisor</value>
    			</list>
    		</property>
    	</bean>
    	<bean id="abstractDaoTarget" class="dao.impl.hibernate.GenericDao" abstract="true">
    		<property name="sessionFactory" ref="sessionFactory"/>
    	</bean>
    	<bean id="TicketDao" parent="abstractDao">
    		<property name="proxyInterfaces">
    			<value>dao.ITicketDao</value>
        	</property>
    	    <property name="target">
    	        <bean parent="abstractDaoTarget">
    	            <constructor-arg>
    	                <value>model.security.Ticket</value>
    	            </constructor-arg>
    	        </bean>
    	    </property>
    	</bean>
    and the following code :

    Code:
    public class FinderIntroductionAdvisor extends DefaultIntroductionAdvisor {
    	public FinderIntroductionAdvisor() {
            super(new FinderIntroductionInterceptor());
        }
    }
    Code:
    public class FinderIntroductionInterceptor implements IntroductionInterceptor {
    	private static Log logger = LogFactory.getLog(FinderIntroductionInterceptor.class);
    
    	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    		logger.debug("Intercepting " + methodInvocation.getMethod() + "on " + methodInvocation.getThis());
    		FinderExecutor genericDao = (FinderExecutor) methodInvocation.getThis();
    
            String methodName = methodInvocation.getMethod().getName();
            if (methodName.startsWith("find")) {
                Object[] arguments = methodInvocation.getArguments();
                return genericDao.executeFinder(methodInvocation.getMethod(), arguments);
            }
            else {
            	return methodInvocation.proceed();
            }
    	}
    
    	public boolean implementsInterface(Class intf) {
    		logger.debug("Implements interface " + intf.getCanonicalName() + "?");
            return intf.isInterface() && FinderExecutor.class.isAssignableFrom(intf);
        }
    Stack trace shows something like that:
    Code:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'RepositoryService' defined in ServletContext resource [/WEB-INF/business.xml]: Cannot resolve reference to bean 'NodeDao' while setting bean property 'nodeDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'NodeDao' defined in ServletContext resource [/WEB-INF/domain.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/domain.xml]: Invocation of init method failed; nested exception is java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource
    Caused by: 
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'NodeDao' defined in ServletContext resource [/WEB-INF/domain.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/domain.xml]: Invocation of init method failed; nested exception is java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource
    Caused by: 
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/domain.xml]: Invocation of init method failed; nested exception is java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource
    Caused by: 
    java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource
            at org.escapek.core.dao.impl.hibernate.FinderIntroductionInterceptor.invoke(FinderIntroductionInterceptor.java:14)
    It seems that ProxyFactoryBean invoke method is called for any class , not only for classes specified in the ProxyFactoryBean target property.

    Unfortunatelly, i couldn't find real answer on both threads. May be one on their authors have found the solution since then.

    Thanks for your help,

    Nico.

  • #2
    Please post your complete configuration. I suspect you have another proxy mechanism (or at least some other proxying) in your config which detects/picks up instances of the Advice classes and applies them to beans. Also post the complete stacktrace if possible.
    Last edited by Marten Deinum; Jun 19th, 2007, 05:30 PM.

    Comment


    • #3
      Hi,

      before posting my complete configuration I decided to clean up some old remaining configuration stuff as well as correcting some O/R mapping mistakes. Now, when running again, the configuration is loaded correctly, and I don't have any more problem with the ProxyFactoryBean.
      I need to do some more tests, but my problem seems to be resolved now. I'm just a bit disapointed to be not able to tell what was the origin.

      Comment


      • #4
        Hi,

        I'm back again with this problem. For the few past days, it hase disappeared. As is said, i've made some cleanup in my configuration files, and all went fine.
        Today, i needed to add some transaction management in that configuration. I simply added the following configuration :

        Code:
        	<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        		<property name="sessionFactory" ref="sessionFactory" />
        	</bean>
        
          <tx:annotation-driven transaction-manager="txManager"/>
        where sessionFactory is :
        Code:
        	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        		<property name="dataSource" ref="dataSource"/>
        		<property name="mappingResources">
        			<list>
        				<value>model-mapping.hbm.xml</value>
        			</list>
        		</property>
        		<property name="hibernateProperties">
        			<props>
        				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
        				<prop key="hibernate.show_sql">false</prop>
        				<prop key="hibernate.generate_statistics">true</prop>
        				<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
        			</props>
        		</property>
         	</bean>
        I've also added the @Transactional annotation on top of one of my Service bean.
        Now, here is the exception strack trace I get when running on Tomcat :

        Code:
        27 juin 2007 09:41:50 org.apache.catalina.core.StandardContext listenerStart
        GRAVE: Exception lors de l'envoi de l'évènement contexte initialisé (context initialized) à l'instance de classe d'écoute (listener) org.springframework.web.context.ContextLoaderListener
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor': Cannot create inner bean '(inner bean)' of type [org.springframework.transaction.interceptor.TransactionInterceptor] while setting bean property 'transactionInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'txManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txManager' defined in ServletContext resource [/WEB-INF/domain.xml]: Initialization of bean failed; nested exception is java.lang.ClassCastException: org.springframework.orm.hibernate3.LocalSessionFactoryBean cannot be cast to org.escapek.core.dao.FinderExecutor
        Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'txManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txManager' defined in ServletContext resource [/WEB-INF/domain.xml]: Initialization of bean failed; nested exception is java.lang.ClassCastException: org.springframework.orm.hibernate3.LocalSessionFactoryBean cannot be cast to org.escapek.core.dao.FinderExecutor
        Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txManager' defined in ServletContext resource [/WEB-INF/domain.xml]: Initialization of bean failed; nested exception is java.lang.ClassCastException: org.springframework.orm.hibernate3.LocalSessionFactoryBean cannot be cast to org.escapek.core.dao.FinderExecutor
        Caused by: java.lang.ClassCastException: org.springframework.orm.hibernate3.LocalSessionFactoryBean cannot be cast to org.escapek.core.dao.FinderExecutor
        	at org.escapek.core.dao.impl.hibernate.FinderIntroductionInterceptor.invoke(FinderIntroductionInterceptor.java:56)
        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
        	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        	at $Proxy0.isSingleton(Unknown Source)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1194)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:262)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
        	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:261)
        	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:109)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1099)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:861)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:421)
        	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
        	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
        	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:261)
        	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:109)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1099)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:861)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:421)
        	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:215)
        	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:127)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1099)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:861)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:421)
        	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
        	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
        	at org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(BeanFactoryAdvisorRetrievalHelper.java:87)
        	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(AbstractAdvisorAutoProxyCreator.java:96)
        	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:83)
        	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:66)
        	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:296)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:312)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1180)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:425)
        	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
        	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
        	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:287)
        	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
        	at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:244)
        	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:187)
        	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49)
        	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3827)
        ...... (truncated)
        Note that by just removing the tx:annotation-driven config. the exception is not thrown.

        Comment


        • #5
          Here is my investigations results:
          The problem comes from my FinderIntroductionInterceptor class which casts the intercepted class into a FinderExecutor interface. The problems is that this interceptor intercepts not only FinderExecutor objects (as it should be), but in fact any objects. I don't think it should intercept any object because the interceptor implements implementsInterface() method like this :

          Code:
          	public boolean implementsInterface(Class intf) {
                  return intf.isInterface() && FinderExecutor.class.isAssignableFrom(intf);
              }
          so I guess the invoke method should only be called for objects implementing the interface FinderExecutor. I've added some logging statements and found that the implementsInterface() method is never called. Is this normal ?

          Finally, in my FinderIntroductionAdvisor, i've subclassed getClassFilter(). Now the code for FinderIntroductionAdvisor is :

          Code:
          public class FinderIntroductionAdvisor extends DefaultIntroductionAdvisor {
          	private static final long serialVersionUID = 1962983854004100921L;
          	private static Log logger = LogFactory.getLog(FinderIntroductionAdvisor.class);
          
          	public FinderIntroductionAdvisor() {
                  super(new FinderIntroductionInterceptor());
              }
          
          	@Override
          	public ClassFilter getClassFilter() {
          		return new ClassFilter() {
          			public boolean matches(Class clazz) {
          				logger.debug("Intercepted class type: " + clazz.getCanonicalName());
          				logger.debug("FinderExecutor.class.isAssignableFrom(clazz) = " + FinderExecutor.class.isAssignableFrom(clazz));
          		        return FinderExecutor.class.isAssignableFrom(clazz);
          			}
          		};
          	}
          }
          The getClassFilter() method of FinderIntroductionAdvisor returns a classFilter instance which returns true is the intercepted class implements FinderExecutor interface.

          Also FinderIntroductionInterceptor is :
          Code:
          public class FinderIntroductionInterceptor implements IntroductionInterceptor {
          	private static Log logger = LogFactory.getLog(FinderIntroductionInterceptor.class);
          
          	@SuppressWarnings("unchecked")
          	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
          		FinderExecutor genericDao = (FinderExecutor) methodInvocation.getThis();
          
                  String methodName = methodInvocation.getMethod().getName();
                  if (methodName.startsWith("find")) {
                      Object[] arguments = methodInvocation.getArguments();
                      return genericDao.executeFinder(methodInvocation.getMethod(), arguments);
                  }
                  else if (methodName.startsWith("get")) {
                          Object[] arguments = methodInvocation.getArguments();
                          return genericDao.executeGetter(methodInvocation.getMethod(), arguments);
                  }
                  else {
                  	return methodInvocation.proceed();
                  }
          	}
          
          	public boolean implementsInterface(Class intf) {
          		logger.debug("Intercepted class type: " + intf.getCanonicalName());
          		logger.debug("intf.isInterface() = " + intf.isInterface());
          		logger.debug("FinderExecutor.class.isAssignableFrom(intf) = " + FinderExecutor.class.isAssignableFrom(intf));
                  return intf.isInterface() && FinderExecutor.class.isAssignableFrom(intf);
              }
          }
          With this code, no more exception is thrown an trace shows that the classFilter does the job. implementsInterface from FinderIntroductionInterceptor is never called.

          Comment


          • #6
            After applying AOP pointcuts to personDAO following exception is thrown any idea why?

            Code:
            org.hibernate.MappingException: Named query not known: Person.iterateFinder

            Comment


            • #7
              yes, I am also facing the same problems

              Comment


              • #8
                Thanks

                Thanks, this worked for me!!!

                Comment

                Working...
                X