JavaFX + Spring Boot + JPA-NullPointerException

标签 java spring spring-boot javafx

我对被注入(inject)的存储库进行任何操作时都遇到问题。

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException:  java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8413)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:748)
 Caused by:
 java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor21.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
    ... 48 more
 Caused by: java.lang.NullPointerException
    at pl.com.jg.serviceapp.controllers.ReportFrameController.generateButtonClicked(ReportFrameController.java:54)
    ... 58 more

我的ReportFrameController(使用问题存储库):

@Controller
public class ReportFrameController{

    @FXML
    private Button generateButton;

    @FXML
    private Button cancelButton;

    @FXML
    private TextArea textReport;

    @Autowired
    @Qualifier(value = "kr")
    private KeywordRepository keywordRepository;

    @FXML
    public void cancelButtonClicked(ActionEvent event) throws IOException {

        Parent root = FXMLLoader.load(getClass().getResource("/fxml/menuFrame.fxml"));
        Scene scene = new Scene(root);
        Stage stage = (Stage) cancelButton.getScene().getWindow();
        stage.hide();
        stage.setTitle("Logged");
        stage.setScene(scene);
        stage.show();
    }

    @FXML
    public void generateButtonClicked(ActionEvent event) throws NullPointerException{

        String word, checking;
        checking = textReport.getText().toLowerCase();


        for (Keyword i : keywordRepository.findAll()) {  //InteliJ suggest trouble on this line

            word = i.getName();
            System.out.println("Word: " + word);
            System.out.println("Checking: " + checking);

            if (checking.contains(word)) {
                System.out.println("I found the key! " + word);
            } else System.out.println("I didn't found the key! " + word);

        }

        Stage stage = (Stage) generateButton.getScene().getWindow();
        stage.close();
    }
}

在另一个仓库上操作是可以的:

@Controller
public class MainFrameController {

    @FXML
    public Button connectButton;

    @FXML
    private PasswordField passwordBox;

    @FXML
    private TextField usernameBox;

    @FXML
    private Label answerLb;

    @Autowired
    UserController userController;

    @FXML
    void connectClicked(ActionEvent event) throws Exception {
        String login;
        String password;
        String answer;

        login = usernameBox.getText();
        password = MD5(passwordBox.getText());

        answer = userController.auth(login, password);
        answerLb.setText(answer);

        if (answer.equals("ok")) {
            try {
                Parent root = FXMLLoader.load(getClass().getResource("/fxml/menuFrame.fxml"));
                Scene scene = new Scene(root);
                Stage stage = (Stage) connectButton.getScene().getWindow();
                stage.hide();
                stage.setTitle("Logged in as: " + login);
                stage.setScene(scene);
                stage.show();

            } catch (IOException e) {
                System.out.println("Failed to create new Window.");
            }

        }
    }


    public String MD5(String s) throws Exception{

        MessageDigest m=MessageDigest.getInstance("MD5");
        m.update(s.getBytes(),0,s.length());
        String pass = new BigInteger(1,m.digest()).toString(16);
        return(pass);
    }

两个存储库都有合适的模型。数据库中的实体有一些条目。 还需要其他东西吗?

编辑。 添加主类:

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages = {"pl.com.jg.serviceapp.controllers",
    "pl.com.jg.serviceapp.services"})
@EntityScan("pl.com.jg.serviceapp.models")
@EnableJpaRepositories(basePackages = {"pl.com.jg.serviceapp.repositories"})
public class ServiceappApplication extends Application{

private ConfigurableApplicationContext springContext;
private Parent rootNode;

public static void main(final String[] args) {
    Application.launch(args);
}

@Override
public void init() throws Exception {
    springContext = SpringApplication.run(ServiceappApplication.class);
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/mainFrame.fxml"));
    fxmlLoader.setControllerFactory(springContext::getBean);
    rootNode = fxmlLoader.load();
}

@Override
public void start(Stage stage) throws Exception {
    stage.setScene(new Scene(rootNode));
    stage.setTitle("SERVICEAPP");
    stage.show();
}

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


}

编辑:

添加MenuFrameController:

