Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Autowiring a list into a bean results in a NoSuchBeanDefinitionException

In a Spring 3.1.3.RELEASE project I want to create and autowire a list that contains some enum to some service.

Unfortunately the autowiring fails (NoSuchBeanDefinitionException), while I can retrieve the bean in the context and manually wire the dependency.

Here is a small testcase showcasing the issue (using Spring 3.1.3 and JUnit):

The XML context (int package /junk):

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="junk"/>

    <util:list id="myList" value-type="junk.GreatThings">
        <value>SUPER</value>
        <value>COOL</value>
    </util:list>

</beans>

The enum:

package junk;
public enum GreatThings {AMAZING, GREAT, SUPER, COOL}

The test class (in package junk - I've removed the import for clarity):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:junkcontext.xml"})  
public class TestAutowiringSupport {
    @Autowired @Qualifier("myList") List<GreatThings> greatThings;

    @Test public void testSuperCool() {
        Assert.assertThat(greatThings, hasItem(SUPER));
        Assert.assertThat(greatThings, hasItem(COOL));
    }
}

This result in a NoSuchBeanDefinitionException. I have try to put a @Qualifier with my bean id to help Spring to perform the wiring without any success.

My IDE is however able to detect the wiring by itself: enter image description here

And if I use the Spring lifecycle callbacks to get back the bean and wire it manually then, it is fine.

Version that compiles and runs fine:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport implements ApplicationContextAware
{

    ApplicationContext ctx;
    List<GreatThings> greatThings;

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {this.ctx = ctx;}

    @PostConstruct
    public void manualWiring() {greatThings = (List<GreatThings>) ctx.getBean("myList");}

    @Test public void testSuperCool() {
        Assert.assertThat(greatThings, hasItem(SUPER));
        Assert.assertThat(greatThings, hasItem(COOL));
    }

}

What's wrong with the autowiring in this case ?

like image 581
Guillaume Avatar asked Dec 06 '25 16:12

Guillaume


2 Answers

Looks like some problem with generics.

With Spring 4.1 I am able to execute this code: where greatThings is of type List<Object>

@Qualifier("myList")
@Autowired List<Object> greatThings;

@Test
public void testSuperCool() {
    Assert.assertThat(greatThings, Matchers.hasSize(2));
    Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.SUPER));
    Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.COOL));        
}
like image 54
Ralph Avatar answered Dec 10 '25 07:12

Ralph


As stated in the reference documentation, placing the @Autowired annotation over a typed collection means "find all beans of the given type (GreatThings in your case), put them in a collection and inject that collection". You are getting the exception because there are no beans of type GreatThings declared.

The problem is that there is no easy way to declare enum values as beans. Then again I don't see the use case to be honest.

like image 22
Apokralipsa Avatar answered Dec 10 '25 08:12

Apokralipsa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!