JavaFX & Spring Boot - NPE

血红的双手。 提交于 2021-02-17 04:53:45

问题


I'm still fighting with my issue. I want to use Spring Framework in order to incject dependencies and I have to use Spring boot to integrate both. Unfortunately, in first view autowiring is run correctly, but if I go next Stage, I got still only Null Pointer Exception.

Thats main class:

@SpringBootApplication(scanBasePackages = "boxingchallenge")
public class BoxingChallengeApplication extends Application {

    public ConfigurableApplicationContext springContext;
    private Parent root;
    public static Stage stage;

    @Override
    public void init() throws Exception {
        springContext = SpringApplication.run(BoxingChallengeApplication.class);
        springContext.getAutowireCapableBeanFactory().autowireBean(this);
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/FXML/start.fxml"));
        fxmlLoader.setControllerFactory(springContext::getBean);
        root = fxmlLoader.load();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        stage = primaryStage;
        primaryStage.setTitle("Boxing challenge");
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    @Override
    public void stop() {
        springContext.stop();
    }

    public static void main(String[] args) {
        launch(BoxingChallengeApplication.class, args);
    }
}

Here in first controller class autowiring run cool:

@Component
public class Start {

    @FXML
    public Button loadGame;
    @FXML
    public Button create;

    @Autowired
    private Boxer boxer;

    public void load(ActionEvent event) {
        System.out.println(boxer.getName());
    }

    //next stage
    public void createNew(ActionEvent event) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("/FXML/creator.fxml"));
        BoxingChallengeApplication.stage.setScene(new Scene(root));
    }
}

Here in second stage, autowiring not working:

@Component
public class Creator {

    @FXML
    public Button ready;
    public TextField nation;
    public TextField name;
    public Boxer boxer;

    /*@Autowired
    private ApplicationContext context;*/

    @Autowired
    public void setBoxer(Boxer boxer) {
        this.boxer = boxer;
    }

    public void createdAndPlay(ActionEvent event) {
        if (boxer == null)
            System.out.println("boxer is null");
        else
            System.out.println("Injected correctly");
    }
}

Thanks, i hope it's going to finished...


回答1:


@Jewelsea's comment is correct: you must set the controller factory when you load creator.fxml. If you don't do this, the FXMLLoader will create the controller simply by calling its no-arg constructor, so Spring will know nothing about it and will have no opportunity to inject any dependencies.

To do this, all you need is access to the ApplicationContext in Start, and you can inject "well-known objects", of which the ApplicationContext is an example, into your Spring-managed beans:

@Component
public class Start {

    @FXML
    public Button loadGame;
    @FXML
    public Button create;

    @Autowired
    private Boxer boxer;

    @Autowired
    private ApplicationContext context ;

    public void load(ActionEvent event) {
        System.out.println(boxer.getName());
    }

    //next stage
    public void createNew(ActionEvent event) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/FXML/creator.fxml"));
        load.setControllerFactory(context::getBean);
        Parent root = loader.load();
        BoxingChallengeApplication.stage.setScene(new Scene(root));
    }
}

As an aside, you almost certainly want a new instance of any controller when you load an FXML file, so you should probably make any controllers prototype scope.



来源:https://stackoverflow.com/questions/48290589/javafx-spring-boot-npe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!