5

I have tried this solution found in the following questions, but none work in my case:

@Configuration
@EnableWebMvc
@ComponentScan("myapp.framework.export")
public class WebConfig extends MyAppWebConfig {

    @Override
    public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {

        super.configureContentNegotiation(configurer);

    }

    @Override
    public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {

        super.configureMessageConverters(converters);

    }

}

Error:

INFO: Initializing Spring FrameworkServlet 'services-rest'
2017-04-11 15:25:52,774|localhost-startStop-1|NO_TID|NO_USER|ERROR|org.springframework.web.servlet.DispatcherServlet.initServletBean|Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xlsHttpMessageConverter': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:321)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:138)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1241)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1154)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1041)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4969)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318)
    ... 29 common frames omitted

Apr 11, 2017 3:25:52 PM org.apache.catalina.core.ApplicationContext log
SEVERE: StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xlsHttpMessageConverter': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:321)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:138)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1241)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1154)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1041)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4969)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318)
    ... 29 more

Apr 11, 2017 3:25:52 PM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet /myapp threw load() exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:138)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1241)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1154)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1041)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4969)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Apr 11, 2017 3:25:52 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
Apr 11, 2017 3:25:52 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-nio-8009"]
Apr 11, 2017 3:25:52 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 10565 ms

xlsHttpMessageConverter:

package myapp.framework.web.converter;

import myapp.framework.export.ExportXlsModelService;

import java.io.IOException;
import java.io.OutputStream;

import javax.annotation.Resource;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Service;
    @Service
    public class XlsHttpMessageConverter<T> extends
                AbstractMyAppHttpMessageConverter<T, ExportXlsModelService<T>> {

        @Resource
        private ExportXlsModelService<T>[] exportServices;

        public XlsHttpMessageConverter() {

            super(MyAppMediaType.APPLICATION_EXCEL);
        }

        @Override
        protected void ecrireFichier(final T toExport, final OutputStream os) throws IOException,
            HttpMessageNotWritableException {

            final ExportXlsModelService<T> exportService = getServiceExport(toExport);

            final HSSFWorkbook model = exportService.construireXlsModel(toExport);
            model.write(os);
        }

        @Override
        protected ExportXlsModelService<T>[] getServicesExport() {

            return exportServices;
        }

    }
