3

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 ?

Guillaume
  • 5,488
  • 11
  • 47
  • 83

2 Answers2

1

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.

Apokralipsa
  • 2,674
  • 17
  • 28
1

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));        
}
Ralph
  • 118,862
  • 56
  • 287
  • 383
  • The weird thing was that Intellij was able to detect the wiring and to provide auto-completion in the list declaration. That gave me the feeling that the setting was "correct" but maybe bugged or badly supported in Spring 3.1. Thank you for this confirmation. – Guillaume Oct 21 '16 at 07:43
  • Is the same code able to execute with a List ??? I can't run the code in Spring 3 even with a List – Guillaume Oct 21 '16 at 12:12
  • @Guillaume: `List` does not work, only `List` - I tryed to make this in my answer explicit in the second line. – Ralph Oct 22 '16 at 08:06