Required Multiple beans of same type in Spring

78,148

Solution 1

You should qualify your autowired variable to say which one should be injected

@Autowired
@Qualifier("A1Unmarshaller")
private Jaxb2Marshaller A1Unmarshaller;

The default autowiring is by type, not by name, so when there is more than one bean of the same type, you have to use the @Qualifier annotation.

Solution 2

The Jaxb2Marshaller is perfectly capable to work with multiple different contexts/xsd. Simply specify multiple context paths by using the setContextPaths methods.

@Bean(name="A1Unmarshaller")
public Jaxb2Marshaller A1Unmarshaller(){
    Jaxb2Marshaller unMarshaller = new Jaxb2Marshaller();
    unMarshaller.setContextPaths(
        "package name for the classes generate by XSD A1",
        "package name for the classes generate by XSD A2",
        "package name for the classes generate by XSD A3",
        "package name for the classes generate by XSD A4",
        "package name for the classes generate by XSD A5" );
    return unMarshaller;
}

That way you only need a single marshaller/unmarshaller.

Links

  1. Jaxb2Marshaller javadoc
  2. setContextPaths javadoc

Solution 3

Injection using @Resource annotation is what you're looking for. You can use

@AutoWired
@Qualifier("A1Unmarshaller")
private Jaxb2Marshaller A1Unmarshaller;

But that is not the only way.

@Resource("A1Unmrshaller")

Does the job too. I suggest you use the later one! See why

Share:
78,148
dharam
Author by

dharam

Updated on December 10, 2020

Comments

  • dharam
    dharam over 3 years

    A request before you mark it as duplicate. I have gone through the forum and couldn't find the solution for the problem anywhere.

    I am writing a code using Spring 3.2 and everything is purely annotation based. The code receives XML files which are derived form different XSD files.

    So we can say, there are five different XSD ( A1, A2, A3, A4, A5) and my code receives XML of any type, and I have the logic to identify the type of the XML upon arrival.

    Now, I am trying to un-marshal these using Spring OXM. But because there are multiple XSDs involved, we cannot actually using one Un-marshaller. So we need around five of them.

    In the Configuration class, I added five beans like below:

    @Bean(name="A1Unmarshaller")
    public Jaxb2Marshaller A1Unmarshaller(){
        Jaxb2Marshaller unMarshaller = new Jaxb2Marshaller();
        unMarshaller.setContextPath("package name for the classes generate by XSD A1");
    }
    
    @Bean(name="A2Unmarshaller")
    public Jaxb2Marshaller A2Unmarshaller(){
        Jaxb2Marshaller unMarshaller = new Jaxb2Marshaller();
        unMarshaller.setContextPath("package name for the classes generate by XSD A2");
    }
    
    @Bean(name="A3Unmarshaller")
    public Jaxb2Marshaller A3Unmarshaller(){
        Jaxb2Marshaller unMarshaller = new Jaxb2Marshaller();
        unMarshaller.setContextPath("package name for the classes generate by XSD A3");
    }
    
    @Bean(name="A4Unmarshaller")
    public Jaxb2Marshaller A4Unmarshaller(){
        Jaxb2Marshaller unMarshaller = new Jaxb2Marshaller();
        unMarshaller.setContextPath("package name for the classes generate by XSD A4");
    }
    
    @Bean(name="A5Unmarshaller")
    public Jaxb2Marshaller A5Unmarshaller(){
        Jaxb2Marshaller unMarshaller = new Jaxb2Marshaller();
        unMarshaller.setContextPath("package name for the classes generate by XSD A5");
    }
    

    Now I have five different classes C1, C2, C3, C4 and C5 and I am trying to inject one unmarshaller bean into one class. That means A1Unmarshaller is autowired to C1 and so on.

    When the Spring context is built, it throws an error saying it expected one bean of type Jaxb2Marshaller and got five.

    Note It worked fine when done using XML configuration, so I am not sure if I am missing something. Please help.

    EDIT The code for one of the classes C1 is below:

    @Component
    public class C1{
    
    @Autowired
    private Jaxb2Marshaller A1Unmarshaller;
        A1 o = null
    
    public boolean handles(String event, int eventId) {
        if (null != event&& eventId == 5) {
                    A1 =  A1Unmarshaller.unMarshal(event);
            return true;
        }
        return false;
    }
    

    }

  • UHDante
    UHDante over 4 years
    This help me a lot, thx! That "s" -> setContextPath"s" save my day.