【问题标题】:Why do I get NullPointerException with @Autowired Repository in Vaadin / SpringBoot application?为什么我在 Vaadin / SpringBoot 应用程序中使用 @Autowired Repository 获得 NullPointerException?
【发布时间】:2019-10-20 11:59:45
【问题描述】:

我开始使用 vaadin 和 Spring Boot 构建一个 Web 应用程序。我想创建一个 vaadin 站点,它在网格中列出来自 MSSQL Server 的数据。尝试使用我的 @Autowired CrudRepository 时,我总是得到 NullPointerException。

我已经阅读了很多 vaadin 和 spring 教程,在 Stackoverflow 上搜索过类似的问题,但还没有找到解决方案。在大多数情况下,同样的错误,人们忘记将 Repository 注释为 @Repository 或使用 new ... 我检查了所有常见的错误,但我无法让我的代码正常工作。 我还针对数据库编写了一个单元测试,效果很好!

带有@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);
    }

}

我的应用程序主类:

...
@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

【问题讨论】:

    标签: java spring-boot vaadin autowired vaadin-flow


    【解决方案1】:

    您的代码中的问题是您在构造函数 VaadinMainUI 中使用了 bewohnerRepository。在 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);
    }
    

    【讨论】:

    • 这很完美,非常感谢。尤其是解释帮助我避免了以后的此类错误。
    • 在这种情况下,使用 Inject 注释而不是 Autowire 可以吗?
    • @Techguy 如果使用Java EE CDI,注解自然是Inject。 Spring 和 CDI 以类似的方式实现。两者都支持构造函数参数注入,并且都在构造函数之后注入字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多