title: Spring Autowire fails with No qualifying bean of type found for dependency error
body: <p>Here's my scenario.  My project is using Spring (3.2.3.RELEASE), Struts2 (2.3.14.3) and JPA (2.0).  We have a project (let's call it project A) that contains various entities and common classes.  We use project A to generate a .jar file so that other projects can use these classes.  In project A we've used the Spring stereotypes: @Component. @Service or @Repository for those classes we want Spring to inject.  Whenever we try to inject beans from the jar, we get an error similar to:</p>
  
  <blockquote>
    <ol>
    <li><p>No qualifying bean of type
    [com.ceiwc.bc.commonsql.service.CommonSQLService] found for
    dependency: expected at least 1 bean which qualifies as autowire
    candidate for this dependency. Dependency annotations:
    {@org.springframework.beans.factory.annotation.Autowired(required=true)}</p></li>
    <li><p>Could not autowire field: private com.ceiwc.bc.commonsql.service.CommonSQLService
    com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
    is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
    qualifying bean of type
    [com.ceiwc.bc.commonsql.service.CommonSQLService] found for
    dependency: expected at least 1 bean which qualifies as autowire
    candidate for this dependency. Dependency annotations:
    {@org.springframework.beans.factory.annotation.Autowired(required=true)}</p></li>
    <li><p>Error creating bean with name 'com.ceiwc.ma.mvc.action.LoginAction': Injection of autowired
    dependencies failed; nested exception is
    org.springframework.beans.factory.BeanCreationException: Could not
    autowire field: private
    com.ceiwc.bc.commonsql.service.CommonSQLService
    com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
    is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
    qualifying bean of type
    [com.ceiwc.bc.commonsql.service.CommonSQLService] found for
    dependency: expected at least 1 bean which qualifies as autowire
    candidate for this dependency. Dependency annotations:
    {@org.springframework.beans.factory.annotation.Autowired(required=true)}</p></li>
    <li><p>Unable to instantiate Action, com.ceiwc.ma.mvc.action.LoginAction, defined for 'doLogin' in namespace '/Login'Error creating bean with
    name 'com.ceiwc.ma.mvc.action.LoginAction': Injection of autowired
    dependencies failed; nested exception is
    org.springframework.beans.factory.BeanCreationException: Could not
    autowire field: private
    com.ceiwc.bc.commonsql.service.CommonSQLService
    com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
    is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
    qualifying bean of type
    [com.ceiwc.bc.commonsql.service.CommonSQLService] found for
    dependency: expected at least 1 bean which qualifies as autowire
    candidate for this dependency. Dependency annotations:
    {@org.springframework.beans.factory.annotation.Autowired(required=true)}</p></li>
    </ol>
  </blockquote>
  
  <p>We are using Java configuration for Spring.  Here is our configuration class:</p>
  
  <pre><code>package com.zzz.bc.config;
  
  @Configuration
  @ImportResource({"/WEB-INF/spring/spring-config.xml"})
  @ComponentScan(basePackages = "com.zzz")
  public class ApplicationConfig {
      @Bean
      public JavaMailSender mailSender() {
          JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
          mailSender.setHost(${app.mail.host});
          return mailSender;
      }
  }
  
  package com.zzz.bc.config;
  
  @Configuration
  @EnableTransactionManagement
  @Import(ApplicationConfig.class)
  @PropertySource({"classpath:db.properties"})
  public class DataConfig {
  
      @Autowired
      Environment environment;
  
      @Bean
      public PlatformTransactionManager transactionManager() {
          JpaTransactionManager transactionManager = new JpaTransactionManager();
          transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
          return transactionManager;
      }
  
      @Bean
      public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
          String[] packagesToScan =
                  {environment.getProperty("db.packagesToScan1"), environment.getProperty("db.packagesToScan2")};
  
          Map&lt;String, Object&gt; jpaProperties = new HashMap&lt;String, Object&gt;();
          jpaProperties.put("eclipselink.weaving", "false");
  
          LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
          entityManagerFactoryBean.setDataSource(dataSource());
          entityManagerFactoryBean.setPackagesToScan(packagesToScan);
          entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
          entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
          entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
  
          return entityManagerFactoryBean;
      }
  
      @Bean
      public DriverManagerDataSource dataSource() {
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName(environment.getProperty("db.driver"));
          dataSource.setUrl(environment.getProperty("db.url"));
          dataSource.setUsername(environment.getProperty("db.username"));
          dataSource.setPassword(environment.getProperty("db.password"));
          return dataSource;
      }
  
      @Bean
      public JpaVendorAdapter vendorAdapter() {
          EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
          vendorAdapter.setDatabase(Database.ORACLE);
          vendorAdapter.setShowSql(true);
          return vendorAdapter;
      }
  
      @Bean
      public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
          return new PersistenceExceptionTranslationPostProcessor();
      }
  }
  </code></pre>
  
  <p>We have @ComponentScan set to check to bean in the package of com.zzz.  In project B, we have a Struts2 Action that we want to inject a bean from project A.  Here is a snippet of the class from project B:</p>
  
  <pre><code>@SuppressWarnings("rawtypes")
  @Service("CommonSQLService")
  public class CommonSQLServiceImpl implements CommonSQLService {
  
      @Autowired
      CommonSQLDao cdao;
  
      @Override
      public Policy getPolicyById(String policyNo) {
          return cdao.getPolicyById(policyNo);
      }
  
      @Override
      public Policy getPolicy(Policy parmRec) {
          return cdao.getPolicy(parmRec);
      }
  
      @Override
      public ArrayList&lt;Policy&gt; getPolicies(String policyNo) {
          return cdao.getPolicies(policyNo);
      }
      @Override
       public List&lt;Policy&gt; getPolicies(Policy parmRec){
          return cdao.getPolicies(parmRec);
      }
  }
  </code></pre>
  
  <p>Here is our action (removed getters/setters):</p>
  
  <pre><code>package com.zzz.ma.mvc.action;
  
  @SuppressWarnings("serial")
  @Component
  @Scope("prototype")
  @Namespace("/Login")
  public class LoginAction extends ActionParent {
      @Autowired
      private IUserService userService; //Contained in project B
  
      @Autowired
      private CommonSQLService commonSQLService; //What's autowired from project A
  
      private User user;
      private String updateFlag;
      private Integer parentMenuId;
      private IwifWebNavmenuItem record;
  
      public static final String LOGIN_STR = "login";
  
      @Action(value = "doLogin", results = { @Result(name = "success", location = "/pages/login.jsp") })
      public String login() {
          updateFlag = "Y";
          return SUCCESS;
      }
  
      @Action(value = "validate", results = {
              @Result(name = "success", location = "/BrowseOptions/showOptions", type = "redirect"),
              @Result(name = "login", location = "/pages/login.jsp") })
      public String validateUser() {
          if (updateFlag == null) {
              session.remove(LOGIN_STR);
              return LOGIN;
          }
  
          if (userService.validateUser(user.getUsername(), user.getPassword()) == null) {
              addActionError(getText("invalid.user"));
              return LOGIN;
          }
  
          session.put(LOGIN_STR, user.getUsername());
  
          return SUCCESS;
      }
  
      @Action(value = "logout", results = { @Result(name = "success", location = "/pages/login.jsp") })
      public String logout() {
          updateFlag = StringUtils.EMPTY;
          session.invalidate();
  
          return SUCCESS;
      }
  }
  </code></pre>
  
  <p>Whenever we try to do this autowire, we get an error like the one listed above.  What are we missing?  Can't classes contained in a jar file with Spring Stereotypes be autowired?  </p>
  
  <p>Thanks for you help in advance!</p>