为什么在 Vaadin / SpringBoot 应用程序中使用 @Autowired Repository 会出现 NullPointerException?
Why do I get NullPointerException with @Autowired Repository in Vaadin / SpringBoot application?
我开始使用 vaadin 和 spring 引导构建 Web 应用程序。我想创建一个 vaadin 站点,它在网格中列出来自 MSSQL Server 的数据。尝试使用我的@Autowired CrudRepository 时,我总是得到 NullPointerException。
我已经阅读了很多 vaadin 和 spring 教程,在 Whosebug 上搜索了类似的问题,但还没有找到解决方案。在大多数出现相同错误的情况下,人们忘记将存储库注释为 @Repository 或使用 new 创建 UI class ...
我检查了所有常见错误,但我的代码无法正常工作。
我还针对数据库编写了单元测试,效果很好!
带有@Repository 注释的我的 CrudRepository 接口
...
@Repository
public interface BewohnerRepository extends CrudRepository<Bewohner, Integer>{
...
}
...
我的 UI 应该显示带有@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);
}
}
我的应用程序主要 class:
...
@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 行显示在我的 VaadinMainUIclass 的网格中。但是在启动我的应用程序时,我得到了 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
您的代码中的问题是您在构造函数 VaadinMainUI 中使用了 bewohnerRepository。在 Spring 中,自动装配的字段在构造函数中不可用,因为字段注入是在构造函数之后完成的。所以你需要相应地改变你的代码。你可以例如在执行此操作的地方有自定义方法,并使用 @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);
}
我开始使用 vaadin 和 spring 引导构建 Web 应用程序。我想创建一个 vaadin 站点,它在网格中列出来自 MSSQL Server 的数据。尝试使用我的@Autowired CrudRepository 时,我总是得到 NullPointerException。
我已经阅读了很多 vaadin 和 spring 教程,在 Whosebug 上搜索了类似的问题,但还没有找到解决方案。在大多数出现相同错误的情况下,人们忘记将存储库注释为 @Repository 或使用 new 创建 UI class ... 我检查了所有常见错误,但我的代码无法正常工作。 我还针对数据库编写了单元测试,效果很好!
带有@Repository 注释的我的 CrudRepository 接口
...
@Repository
public interface BewohnerRepository extends CrudRepository<Bewohner, Integer>{
...
}
...
我的 UI 应该显示带有@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);
}
}
我的应用程序主要 class:
...
@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 行显示在我的 VaadinMainUIclass 的网格中。但是在启动我的应用程序时,我得到了 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
您的代码中的问题是您在构造函数 VaadinMainUI 中使用了 bewohnerRepository。在 Spring 中,自动装配的字段在构造函数中不可用,因为字段注入是在构造函数之后完成的。所以你需要相应地改变你的代码。你可以例如在执行此操作的地方有自定义方法,并使用 @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);
}