使用javafx的spring依赖注入会产生nullpointerexceptions

oogrdqng  于 2021-07-14  发布在  Java
关注(0)|答案(2)|浏览(799)

我想混合javafx和spring数据。我找到了关于这个问题的视频https://www.youtube.com/watch?v=u0def-qn-90&t=3s 我在代码中实现了它。结果,我的ui正常工作,但我无法将依赖项注入taskrepository。我一直在尝试用difrent方法注入任何东西,但总是得到相同的错误,即我的依赖项为空。我做错什么了?
添加窗口.fxml

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>

<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pl.projektyjava.listToDoJavaFX.fxmlcontrollers.AddingWindowController">
   <children>
      <VBox prefHeight="400.0" prefWidth="473.0" HBox.hgrow="ALWAYS">
         <children>
            <Label alignment="TOP_CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="Tytuł" textAlignment="CENTER" />
            <TextField fx:id="title" VBox.vgrow="ALWAYS" />
            <Label alignment="TOP_CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="Opis" textAlignment="CENTER" />
            <TextArea fx:id="description" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
            <HBox maxHeight="-Infinity" VBox.vgrow="ALWAYS">
               <children>
                  <Button fx:id="listOfQuest" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Lista Zadań" HBox.hgrow="ALWAYS" />
                  <Button fx:id="addQuest" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Dodaj zadanie" HBox.hgrow="ALWAYS" />
               </children>
            </HBox>
         </children>
      </VBox>
      <Slider fx:id="priority" blockIncrement="1.0" majorTickUnit="1.0" max="5.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minorTickCount="0" orientation="VERTICAL" showTickLabels="true" showTickMarks="true" snapToTicks="true" HBox.hgrow="ALWAYS" />
   </children>
</HBox>

pl.projektyjava.listtodojavafx.appinitialization。初始化

package pl.projektyjava.listToDoJavaFX.appinitialization;

import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class Initialization implements ApplicationListener<StarterClass.StageReadyEvent>{

    @Override
    public void onApplicationEvent(StarterClass.StageReadyEvent event) {
        Stage stage = event.getStage();
        HBox mainPane= null;
        try {
            mainPane = FXMLLoader.load(getClass().getResource("/addingWindow.fxml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        Scene scene=new Scene(mainPane);
        stage.setScene(scene);
        stage.show();
    }
}

pl.projektyjava.listtodojavafx.appinitialization.listtodojavafx应用程序

package pl.projektyjava.listToDoJavaFX.appinitialization;

import javafx.application.Application;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ListToDoJavaFxApplication  {

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

    }
}

pl.projektyjava.listtodojavafx.appinitialization.starterclass类

package pl.projektyjava.listToDoJavaFX.appinitialization;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class StarterClass extends Application {

    private ConfigurableApplicationContext applicationContext;

    @Override
    public void init()  {

        applicationContext=new SpringApplicationBuilder(ListToDoJavaFxApplication.class).run();
    }

    @Override
    public void start(Stage stage)  {

        applicationContext.publishEvent(new StageReadyEvent(stage));

    }

    @Override
    public void stop()  {
        applicationContext.close();
        Platform.exit();
    }

    static class StageReadyEvent extends ApplicationEvent {
        public StageReadyEvent (Stage stage){
            super(stage);
        }
        public Stage getStage(){
           return ((Stage) getSource());
        }
    }
}

pl.projektyjava.listtodojavafx.body.task文件

package pl.projektyjava.listToDoJavaFX.body;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Task {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;
    private String description;
    private double priority;

    public Task(String title, String description, double priority) {
        this.title = title;
        this.description = description;
        this.priority = priority;
    }

    public Task() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public double getPriority() {
        return priority;
    }

    public void setPriority(double priority) {
        this.priority = priority;
    }
}

pl.projektyjava.listtodojavafx.body.taskrepository任务库

package pl.projektyjava.listToDoJavaFX.body;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface TaskRepository extends CrudRepository<Task, Long> {
}

pl.projektyjava.listtodojavafx.fxmlcontrollers.addingwindowcontroller

package pl.projektyjava.listToDoJavaFX.fxmlcontrollers;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import pl.projektyjava.listToDoJavaFX.body.Task;
import pl.projektyjava.listToDoJavaFX.body.TaskRepository;

@Controller
public class AddingWindowController {

    @Autowired
    TaskRepository taskRepository;

    @FXML
    private TextField title;

    @FXML
    private TextArea description;

    @FXML
    private Button listOfQuest;

    @FXML
    private Button addQuest;

    @FXML
    private Slider priority;

    public void initialize() {
        addQuest.setOnAction(event -> {
            String titleText = title.getText();
            String descriptionText = description.getText();
            double priorityVal = priority.getValue();

            Task task = new Task(titleText, descriptionText, priorityVal);
            taskRepository.save(task);

        });
    }

}

和错误:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "pl.projektyjava.listToDoJavaFX.body.TaskRepository.save(Object)" because "this.taskRepository" is null
    at pl.projektyjava.listToDoJavaFX.fxmlcontrollers.AddingWindowController.lambda$initialize$0(AddingWindowController.java:41)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
    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:8792)
    at javafx.scene.control.Button.fire(Button.java:203)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:208)
    at com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
    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:3861)
    at javafx.scene.Scene.processMouseEvent(Scene.java:1854)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2587)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:409)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:299)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:447)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:413)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:446)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:556)
    at com.sun.glass.ui.View.notifyMouse(View.java:942)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)