Mercer
  • 9,736
  • 30
  • 105
  • 170
  • Post `xlsHttpMessageConverter` bean code. The problem is there. – Strelok Apr 12 '17 at 07:37
  • @Strelok i have Post xlsHttpMessageConverter bean code. – Mercer Apr 12 '17 at 07:40
  • Can you try and change that field to an List instead of array and see if that works? – Strelok Apr 12 '17 at 07:55
  • @Strelok Which fields .? – Mercer Apr 12 '17 at 07:58
  • `@Resource private ExportXlsModelService[] exportServices;` – Strelok Apr 12 '17 at 08:27
  • @Strelok i have the same pb – Mercer Apr 12 '17 at 09:46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/141528/discussion-between-mercer-and-strelok). – Mercer Apr 12 '17 at 09:51
  • @Strelok Can you explain me why if i change that field to an List instead of array there is no error ? – Mercer Apr 12 '17 at 14:18
  • If your jar file has it's own configuration, you need to import that configuration. In your WebConfig class add @Import({ .class}) – user871199 Apr 13 '17 at 23:53
  • what is definition in jar for "ExportXlsModelService" ? Is that annoted with @service? – utkusonmez Apr 14 '17 at 08:32
  • Have you tried with @Qualifier and if so, what error did you got? – sschrass Apr 14 '17 at 08:52
  • @sschrass i have tried with `@Qualifier` i have the same error – Mercer Apr 14 '17 at 09:41
  • @utkusonmez `public interface ExportXlsModelService extends ExportModelService { public HSSFWorkbook construireXlsModel(T toExport); ` – Mercer Apr 14 '17 at 09:42
  • @utkusonmez yes taht is anoted with `@service?` – Mercer Apr 14 '17 at 12:13
  • you can try @ComponentScan() & put the path of the ExportXlsModelService's implementation class. – Gurpreet Singh Apr 15 '17 at 12:23
  • Otherwise if you can change the jar file.. have a look http://stackoverflow.com/questions/30796306/cant-i-autowire-a-bean-which-is-present-in-a-dependent-library-jar – Gurpreet Singh Apr 15 '17 at 12:24
  • @Gurpreet Singh can you post an example please – Mercer Apr 15 '17 at 16:26
  • I believe this because of the generics, can you try removing generics ?. – Keaz Apr 18 '17 at 11:03
  • In your provided example there is something missing. ComponentScan("myapp.framework.export") but the class XlsHttpMessageConverter is in other package – reos Apr 18 '17 at 17:07
  • StanislavL says you have different packages in your ComponentScan and your service therefore Spring would not find them this is usually resolved by sending an array to ComponentScan instead of a single string `@ComponentScan({"myapp.framework.export","myapp.framework.web.converter"})` try that and see if it solves your problem, otherwise we need more information on the problem. Also [check this answer](http://stackoverflow.com/questions/10794587/how-to-scan-multiple-paths-using-the-componentscan-annotation). – Nord Apr 18 '17 at 20:02
  • which version of spring are you using? – Prateek Jain Apr 19 '17 at 15:46
  • @techtrainer Spring 4.3.7 – Mercer Apr 19 '17 at 21:55
  • 1. Any specific reason that you are extending and injecting same class ExportXlsModelService, inside XlsHttpMessageConverter? 2. see this http://stackoverflow.com/questions/35749819/spring-4-2-4-autowiring-list-of-extended-generic-interfaces – Prateek Jain Apr 20 '17 at 10:17

3 Answers3

5

Try to add classpath*: Prefix to your scan. (read here)

The * means scan in all jars on classpath

UPDATE:

Your converter has package myapp.framework.web.converter but scan checks myapp.framework.export

StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • i have to try to add `classpath*:` i have the same problem – Mercer Apr 12 '17 at 07:56
  • Your component scan can not find it as it is scanning the wrong package as suggested. Package myapp.framework.web.converter is not within the hierarchy of myapp.framework.export. – Michael Hibay Apr 20 '17 at 21:43
1

I think there is issue in autowiring as Generic class. We have to specify particular Type while autowiring.

Following Reference may be useful:

  1. Reference1
  2. Reference2
Community
  • 1
  • 1
Mitul Gedeeya
  • 886
  • 1
  • 10
  • 20
1

You can't have a @Service that has a type parameter T, how would Spring know what T should be when it instantiates the bean.

If you have 5 different XlsHttpMessageConverter<T>, you have to declare 5 beans. Unfortunately even if you define each converter as a separate bean, there is no way for Spring to know which ExportXlsModelService<T>[] exportServices; to inject, as it will consider all ExportXlsModelService as candidate regardless of the type parameter (see edit below).

It is however possible to inject a bean of a specific type into a @Bean method, so the following example works (but is very impractical for large number of types).

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

import static org.junit.Assert.assertNotNull;

@Configuration
public class MyConfig {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);

        ConverterInjectionTarget bean = ctx.getBean(ConverterInjectionTarget.class);
        System.out.println("injected Converters = " + bean.converters.size());
        for (XlsHttpMessageConverter converter : bean.converters) {
            assertNotNull(converter.value);
        }
    }

    // correct version of generic bean can be autowired into @Bean method
    @Bean
    XlsHttpMessageConverter integerConverter(Injectable<Integer> value) {
        return new XlsHttpMessageConverter<>(value);
    }

    @Bean
    XlsHttpMessageConverter StringConverter(Injectable<String> value) {
        return new XlsHttpMessageConverter<String>(value);
    }

    @Bean
    Injectable<Integer> integerDummyBean() {
        return new Injectable<>(1);
    }

    @Bean
    Injectable<String> stringDummyBean() {
        return new Injectable<>("hello");
    }

    @Bean
    ConverterInjectionTarget myBean() {
        return new ConverterInjectionTarget();
    }

    static class XlsHttpMessageConverter<T> {
        // impossible to autowire this, it has to be set through the constructor
        final Injectable<T> value;

        XlsHttpMessageConverter(Injectable<T> value) {
            this.value = value;
        }
    }

    static class ConverterInjectionTarget {
        @Autowired
        List<XlsHttpMessageConverter> converters;
    }

    class Injectable<T> {
        final T value;

        Injectable(T value) {
            this.value = value;
        }
    }
}

If you modify the example and try to autowire the Injectable into XlsHttpMessageConverter you will see that it fails.

The best solution may be to create a BeanFactoryPostProcessor that will create all the ExportXlsModelService instances programmatically, and provide them as input to the XlsHttpMessageConverter instances, which are then registered as singletons.

EDIT One thing I did not mention, is that it is possible to autowire a generic type, but it requires that the bean is defined as a concrete class (not using a @Bean method), so the following would also work (multiple files).

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.List;

import static org.junit.Assert.assertNotNull;

@Configuration
@ComponentScan("myPackage")
public class MyConfig {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);

        ConverterInjectionTarget bean = ctx.getBean(ConverterInjectionTarget.class);
        System.out.println("injected Converters = " + bean.converters.size());
        for (XlsHttpMessageConverter converter : bean.converters) {
            assertNotNull(converter.value);
        }
    }

    @Bean
    Injectable<Integer> integerDummyBean() {
        return new Injectable<>(1);
    }

    @Bean
    Injectable<String> stringDummyBean() {
        return new Injectable<>("hello");
    }

    @Bean
    ConverterInjectionTarget myBean() {
        return new ConverterInjectionTarget();
    }

    static class ConverterInjectionTarget {
        @Autowired
        List<XlsHttpMessageConverter> converters;
    }

    static class Injectable<T> {
        final T value;

        Injectable(T value) {
            this.value = value;
        }
    }
}

abstract class  XlsHttpMessageConverter<T> {
    // this is possible to autowire because we have a concrete class that spring can read the bytecode from.
    @Autowired
    MyConfig.Injectable<T> value;
}

@Service
public class IntegerXlsHttpMessageConverter<T> extends XlsHttpMessageConverter<Integer> {
}

@Service
public class StringXlsHttpMessageConverter extends XlsHttpMessageConverter<String> {
}

But again this may not be feasible if there are many types.

Klaus Groenbaek
  • 4,820
  • 2
  • 15
  • 30