@Controller
public class MenuFrameController {

@FXML
private Button generateReportButton;



@FXML
void generateReportButtonClicked(ActionEvent event) throws Exception {

        try {
            Parent root = FXMLLoader.load(getClass().getResource("/fxml/reportFrame.fxml"));
            Scene scene = new Scene(root);
            Stage stage = (Stage) generateReportButton.getScene().getWindow();
            stage.setTitle("Generate new report");
            stage.setScene(scene);
            stage.show();
        } catch (IOException e) {
            System.out.println("Failed to create Generate Window.");
        }



    }

}

最佳答案

加载 reportFrame.fxml 时,您没有在 FXMLLoader 上设置 Controller 工厂。因此,当 FXMLLoader 需要 ReportFrameController 的实例时,它只是直接实例化一个实例,而不是从 Spring 应用程序上下文中获取一个实例。由于 spring 不管理 Controller ,因此无法向其中注入(inject)任何内容。

只需使用与加载 mainFrame.fxml 相同的模式即可加载 reportFrame.fxml。您可以将 ApplicationContext 本身注入(inject) Controller 中以实现此目的。请注意,这意味着您的 MenuFrameController 也必须由 spring 管理(因此在加载其相应的 FXML 文件等时使用相同的技术)。

另外,顺便说一句,您应该制作所有 Controller 原型(prototype),因为每次加载相同的 FXML 文件时,您都需要一个新的 Controller 实例。

@Controller
@Scope("prototype")
public class MenuFrameController {

@FXML
private Button generateReportButton;

@Autowired
private ApplicationContext springContext ;

@FXML
void generateReportButtonClicked(ActionEvent event) throws Exception {

        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/reportFrame.fxml"));
            fxmlLoader.setControllerFactory(springContext::getBean);
            Parent root = fxmlLoader.load();
            Scene scene = new Scene(root);
            Stage stage = (Stage) generateReportButton.getScene().getWindow();
            stage.setTitle("Generate new report");
            stage.setScene(scene);
            stage.show();
        } catch (IOException e) {
            System.out.println("Failed to create Generate Window.");
        }



    }

}
<小时/>

如果您愿意,可以通过创建一个封装加载功能的类来减少重复代码,并在需要的地方注入(inject)它的实例:

public class SpringFXMLLoader {

    @Autowired
    private ApplicationContext springContext ;

    public Parent load(String resourceName) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource(resourceName));
        loader.setControllerFactory(springContext::getBean);
        return loader.load();
    }
}

那么你的主类就可以做到

@Override
public void init() throws Exception {
    springContext = SpringApplication.run(ServiceappApplication.class);
    rootNode = springContext.getBean(SpringFXMLLoader.class).load("/fxml/mainFrame.fxml");
}

你的MenuFrameController简化(一点点)为

@Controller
@Scope("prototype")
public class MenuFrameController {

@FXML
private Button generateReportButton;

@Autowired
private SpringFXMLLoader fxmlLoader ;

@FXML
void generateReportButtonClicked(ActionEvent event) throws Exception {

        try {
            Parent root = fxmlLoader.load("/fxml/reportFrame.fxml");
            Scene scene = new Scene(root);
            Stage stage = (Stage) generateReportButton.getScene().getWindow();
            stage.setTitle("Generate new report");
            stage.setScene(scene);
            stage.show();
        } catch (IOException e) {
            System.out.println("Failed to create Generate Window.");
        }



    }

}

关于JavaFX + Spring Boot + JPA-NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50455295/

相关文章:

java - 在Java中计算附加值

java - @ContextConfiguration 中配置类的初始化顺序会受到影响吗?

java - Spring Boot 和数据库默认数据与 Mongodb

java - 如何将响应变量建模为来自后端的响应

java - 如何创建替换关键字密码

java - 调用自己的方法时,旧字符串值会留下

java - Java Play 中连续运行的代码!框架

java - 401-从 Spring Boot 应用程序使用 REST API Dynamics CRM 和 Azure AD 进行未经授权的身份验证

java - Spring Boot Redis 配置不起作用

java - 如何使用 spring 集成从 sftp 移动到本地目录时将不同文件保存到不同位置