Results 1 to 3 of 3

Thread: @Resource on test class field: should work, but still get exception

  1. #1
    Join Date
    Jan 2011
    Posts
    1

    Default @Resource on test class field: should work, but still get exception

    I'm using Spring 2.5.6 and I need 2 instances of my service ReportService, each with its own data source. Initially got the obvious error from having 2 matching ReportService beans.

    Code:
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [....ReportService] is defined: expected single matching bean but found 2: [reportService, pdsReportService]
    OK so initially my test class was like this:
    Code:
    public class SiteAppServiceTest extends AbstractUnitTest {
      private SiteAppService siteAppService;
      private ImplementationService implementationService;
      private ReportService reportService;
    
      @Override
      protected String[] getConfigLocations() {
          return new String[]{"appctx-...-service-test.xml"};
      }
    BTW - ReportService is an interface and ReportServiceImpl is listed as the class in the xml. Don't thikn that should matter. The AbstractUnitTest is something my coworker wrote and extends AbstractTransactionalSpringContextTests.

    So I found this page http://static.springsource.org/sprin...e/testing.html and was pretty happy, I just changed my reportService to this:

    Code:
    @Resource(name="reportService")
      private ReportService reportService;
    and I was ready to call it a day. But I reran and got the same exact error. I was stubborn and attached the 2.5.6 source code to my debugger and started stepping through Spring setup itself. After studying some complex code I conclude that although Spring is acknowledging the Resource annotation with the CommonAnnotationBeanPostProcessor doodad and is setting the reportService field on the SiteAppServiceTest, the reportService field is considered unsatisfied and gets shoved into the set of properties that need to be resolved by autowiring.

    My appctx-...-service.test.xml was this

    Code:
    <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"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
             http://www.springframework.org/schema/aop
             http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
             http://www.springframework.org/schema/tx
             http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
             http://www.springframework.org/schema/context 
             http://www.springframework.org/schema/context/spring-context-2.5.xsd">
        
      <context:property-placeholder location="file:../../prm/config/test/prm.properties,file:../../prm/config/test/prm-cred.properties.dec,file:../../prm/config/test/cache.ccf,file:../config/test/lemur.properties,file:../config/test/report-cred.properties"/>
    
      <bean id="prmDataSource" class="org.apache.commons.dbcp.BasicDataSource">
       [properties and stuff]
      </bean>
      <bean id="pdsDataSource" class="org.apache.commons.dbcp.BasicDataSource">
      [properties and stuff]
      </bean>
    
      <bean id="prmTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="prmDataSource"/>
      </bean>
    
      <tx:annotation-driven transaction-manager="prmTransactionManager"/>
    
      <!--
        SERVICES
      -->
      <import resource="classpath:appctx-...-service.xml"/>
    
    </beans>
    Code:
    <beans>
    
        <import resource="classpath:appctx-prm-service.xml"/>
    
        <bean id="publisherRegistrationService"
              class="....PublisherRegistrationServiceImpl">
            <property name="publisherService" ref="publisherService"/>
            <property name="propertyService" ref="propertyService"/>
            <property name="contactService" ref="contactService"/>
            <property name="userAccountDAO" ref="userAccountDAO"/>
            <property name="securitySalt" value="${prm.app.salt}"/>
        </bean>
    
    
        <bean id="siteAppService"
              class="...SiteAppServiceImpl">
            <property name="publisherService" ref="publisherService"/>
            <property name="propertyService" ref="propertyService"/>
            <property name="implementationService" ref="implementationService"/>
            <property name="contactService" ref="contactService"/>
            <property name="userAccountDAO" ref="userAccountDAO"/>
            <property name="platformCategoryService" ref="platformCategoryService"/>
        </bean>
    
        <bean id="platformCategoryService" class="....PlatformCategoryServiceImpl">
          <property name="cachingService" ref="cachingService"/>
        </bean>
    
        <bean id="accountService" class="....AccountServiceImpl">
            <property name="publisherService" ref="publisherService"/>
            <property name="contactService" ref="contactService"/>        
        </bean>
    
        <bean id="pdsReportDAO" class="....ReportDAOImpl">
            <property name="dataSource" ref="pdsDataSource"/>
        </bean>
    
        <bean id="pdsReportService" class="....ReportServiceImpl">
            <property name="reportDAO" ref="pdsReportDAO"/>
        </bean>
    
    </beans>
    And I should point out that the beans 'reportService' and 'reportDAO' are further defnined in that included appctx-prm-service.xml file.

    And of course after adding @Resource I added <context:annotation-config /> in the first file.
    Last edited by jpellico; Jan 31st, 2011 at 05:01 PM.

  2. #2
    Join Date
    Aug 2006
    Location
    Arequipa-Peru / South America
    Posts
    2,796

    Default

    Hello

    Be sure to define your beans with unique name to avoid the duplicity error shown, something like @Annotation(name="someName") , where can be @Resource, @Repository, @Service etc, and inject your beans with the @Qualifier annotation

    I suggest you read more documentation about this

    HTH
    - Manuel Jordan

    Kill Your Pride, Share Your Knowledge With All
    The Fear Of The LORD Is The Beginning Of Knowledge, But Fools Despise Wisdom And Discipline. Proverbs 1:7

    Blog


    Technical Reviewer of Apress

    • Pro SpringSource dm Server
    • Spring Enterprise Recipes: A Problem-Solution Approach
    • Spring Recipes: A Problem-Solution Approach, 2nd Edition
    • Pro Spring Integration
    • Pro Spring Batch
    • Pro Spring 3
    • Pro Spring MVC: With Web Flow
    • Pro Spring Security

  3. #3
    Join Date
    Nov 2005
    Posts
    113

    Default

    I don't see the second report service defined, but keep in mind that @Resource takes the name of the bean in your config file i.e. @Resource("pdsReportService"). Same goes with using @Qualifier by default (though a different qualifier can be provided).

    Now if the second ReportService instance has an id of "reportService", there's something else at play here...

    Hope this helps
    - Don

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •