How to correctly initialise a Bean in the main method of a Spring Boot application?

Viewed 4428

I have the following configuration class:

@Configuration
public class StartupConfig {

    private final Logger log = LoggerFactory.getLogger(this.getClass().getSimpleName());

    @PostConstruct
    public void init() {
        log.debug("Start up config initialized.");
    }

    @Bean
    public SchedulerService schedulerService() {

        return new SchedulerService();
    }
}

I want to be able to load the schedulerService bean from the applications main method. Something like this:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.crm.config.StartupConfig;
import com.crm.service.SchedulerService;

@SpringBootApplication
@EnableCaching
public class Server {

    public static void main(String[] args) throws Exception {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(StartupConfig.class);
        context.refresh();

        SpringApplication.run(Server.class, args);

        SchedulerService schedulerService = (SchedulerService) context.getBean("schedulerService");
        schedulerService.start();
    }
}

The schedulerService class has an Autowired dependency:

    @Service
    @Transactional
    public class SchedulerService {

        @Autowired
        private SchedulerTriggerJpaDao schedulerTriggerJpaDao;
        ...

Here is the definition of SchedulerTriggerJpaDao:

package com.crm.dao;

import java.util.Collection;

import javax.transaction.Transactional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.crm.entity.SchedulerTrigger;

@Transactional
public interface SchedulerTriggerJpaDao extends JpaRepository<SchedulerTrigger, Integer> {

    public Collection<SchedulerTrigger> findByEnabledTrueAndDeletedFalse();

}

When I run up the application I get the following error:

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'schedulerService': Unsatisfied dependency expressed through field 'schedulerTriggerJpaDao'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.crm.dao.SchedulerTriggerJpaDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) 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)

What do I need to change to correctly initialise the schedulerService bean so it can also initialise the schedulerTriggerJpaDao dependency?

3 Answers

If your SchedulerTriggerJpaDao class has the following annotation

@Repository

then it should be recognised as a bean.

Your SchedulerTriggerJpaDao is just an interface. You need

  1. either provide a Dao implementation yourself and annotate it with @Component
    (FYI @Repository and @Service automatically mark class as component)

  2. or use some framework that will generate a Dao implementation for you based on your interface. E.g. Spring Data JPA (http://projects.spring.io/spring-data-jpa/)

The problem is that you are returning a new instance of the SchedulerService, which is not managed by spring. You are annotating the class as a @Service but spring is only managing the one injected by @Inject and/or @Autowire.

Related