Spring Bean дает исключение NullPointerException, но не является нулевым - PullRequest
0 голосов
/ 14 января 2020

Я использую Spring с конфигурацией XML для настройки зависимостей bean-компонентов в программе текстового редактора, в которой я использую JavaFX для GUI. Для выбора файлов у меня есть класс File Manager, в который должна быть вставлена ​​стадия приложения. У меня есть 2 метода печати объекта Stage, чтобы увидеть, является ли он нулевым или нет. В методе init() объект печатается успешно, выводя javafx.stage.Stage@1cdcac0e. Но когда я вызываю метод open(), я получаю сообщение об ошибке.

Во-первых, так настроены мои bean-компоненты в Beans. xml:

<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="main" class="config.Main" scope="singleton" init-method="initiate">

    </bean>

    <bean id = "fileManager" class="files.FileManager" scope="singleton" init-method="init">
        <property name="ownerWindow" value="#{main.primaryStage}"/>
    </bean>

    <bean id = "editor" class = "controllers.Editor" init-method="init">
        <property name="fileManager">
            <bean id="fileManager" class="files.FileManager"/>
        </property>
    </bean>

</beans>

Вот мой Класс File Manager.

package files;

import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class FileManager {
    Stage ownerWindow;
    FileChooser fileChooser;

    public void open() {
        System.out.println(ownerWindow);
    }

    public void setOwnerWindow(Stage ownerWindow) {
        this.ownerWindow = ownerWindow;
    }
    public void init() {
        System.out.println(ownerWindow);
    }
}

Мой основной класс такой:

package config;

public class Main extends Application {
    public static ApplicationContext context = new ClassPathXmlApplicationContext("/Beans.xml");
    FXMLLoader loader = new FXMLLoader();
    public Stage primaryStage = new Stage();
    Parent root;
    String rootPath = "/views/Editor.fxml";
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        root = loader.load(getClass().getResourceAsStream(rootPath));
        this.primaryStage.setScene(new Scene(root));
        this.primaryStage.show();

    }

    public void setPrimaryStage(Stage primaryStage) {
        this.primaryStage = primaryStage;
    }
    public void initiate() {
        System.out.println(primaryStage);
    }
}

Метод initiate() в Main печатает ту же строку, что и метод init() в FileManager, поэтому я предполагаю, что Spring успешно вводит primaryStage в класс FileManager. Несмотря на это, когда я вызываю open() из третьего класса, а именно Editor класса, я получаю NullPointerException:

java.lang.NullPointerException at controllers.Editor.openNewFile(Editor.java:15)

Класс Editor является контроллером для GUI моего приложения, у него есть экземпляр FileManager, который должен быть внедрен Spring, и в методе init(), который просто печатает объект FileManager, программа выводит files.FileManager@668188db, поэтому я предполагаю, что экземпляр был успешно внедрен и не должно быть нулевым. Мой класс редактора выглядит следующим образом:

package controllers;

public class Editor {
    //Spring bean
    private FileManager fileManager;
    @FXML TextArea page;
    @FXML Menu menuFile;

    @FXML private void openNewFile() {
        fileManager.open();
    }

    public void setFileManager(FileManager fileManager) {
        this.fileManager = fileManager;
    }
    public void init() {
        System.out.println(fileManager);
    }

}

Метод openNewFile() - это то, где выдается ошибка. Мой файл f xml на случай, если он поможет:

<AnchorPane prefHeight="600.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"
        fx:controller="controllers.Editor">
   <children>
       <MenuBar layoutX="188.0" layoutY="14.0" AnchorPane.bottomAnchor="575.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
           <Menu fx:id="menuFile" mnemonicParsing="false" text="File">
               <MenuItem text="New" onAction="#openNewFile"/>
               <MenuItem text="Open"/>
               <MenuItem text="Open Recent"/>
               <MenuItem text="Save"/>
               <MenuItem text="Save as"/>
               <MenuItem text="Close"/>
           </Menu>
       </MenuBar>
      <BorderPane layoutX="250.0" layoutY="178.0" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="100.0" AnchorPane.rightAnchor="100.0" AnchorPane.topAnchor="100.0">
        <center>
            <AnchorPane prefHeight="550.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
                <children>
                    <TextArea fx:id="page" layoutX="186.0" layoutY="100.0" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                        <padding>
                            <Insets right="10.0" />
                        </padding>
                    </TextArea>
                </children>
            </AnchorPane>
        </center>
      </BorderPane>
   </children>
</AnchorPane>

1 Ответ

0 голосов
/ 14 января 2020

Как отметили @Simon и @M. Deinum, NullPointerException, был брошен, потому что экземпляр Editor, созданный Spring, не был инсталлятором, вызывающим метод openNewFile(), скорее JavaFX был тем, который контролировал мой экземпляр. Установка контроллера JavaFX с использованием loader.setController(context.getBean("editor)) вместо настройки его в файле f xml устранила мою проблему. start() метод Main класса теперь выглядит так:

public void start(Stage primaryStage) throws Exception {
    loader.setController(context.getBean("editor"));
    root = loader.load(getClass().getResourceAsStream(rootPath));
    this.primaryStage.setScene(new Scene(root));
    this.primaryStage.show();

}
...