Почему я получаю исключение NullPointerException с репозиторием @Autowired в приложении Vaadin / SpringBoot?

Я начинаю создавать веб-приложение с vaadin и spring boot. Я хочу создать сайт vaadin, который перечисляет данные с сервера MSSQL в сетке. Я всегда получаю NullPointerException при попытке использовать мой @Autowired CrudRepository.

Я прочитал много руководств по vaadin и spring, искал в Stackoverflow похожие проблемы, но пока не нашел решения. В большинстве случаев с той же ошибкой люди забывали аннотировать репозиторий как @Repository или создавали класс пользовательского интерфейса с новым ... Я проверил все эти распространенные ошибки, но не могу заставить свой код работать. Я также написал модульные тесты для базы данных, которая отлично работает!

Мой интерфейс CrudRepository с аннотацией @Repository

...
@Repository
public interface BewohnerRepository extends CrudRepository<Bewohner, Integer>{
    ...
}
...

Мой пользовательский интерфейс, который должен отображать данные с репозиторием @Autowired

...
@Route("")
@SpringComponent
@Configurable
public class VaadinMainUI extends VerticalLayout {

    @Autowired
    private BewohnerRepository bewohnerRepository;

    public VaadinMainUI() {     
        Grid<Bewohner> grid = new Grid<Bewohner>(Bewohner.class);
        Iterable<Bewohner> bewohnerList = bewohnerRepository.findAll();
        grid.setItems((Collection<Bewohner>) bewohnerList);
        add(grid);
    }

}

Основной класс Мои приложения:

...
@SpringBootApplication
public class IndikatorenbogenApplication {

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

Мой тест JUnit, который также использует репозиторий @Autowired (этот тест отлично работает и отображает данные из моей БД:

...

@RunWith(SpringRunner.class)
@SpringBootTest
public class BewohnerRepositoryTest {

    @Autowired
    private BewohnerRepository bewohnerRepository;

    @Test
    public void testInjectedComponentsNotNull() {
        assertNotNull(bewohnerRepository);
    }

    @Test
    public void testFetchData(){
        Iterable<Bewohner> bewohnerList = bewohnerRepository.findAll();
        int count = 0;
        for(Bewohner bewohner : bewohnerList){          
            count++;
            System.out.println(count +": " + bewohner);
        }
        assertEquals(count, 1178);
    }
}

Мой ожидаемый результат состоит в том, что 1178 строк, перечисленных в тесте, отображаются в сетке в моем классе VaadinMainUI. Но вместо этого при запуске приложения я получаю исключение NullPointerException:

...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [de.lim.tap.indikatorenbogen.ui.VaadinMainUI]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:184)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1295)
    ... 23 more

person tigu    schedule 04.06.2019    source источник


Ответы (1)


Проблема в вашем коде заключается в том, что вы используете bewohnerRepository в конструкторе VaadinMainUI. В Spring Autowired поля недоступны в конструкторах, поскольку внедрение поля выполняется после конструктора. Поэтому вам нужно соответствующим образом изменить свой код. Вы можете, например, есть собственный метод, в котором вы это делаете, и аннотируйте его аннотацией @PostConstruct, что заставляет Spring вызывать его после инъекции поля.

@PostConstruct
private void doGridSetup() {
Grid<Bewohner> grid = new Grid<Bewohner>(Bewohner.class);
        Iterable<Bewohner> bewohnerList = bewohnerRepository.findAll();
        grid.setItems((Collection<Bewohner>) bewohnerList);
        add(grid);
}

Или, в качестве другой альтернативы, вы можете автоматически подключить bewohnerRepository в качестве параметра конструктора:

@Autowire
public VaadinMainUI(BewohnerRepository bewohnerRepository) {
Grid<Bewohner> grid = new Grid<Bewohner>(Bewohner.class);
        Iterable<Bewohner> bewohnerList = bewohnerRepository.findAll();
        grid.setItems((Collection<Bewohner>) bewohnerList);
        add(grid);
}
person Tatu Lund    schedule 05.06.2019
comment
Это отлично работает, большое вам спасибо. Особенно объяснение помогло мне избежать подобных ошибок в будущем. - person tigu; 06.06.2019