Search code examples
springspring-integrationautowiredspring-beanspring-ioc

Spring dependency injection in external jar


I have a project A which is consuming a jar lets say B.jar (where B is another project used as a dependency in our project A), now there is a Bean (kind of a Spring-gemfire cache), which holds all the required data in a map. This map bean is being used by project (included as jar in my project) i.e B to read the cache properties , but i am unable to do so any help ?

my webapp-config.xml for project B

    <!-- Injecting bean in our A application -->
    <bean id="foo" class="com.abc.solutions.Foo" init-method="loadFoo">
             <property name="bar1" ref="gemFireBean"/>
             <property name="bar2" ref="commonBean"/>
    </bean>

    <bean id="b2" class="java.util.HashMap"
       factory-bean="foo" factory-method="createB2" autowire="byName">
    </bean>

the above bean b2 has to be used in external project B (included as jar in my project A).

part of clas sin project B2

@Autowired
    @Qualifier("b2")
    private Map<String, String> mapFromA;

but i am getting

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency

any help will be appreciated.


Solution

  • Short answer: a HashMap (or any other generic container like arrays or collections) should never be a Spring Bean. Only business objects should be beans, not infrastructure containers.

    You can circumvent this by building a custom object around your map and injecting this. In your case, you should inject your foo bean, and get the map from it programmatically.


    What happens in your case is outlines in the @Autowired section of the manual:

    Even typed Maps can be autowired as long as the expected key type is String. The Map values will contain all beans of the expected type, and the keys will contain the corresponding bean names:

    public class MovieRecommender {
    
        private Map<String, MovieCatalog> movieCatalogs;
    
        @Autowired
        public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
            this.movieCatalogs = movieCatalogs;
        }
    
        // ...
    
    }
    

    I.e. Spring thinks you want a map where the keys are the bean names and the values are beans of type string.