4

I have just updated from spring 3.2 to spring 4.0.0.RC2 but now I am getting the following expection

org.springframework.beans.factory.NoSuchBeanDefinitionException

on my dao classes when running tests. It fails when autowiring the PersistenceContext (which is our own generic class).

@Repository
public class AccountDaoImpl extends AbstractDao<Account> implements AccountDao {

    @Autowired
    public AccountDaoImpl(final PersistenceContext<Account> context) {
        super(context);
    }

...

If I change the version back to 3.2 everything works. What is different in 4.0 that is causing this problem?

jax
  • 37,735
  • 57
  • 182
  • 278

1 Answers1

1

This happens most probably because the bean you are injecting is declared with different (than Account) type parameter. The Spring Framework 4 performs now more strict type checking.

Here is an example illustrating the problem (test passes with SF 3.2.3.RELEASE and fails with 4.0.0.RC2):

@ContextConfiguration(classes=GenericAutowireTest.TestConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class GenericAutowireTest {

    public static class MyGenericClass<T> {
    }

    @Configuration
    public static class TestConfig {

        @Bean
        public MyGenericClass<String> myGenericClass() {
            return new MyGenericClass<String>();
        }
    }

    @Autowired 
    private MyGenericClass<Integer> myObject;

    @Test
    public void test() {
        assertNotNull(myObject);
    }

}

Here's a nice article about this new feature.

Solution would be to make "accepting" @Autowired field type assignable for the @Bean return type, e.g. make them same including parameterized type. Only that will make sense at runtime.

Sergey Shcherbakov
  • 4,534
  • 4
  • 40
  • 65
  • In essence we got it working by stepping through the spring code. It got confused when getting the @Service bean that was of a generic type. I am pretty sure it was a type error thing like you said and it was resolved by moving the generics out of the class into another class. – jax Dec 13 '13 at 01:45
  • @Smollet - So what would be the solution if I want to keep the generic type? Use @Qualifier("beanname") ? – Andy Dufresne Jan 30 '14 at 11:24
  • @AndyDufresne Solution would be to make same types on both sides of the dependency injection: the `@Bean` return type and and the "accepting" `@Autowired` field type (which only makes sense at runtime). Btw. when you are using `@Qualifier` annotation tend to use some generic notion to name the relationship rather than a bean name (which is also fine). – Sergey Shcherbakov Feb 01 '14 at 14:42
  • @Smollet - I didn't follow your solution. I have detailed my problem here - http://stackoverflow.com/questions/21473926/upgrading-spring-from-3-2-to-4-issue-with-generics-extends. Do you have any inputs? – Andy Dufresne Feb 02 '14 at 07:31