0

My Autowire works perfectly everywhere but not on my threads. I get this error:

Description:

Field dockerService in threads.EnvironmentThread required a bean of type 'services.DockerService' that could not be found.

Action:

Consider defining a bean of type 'services.DockerService' in your configuration.

My code:

 @SpringBootApplication
public class IzyApplication implements CommandLineRunner{

@Autowired
private DockerService dockerService;

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


@Override
public void run(String... args) {

    // Call Threads
    ApplicationContext context = new AnnotationConfigApplicationContext(ThreadConfig.class);
    EnvironmentThread environmentThread = (EnvironmentThread) context.getBean("environmentThread");
    environmentThread.setName("Environment Thread");

    //Start Them
    environmentThread.start();
}

}

Thread : The error get's thrown when running the EnvironmentThread environmentThread = (EnvironmentThread) context.getBean("environmentThread");

@Component
@Scope("prototype")
public class EnvironmentThread extends Thread {

private static final Logger logger = Logger.getLogger(EnvironmentThread.class);

@Autowired
private DockerService dockerService;
@Autowired
private SettingsService settingsService;
@Autowired
private EnvironmentRepository environmentRepository;
@Autowired
private ReportService reportService;

@Override
public void run() {

}

ThreadConfig

@Configuration
@ComponentScan(basePackages = {"threads"})
public class ThreadConfig {

}

Service

@Service("dockerService")
public class DockerService {

private static Logger logger;
public DockerClient dockerClient;
@Autowired
private SettingsService settingsService;

// #####################  BUILD CONNECTION WITH DOCKER ####################################
@Singleton
public void buildDockerClient() {

    logger = Logger.getLogger(DockerService.class);

    try {
        //todo remove id
        Settings settings = settingsService.getSettings();
        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost("tcp://" + settings.getDockerIP() + ":" + settings.getDockerPort())
                .withDockerConfig("/home/user/.docker/config.json")
                .build();

        dockerClient = DockerClientBuilder.getInstance(config).build();

    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
  }
Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • You can only autowire things inside the spring-managed beans, and the one which starts the spring app is clearly not one of those. It has nothing to do with Thread. – Jan Ossowski May 18 '18 at 15:46
  • look my code again. The dockerService works on the main.java of the springbootapplication. But doesn't work on the EnvironmentThread class –  May 18 '18 at 15:50
  • oh I see, I got confused. The problem here is the prototype scope, look here https://stackoverflow.com/questions/9819994/spring-autowire-and-prototype-scope – Jan Ossowski May 18 '18 at 15:55
  • can you please fix your formatting so that "public class EnvironmentThread extends Thread {" is also marked as code? – Jan Ossowski May 18 '18 at 15:57

1 Answers1

0

You're creating an application context with the settings from your ThreadConfig which specifies @ComponentScan(basePackages = {"threads"}).

DockerService is in package services. That application context doesn't know about it, because you didn't tell it to scan that package.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • Yeah but why create a new context in the first place? And besides, a prototype-scoped bean still won't autowire. – rustyx May 18 '18 at 16:22
  • @rustyx I didn't write the code, so I really don't know the idea behind creating a new context. `EnvironmentThread` is scoped prototype, and others are the default singleton, so there's no problem with autowiring the singletons to the prototype. What use would prototype beans be if you couldn't autowire them? He's also not autowiring the prototype bean, he's getting it from the application context with `getBean()`. – Kayaman May 18 '18 at 16:25