Announcement Announcement Module
Collapse
No announcement yet.
Problem with multiple contexts Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with multiple contexts

    Hi there,

    I'm trying to setup a simple exception handling for my app. The app context is spread over several xml files. Consider the following code:
    Code:
        ...
        <aop:config>
            <aop:pointcut id="serviceMethod"
                expression="execution(* my.app.services.*.*(..))" />
            <aop:advisor pointcut-ref="serviceMethod"
                advice-ref="exceptionAdvice" />
        </aop:config>
    
        <bean id="exceptionAdvice"
              class="my.app.aop.MyExceptionAdvice" />
    
        <bean id="service"
              class="my.app.services.DummyServiceImpl" />
        ...
    Let's assume this code resides in aop-context.xml and let's assume I have a bunch of other context files. Now if I initialize the app using aop-context.xml as the single context descriptor - everything works fine, i.e. my Advice (see below) is called upon an exception. However if the other remaining xml files are added to app context, the Advice afterThrows method is not called.

    So, here's some code to make it all more clear:
    Code:
    // the advice
    public class MyExceptionAdvice
    implements ThrowsAdvice
    {
        public void afterThrowing(Exception e)
        {
            System.out.println("Yep, there was an exception, do something!");
        }
    }
    
    // service interface and implementation
    public interface DummyService
    {
        public void testService();
    }
    
    public class DummyServiceImpl
    {
        public void testService()
        {
             throw new IllegalArgumentException("WHOOOPS!");
         }
    }
    So, if I run a simple test app using the code below - everything works just fine:
    Code:
    public class AopTest
    {   
        public static void main(String[] args)
        {
            String[] paths = {"aop-context.xml"};
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(paths);  
            DummyService service = (DummyService) ctx.getBean("service");
            service.testService();
        }
    }
    This however doesn't - the advice doesn't receive any exceptions:

    Code:
    public class AopTest
    {   
        public static void main(String[] args)
        {
            String[] paths = {"aop-context.xml", "application-context", "jdbc-context.xml", "directory-context.xml"};
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(paths);  
            DummyService service = (DummyService) ctx.getBean("service");
            service.testService();
        }
    }

    Any ideas? It's really driving me mad

    TIA,
    jenner

  • #2
    Can you provide the other context configuration?

    Comment


    • #3
      Originally posted by rgeorgiev View Post
      Can you provide the other context configuration?
      Yep, see below (I'll split it up into three posts - the forum allows max. 10000 characters).
      The aop-context.xml is almost the same as above, only without the
      Code:
         <bean id="service"  class="my.app.services.DummyServiceImpl" />
      part.

      application-context.xml:
      Code:
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      	xmlns:aop="http://www.springframework.org/schema/aop"
      	xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                                 http://www.springframework.org/schema/aop
                                 http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
      
          <bean id="placeholderConfig"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
              <property name="locations">
                  <list><value>file:/etc/myapp/webapp.conf</value></list>
              </property>
          </bean>
      
          <bean id="userDao"
              class="my.app.data.dao.ldap.UserDaoLdap">
              <property name="ldapUserSearch">
                  <ref bean="userSearch" />
              </property>
          </bean>
      
          <bean id="mailSender"
              class="org.springframework.mail.javamail.JavaMailSenderImpl">
              <property name="host">
                  <value>${mail.smtp.server}</value>
              </property>
          </bean>
      
          <bean id="spamFilterMailSender"
              class="org.springframework.mail.javamail.JavaMailSenderImpl">
              <property name="host">
                  <value>${spamfilter.mail.smtp.server}</value>
              </property>
          </bean>
      
          <bean id="mailboxService"
              class="my.app.services.MailboxServiceImpl">
              <property name="defaultRootFolderName">
                  <value>${mail.imap.defaultRootFolder}</value>
              </property>
              <property name="imapServer">
                  <value>${mail.imap.server.host}</value>
              </property>
              <property name="imapPort">
                  <value>${mail.imap.server.port}</value>
              </property>
          </bean>
      
          <bean id="statisticsService"
              class="my.app.services.StatisticsServiceImpl">
          </bean>
      
          <bean id="unreadMessagesService"
              class="my.app.services.UnreadMessagesServiceImpl">
              <property name="mailboxService">
                  <ref local="mailboxService" />
              </property>
              <property name="searchService">
                  <ref local="searchService" />
              </property>
              <property name="messageConverterService">
                  <ref local="messageConverterService" />
              </property>
          </bean>
      
          <bean id="readQuotaService"
              class="my.app.services.ReadQuotaServiceImpl">
              <property name="mailboxService">
                  <ref local="mailboxService" />
              </property>
          </bean>
      
          <bean id="messageService"
              class="my.app.services.MessageServiceImpl">
              <property name="statisticsService">
                  <ref local="statisticsService" />
              </property>
              <property name="mailboxService">
                  <ref local="mailboxService" />
              </property>
              <property name="messageConverterService">
                  <ref local="messageConverterService" />
              </property>
              <property name="userDao">
                  <ref local="userDao" />
              </property>
              <property name="mailSender">
                  <ref local="mailSender" />
              </property>
          </bean>
          
          <bean id="systemService"
              class="my.app.services.SystemServiceImpl">
              <property name="userDao">
                  <ref local="userDao" />
              </property>
              <property name="messageService">
                  <ref local="messageService" />
              </property>
              <property name="attachmentStorageService">
                  <ref local="attachmentStorageService" />
              </property>
          </bean>
      
          <bean id="folderService"
              class="my.app.services.FolderServiceImpl">
              <property name="mailboxService">
                  <ref local="mailboxService" />
              </property>
              <property name="messageConverterService">
                  <ref local="messageConverterService" />
              </property>
          </bean>
      
          <bean id="searchService"
              class="my.app.services.SearchServiceImpl">
              <property name="mailboxService">
                  <ref local="mailboxService" />
              </property>
              <property name="messageConverterService">
                  <ref local="messageConverterService" />
              </property>
          </bean>
      
          <bean id="versionService"
              class="my.app.services.VersionServiceImpl">
              <property name="version">
                  <value>0.7.7.3</value>
              </property>
          </bean>
      
          <bean id="mailFilterService"
              class="my.app.services.MailFilterServiceImpl">
              <property name="mailboxService">
                  <ref local="mailboxService" />
              </property>
              <property name="mailSender">
                  <ref local="spamFilterMailSender" />
              </property>
              <property name="mailFilterDao">
                  <ref bean="mailFilterDao" />
              </property>
              <property name="whiteBlackListDao">
                  <ref bean="whiteBlackListDao" />
              </property>
              <property name="notificationSender">
                  <value>${spamassassin.mail.notificationSender}</value>
              </property>
              <property name="recipientHostPart">
                  <value>${spamassassin.mail.recipientHostPart}</value>
              </property>
              <property name="recipientPrefix">
                  <value>${spamassassin.mail.recipientPrefix}</value>
              </property>
              <property name="spamKeyword">
                  <value>${spamassassin.spamKeyword}</value>
              </property>
              <property name="hamKeyword">
                  <value>${spamassassin.hamKeyword}</value>
              </property>
          </bean>
          
          <bean id="messageConverterService"
              class="my.app.services.MessageConverterServiceImpl">
              <property name="attachmentStorageService">
                  <ref local="attachmentStorageService" />
              </property>
      	    <property name="mimeFileTypeMap">
                  <ref local="mimeFileTypeMap" />
              </property>
              <property name="userDao">
                  <ref local="userDao" />
              </property>
              <property name="defaultCharset">
                  <value>UTF-8</value>
              </property>
          </bean>
      
          <bean id="attachmentDownloadService"
              class="my.app.services.AttachmentDownloadServiceImpl">
             <property name="mailboxService">
                  <ref local="mailboxService" />
             </property>
          </bean>
      
          <bean id="compoundService"
              class="my.app.services.CompoundServiceImpl">
              <property name="statisticsService">
                  <ref local="statisticsService" />
              </property>
              <property name="folderService">
                  <ref local="folderService" />
              </property>
              <property name="messageService">
                  <ref local="messageService" />
              </property>
              <property name="readQuotaService">
                  <ref local="readQuotaService" />
              </property>
              <property name="unreadMessagesService">
                  <ref local="unreadMessagesService" />
              </property>
              <property name="searchService">
                  <ref local="searchService" />
              </property>
              <property name="versionService">
                  <ref local="versionService" />
              </property>
              <property name="mailFilterService">
                  <ref local="mailFilterService" />
              </property>
              <property name="systemService">
                  <ref local="systemService" />
              </property>
              
          </bean>
      
          <!--  services not exported by xfire -->
          <bean id="attachmentStorageService"
              class="my.app.services.SimpleAttachmentStorageService">
              <property name="chunkSize">
                  <value>1024</value>
              </property>
              <property name="metadataSuffix">
                  <value>.props.xml</value>
              </property>
              <property name="storagePath">
                  <value>${attachments.storagePath}</value>
              </property>
          </bean>
          
          <bean id="mimeFileTypeMap"
              class="org.springframework.mail.javamail.ConfigurableMimeFileTypeMap">
              <property name="mappingLocation" value="file:/etc/mime.types" />
          </bean>
      </beans>
      Last edited by jenner; Mar 14th, 2007, 04:35 AM.

      Comment


      • #4
        jdbc-context.xml

        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
        	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        	xmlns:aop="http://www.springframework.org/schema/aop"
        	xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                   http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                                   http://www.springframework.org/schema/aop
                                   http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
        
            <bean id="pgDataSource"
                class="org.apache.commons.dbcp.BasicDataSource">
                <property name="driverClassName" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
                <property name="initialSize" value="${jdbc.poolsize}" />
            </bean>
        
            <bean id="hibernateFactory"
                class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                <property name="dataSource" ref="pgDataSource" />
                <property name="mappingResources">
                    <list>
                        <value>MailMessageFilter.hbm.xml</value>
                        <value>MailMessageFilterRule.hbm.xml</value>
                        <value>WhiteBlackList.hbm.xml</value>
                    </list>
                </property>
                <property name="hibernateProperties">
                    <props>
                        <prop key="hibernate.dialect">
                            org.hibernate.dialect.PostgreSQLDialect
                        </prop>
                    </props>
                </property>
            </bean>
        
            <bean id="mailFilterDao"
                  class="my.app.data.dao.sql.MailFilterDaoHibernateImpl">
                <property name="sessionFactory" ref="hibernateFactory" />
                <property name="uniqQueryName" value="MailMessageFilter.getOneByUserId" />
                <property name="listQueryName" value="MailMessageFilter.listByUserId" />
                <property name="predQueryName" value="MailMessageFilter.getOneByPredecessorId" />
            </bean>
            
            <bean id="mailFilterRuleDao"
                  class="my.app.data.dao.sql.MailFilterRuleDaoHibernateImpl">
                <property name="sessionFactory" ref="hibernateFactory" />
                <property name="uniqQueryName" value="MailMessageFilterRule.getOneById" />
                <property name="listQueryName" value="MailMessageFilterRule.listByFilterId" />
            </bean>
        
            <bean id="whiteBlackListDao"
                  class="my.app.data.dao.sql.WhiteBlackListDaoHibernateImpl">
                <property name="sessionFactory" ref="hibernateFactory" />
            </bean>
            
            <bean name="openSessionInViewInterceptor"
                class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
                <property name="sessionFactory">
                    <ref bean="hibernateFactory" />
                </property>
                <property name="flushModeName">
                    <value>FLUSH_AUTO</value>
                </property>
            </bean>
            
        </beans>

        Comment


        • #5
          directory-context.xml:
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
          	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          	xmlns:aop="http://www.springframework.org/schema/aop"
          	xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                                     http://www.springframework.org/schema/aop
                                     http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
          
              <bean id="directoryContextFactory"
                  class="my.app.ldap.InitialDirContextFactory">
                  <property name="url">
                      <value>${ldap.connection.url}</value>
                  </property>
                  <property name="bindDN">
                      <value>${ldap.connection.bindDN}</value>
                  </property>
                  <property name="bindPassword">
                      <value>${ldap.connection.bindPassword}</value>
                  </property>
                  <property name="connectionPoolEnabled">
                      <value>${ldap.connection.connectionPoolEnabled}</value>
                  </property>
              </bean>
          
              <bean id="userSearch"
                  class="my.app.ldap.LdapUserSearch">
                  <property name="searchScope">
                      <value>${ldap.search.scope}</value>
                  </property>
                  <property name="baseFilter">
                      <bean class="my.app.ldap.search.SimpleStringTerm">
                          <property name="attributeType" value="objectClass" />
                          <property name="value" value="dvagEmailPerson" />
                      </bean>
                  </property>
                  <property name="uidAttribute">
                      <value>${ldap.search.uidAttribute}</value>
                  </property>
                  <property name="directoryContextFactory">
                      <ref local="directoryContextFactory" />
                  </property>
              </bean>
          
          </beans>

          Comment


          • #6
            OK, I've managed to create a working setup. In my tests I'm calling systemService.testService() which just throws an IllegalStateException. The "systemService" bean is defined in application-context.xml. Now when I leave the setup as-is then I get a BeanCreationException:
            Code:
            Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'systemService' defined in class path resource [application-context.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
            PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy9] to required type [my.app.service.MessageServiceImpl] for property 'messageService'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy9] to required type [my.app.service.MessageServiceImpl] for property 'messageService': no matching editors or conversion strategy found
            Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessException details (1) are:
            PropertyAccessException 1:
            org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy9] to required type [my.app.service.MessageServiceImpl] for property 'messageService'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy9] to required type [my.app.service.MessageServiceImpl] for property 'messageService': no matching editors or conversion strategy found
            Caused by: java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy9] to required type [my.app.service.MessageServiceImpl] for property 'messageService': no matching editors or conversion strategy found
                at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:224)
                at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:139)
                at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:772)
                at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:606)
                at org.springframework.beans.AbstractPropertyAccessor.setPropertyValue(AbstractPropertyAccessor.java:49)
                at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:74)
                at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:57)
                at org.springframework.beans.factory.support.AbstractBeanFactory.applyPropertyValues(AbstractBeanFactory.java:840)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1026)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:809)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:425)
                at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:250)
                at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
                at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:247)
                at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:161)
                at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:273)
                at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:346)
                at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:92)
                at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:77)
                at my.app.service.AopTest.main(AopTest.java:35)
            If I remove the <property name="messageService" local="messageService" /> the ApplicationContext is loaded just fine and my Advice is triggered in the right place.

            The problem is now - why do I get a BeanCreationException here? If I remove my <aop:config /> stuff from context everything works as it should, if I add it back - the BeanCreationException is thrown...
            Maybe my pointcut expression is crippled somehow? E.g. s.th. like 'execution(* my.app.*.*(..))' should take care of all exceptions which are thrown "underneath" my.app package, right? Well in my case the Advice isn't triggered at all. Only if I use 'execution(* my.app.services.*.*(..))' the Advice is triggered correctly (that is, if I don't inject the messageService bean into systemService).

            jenner.

            Comment


            • #7
              I think the exception says that the 'systemService' bean has a property called 'messageService' which couldn't be initialized with an aop proxy. This is so because the 'messageService' property of type [my.app.service.MessageServiceImpl] is not an interface and JDK Dynamic Proxies work on interfaces only. Either convert the field to an interface (preferable) or if not an option switch to CGLIB-based proxying using this:

              <aop:config proxy-target-class="true">
              ...
              </aop:conifg>

              Comment

              Working...
              X