3

I don't quite understand why this code gives me 'no default constructor found' error. The constructor is @Autowired. Everything seems to be injected correctly. Can anybody please help? Thanks

@SpringBootApplication
public class Application {

    private ApplicationContext applicationContext;
    private MessagingService messagingService;
    private Parser parser;

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    @Autowired
    public Application(ApplicationContext applicationContext,
                       MessagingService messagingService,
                       Parser parser)
    {
        this.applicationContext = applicationContext;
        Assert.notNull(messagingService, "MessagingService must not be null");
        this.messagingService = messagingService;
        Assert.notNull(parser, "Parser must not be null");
        this.parser = parser;
    }

    public static void main (String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner app() {
        return args -> {
            Locale defaultLocale = Locale.getDefault();
            Locale.setDefault(defaultLocale);
            log.info("Using MessagingService: " + messagingService.getMyMessageCode());

            parser.parse();
        };
    }
}

Edit: updated Application.class

@SpringBootApplication
public class Application {

    @Autowired
    private MessagingService messagingService;
    @Autowired
    private Parser parser;

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public Application() {}

    public static void main (String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner app() {
        return args -> {
            Locale defaultLocale = Locale.getDefault();
            Locale.setDefault(defaultLocale);
            log.info("Using MessagingService: " + messagingService.getMyMessageCode());

            parser.parse();
        };
    }
}
Deniss M.
  • 3,617
  • 17
  • 52
  • 100
  • default constructor means constructor without any argument. Look at your code if you have any default constructor. Don't use other spring annotation in your main class with @SpringBootAnnotation annotation. – SMA Sep 11 '16 at 08:57

2 Answers2

4

Answer from luboskrnac is correct.

But if you really want to use Constructor Injection you can upgrade you SpringBoot version to 1.4.0.RELEASE which will use Spring 4.3.2.RELEASE

From Spring 4.3 Constructor Injection is supported on @Configuration class

New Features and Enhancements in Spring Framework 4.3

Community
  • 1
  • 1
A0__oN
  • 8,740
  • 6
  • 40
  • 61
  • Thanks! Now I understand why constructor injection was working almost everywhere at work, but not at home. I have version 1.4.0 of spring boot at work, but 1.2.3 at home. Thanks for the tip! – Deniss M. Sep 11 '16 at 12:46
3

You can't autowire into main Spring Boot class. You can inject dependencies needed for CommandLineRunner as parameters of method annotated with @Bean and of course remove constructor injection for main class:

@SpringBootApplication
public class Application {
    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public static void main (String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner app(ApplicationContext applicationContext,
                       MessagingService messagingService,
                       Parser parser) {
        return args -> {
            Locale defaultLocale = Locale.getDefault();
            Locale.setDefault(defaultLocale);
            log.info("Using MessagingService: " + messagingService.getMyMessageCode());

            parser.parse();
        };
    }
}

EDIT: Correct context configuration after edit:

@SpringBootApplication
public class Application {

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public Application() {}

    public static void main (String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner app(MessagingService messagingService, Parser parser) {
        return args -> {
            Locale defaultLocale = Locale.getDefault();
            Locale.setDefault(defaultLocale);
            log.info("Using MessagingService: " + messagingService.getMyMessageCode());

            parser.parse();
        };
    }
}
luboskrnac
  • 23,973
  • 10
  • 81
  • 92
  • Thanks! That's what I wanted to know. I have made an edit to my class, can you please take a look and tell me if I can inject my dependencies in such manner also as it seems to be more clean in my opinion? – Deniss M. Sep 11 '16 at 09:02
  • I included correct context configuration for your class updated class. – luboskrnac Sep 11 '16 at 09:07
  • Thanks a lot! So it is OK to inject as many dependencies into my CommandLineRunner app as I need. The reason I am asking is that I had done this before and have been told, that is it not correct and should be done as per my EDIT version of the class. – Deniss M. Sep 11 '16 at 09:11
  • 1
    Injection via `@Bean` method parameters is perfectly valid and supported feature of Spring IoC container. If anybody says "it is not correct", he should educate himself. – luboskrnac Sep 11 '16 at 09:18