Проблема создания контекста spring framework

Пытаюсь написать эмулятор серверной части магазина. Для того, чтобы обмениваться данным между базой данных и HTTP запросами, созданы классы-контейнеры, экземпляры которых я пытаюсь создавать, используя технологии spring IoC контейнера. Но при создании конфигурации в классе, обрабатывающем post запросы, я получаю ошибку

nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'postController' defined in file [/home/aleksey/Stud/demo/target/classes/com/example/demo/controllers/PostController.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demo.controllers.PostController]: Constructor threw exception;

PostController - класс, где возникает ошибка

package com.example.demo.controllers;

import com.example.demo.Config;
import com.example.demo.DataBaseAssistant;
import com.example.demo.dataManagers.Desktop;
import com.example.demo.dataManagers.HardDisk;
import com.example.demo.dataManagers.Monitor;
import com.example.demo.dataManagers.Notebook;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PostController {
    private final ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

    @PostMapping(path = "/uploadDesktop")
    public @ResponseBody String uploadDesktop(@RequestParam("seriesNumber") int seriesNumber,
                                              @RequestParam("maker") String maker,
                                              @RequestParam("price") int price,
                                              @RequestParam("counter") int counter,
                                              @RequestParam("formFactor") String formFactor){
        Desktop desktop = context.getBean(Desktop.class);
        desktop.init(seriesNumber, maker, price, counter, formFactor);
        if(context.getBean(DataBaseAssistant.class).add(desktop)){
            return "Successful";
        } else return "Error in upload";
    }

    @PostMapping(path = "/uploadNotebook")
    public @ResponseBody String uploadNotebook(@RequestParam("seriesNumber") int seriesNumber,
                                               @RequestParam("maker") String maker,
                                               @RequestParam("price") int price,
                                               @RequestParam("counter") int counter,
                                               @RequestParam("size") int size){
        Notebook notebook = context.getBean(Notebook.class);
        notebook.init(seriesNumber, maker, price, counter, size);
        if(context.getBean(DataBaseAssistant.class).add(notebook)){
            return "Successful";
        } else return "Error in upload";
    }

    @PostMapping(path = "/uploadHardDisk")
    public @ResponseBody String uploadHardDisk(@RequestParam("seriesNumber") int seriesNumber,
                                               @RequestParam("maker") String maker,
                                               @RequestParam("price") int price,
                                               @RequestParam("counter") int counter,
                                               @RequestParam("volume") int volume){
        HardDisk hardDisk = context.getBean(HardDisk.class);
        hardDisk.init(seriesNumber, maker, price, counter, volume);
        if(context.getBean(DataBaseAssistant.class).add(hardDisk)){
            return "Successful";
        } else return "Error in upload";
    }

    @PostMapping(path = "/uploadMonitor")
    public @ResponseBody String uploadMonitor(@RequestParam("seriesNumber") int seriesNumber,
                                               @RequestParam("maker") String maker,
                                               @RequestParam("price") int price,
                                               @RequestParam("counter") int counter,
                                               @RequestParam("diagonal") int diagonal){
        Monitor monitor = context.getBean(Monitor.class);
        monitor.init(seriesNumber, maker, price, counter, diagonal);
        if(context.getBean(DataBaseAssistant.class).add(monitor)){
            return "Successful";
        } else return "Error in upload";
    }
}

Config - класс конфигурации

package com.example.demo;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class Config {}

Desctop - один из компонентов конфигурации

package com.example.demo.dataManagers;

import org.springframework.stereotype.Component;

@Component
public class Desktop extends Data {
    protected String formFactor;

    public Desktop(int id, int seriesNumber, String maker, int price, int counter, String formFactor){
        super(id, seriesNumber, maker, price, counter);
        this.formFactor = formFactor;
    }

    public void init(int seriesNumber, String maker, int price, int counter, String formFactor) {
        super.init(seriesNumber, maker, price, counter);
        this.formFactor = formFactor;
    }

    @Override
    public String toString() {
        return "Desktop{" +
                "seriesNumber=" + seriesNumber +
                ", price=" + price +
                ", counter=" + counter +
                ", maker='" + maker + '\'' +
                ", formFactor='" + formFactor + '\'' +
                '}';
    }

    public String getFormFactor() {
        return formFactor;
    }
}

Ответы (1 шт):

Автор решения: Roman Konoval

В вашем коде несколько проблем.

Первая, это ручное создание контекста в PostController. Контекст в spring boot приложении создается кодом типа такого:

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

Так что удалите из PostController поле context.

Вторая проблема, это то как вы пробуете использовать бины из контекста. Если вам нужно использовать DataBaseAssistant правильно использовать внедрение зависимостей (англ. dependency injection), т.е. делать так:

@RestController
public class PostController {
    @Autowired
    private DataBaseAssistant databaseAssistant;

    @PostMapping(path = "/uploadDesktop")
    public @ResponseBody String uploadDesktop(@RequestParam("seriesNumber") int seriesNumber,
                                              @RequestParam("maker") String maker,
                                              @RequestParam("price") int price,
                                              @RequestParam("counter") int counter,
                                              @RequestParam("formFactor") String formFactor){
        Desktop desktop = new Desktop(seriesNumber, maker, price, counter, formFactor);
        if(databaseAssistant.add(desktop)){
            return "Successful";
        } else return "Error in upload";
    }

Спринг сам проинициализирует поле databaseAssistant соответствующим бином из контекста.

Третья проблема - это использование бинов типа Desktop, Notebook и т.д. Не нужно эти классы делать бинами, которыми управляет спринг. Уберите из них аннотации @Component и создавайте экземпляры как в примере выше.

→ Ссылка