添加后 ControlerFactoryFXMLLoader 我有这个:

javafx.fxml.LoadException: 
/B:/Projekty/1%20PROJEKT/listToDo-JavaFX/listToDo-JavaFX/target/classes/addingWindow.fxml:11

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2707)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2685)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2517)
    at pl.projektyjava.listToDoJavaFX.appinitialization.Initialization.onApplicationEvent(Initialization.java:28)
    at pl.projektyjava.listToDoJavaFX.appinitialization.Initialization.onApplicationEvent(Initialization.java:14)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
    at pl.projektyjava.listToDoJavaFX.appinitialization.StarterClass.start(StarterClass.java:26)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:849)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:474)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:447)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:446)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:831)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'pl.projektyjava.listToDoJavaFX.fxmlcontrollers.AddingWindowController' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:940)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:982)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:229)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:754)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2808)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2634)
    ... 19 more
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
2021-04-23 19:47:00.791  INFO 12928 --- [lication Thread] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2021-04-23 19:47:00.794  INFO 12928 --- [lication Thread] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2021-04-23 19:47:00.800  INFO 12928 --- [lication Thread] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:903)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
    at java.base/java.lang.Thread.run(Thread.java:831)
Caused by: java.lang.NullPointerException: Root cannot be null
    at javafx.scene.Scene.<init>(Scene.java:345)
    at javafx.scene.Scene.<init>(Scene.java:207)
    at pl.projektyjava.listToDoJavaFX.appinitialization.Initialization.onApplicationEvent(Initialization.java:32)
    at pl.projektyjava.listToDoJavaFX.appinitialization.Initialization.onApplicationEvent(Initialization.java:14)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
    at pl.projektyjava.listToDoJavaFX.appinitialization.StarterClass.start(StarterClass.java:26)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:849)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:474)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:447)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:446)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    ... 1 more

Process finished with exit code 1
7nbnzgx9

7nbnzgx91#

默认情况下 FXMLLoader 将通过调用无参数构造函数来创建控制器示例。因此 AddingWindowController 创建的示例不受spring管理,spring无法注入 @Autowired 它的依赖性(基本上,Spring ApplicationContext 不知道 AddingWindowController 示例已存在。)
你可以提供 ControllerFactoryFXMLLoader 它要求由spring应用程序上下文创建控制器:

@Component
public class Initialization implements ApplicationListener<StarterClass.StageReadyEvent>{

    @Autowired
    private ApplicationContext applicationContext ;

    @Override
    public void onApplicationEvent(StarterClass.StageReadyEvent event) {
        Stage stage = event.getStage();
        HBox mainPane= null;
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/addingWindow.fxml"));
            fxmlLoader.setControllerFactory(applicationContext::getBean);
            mainPane = fxmlLoader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Scene scene=new Scene(mainPane);
        stage.setScene(scene);
        stage.show();
    }
}

还要注意,每次加载fxml时都应该创建一个新的控制器示例,因此javafx控制器应该具有prototype作用域。这可能不太重要,但是 @Controller spring中的注解实际上是针对web应用程序中的mvc控制器的,因此 @Component 刻板印象在这里更合适:

@Component
@Scope("prototype")
public class AddingWindowController {

    // ...

}
vulvrdjw

vulvrdjw2#

默认情况下,@springbootapplication在它自己的文件夹和下面进行componentscan。所以只需将您的listtodojavafx应用程序的一个文件夹放到pl.projektyjava.listtodojavafx中
或者只需添加 @ComponentScan(“pl.projektyjava.listToDoJavaFX”) 就在@springbootplication上面,它明确定义了组件扫描。
通常情况下,每当自动布线在启动时无声地发生故障而没有beancreationexception时,这表明组件扫描没有找到ur组件

相关问题