0

i hope you are doing well in this difficult period,

i'm developping a JavaFx client for my rest web services and while running my app there is a weird exception that point my LoginPresenter class, i'hv checked all the source path but nothing to signal, so i came here to ask for some help ,here is the error:

    Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.NullPointerException: inputStream is null.
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2480)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2450)
    at fr.orleans.univ.projet/fr.orleans.univ.projet.view.LoginPresenter.getInstance(LoginPresenter.java:39)
    at fr.orleans.univ.projet/fr.orleans.univ.projet.PrimaryController.showLogin(PrimaryController.java:22)
    at fr.orleans.univ.projet/fr.orleans.univ.projet.App.start(App.java:30)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
    ... 1 more
Exception running application fr.orleans.univ.projet.App

Here is my code:

the controller PrimaryController.class

public class PrimaryController {

    private Stage stage;
    private Service service;

    public PrimaryController(Stage stage, Service service) {
        this.stage = stage;
        this.service = service;
    }

    public void showLogin(){
        LoginPresenter login = LoginPresenter.getInstance(this);
        Scene scene = new Scene(login.getRoot());
        stage.setScene(scene);
        stage.show();
    }

    public void tenteLogin(String username, String password) {
        service.login(username,password);
        if(service.isAuthenticated()){
            System.out.println("Connecté!");
        }
    }
}

This is my LoginPresenter.class

public class LoginPresenter {

    private PrimaryController primaryController;

    public void setPrimaryController(PrimaryController primaryController){
        this.primaryController=primaryController;
    }

    @FXML
    private TextField username;
    @FXML
    private PasswordField password;
    @FXML
    private Parent root;

    public Parent getRoot(){
        return root;
    }

    public void login(ActionEvent actionEvent)  {
        primaryController.tenteLogin(username.getText(),password.getText());
    }

    public  static LoginPresenter getInstance(PrimaryController primaryController){
        FXMLLoader loader = new FXMLLoader();
        try {
            Parent root = loader.load(LoginPresenter.class.getResourceAsStream("login.fxml"));
        } catch (IOException e){
            e.printStackTrace();
        }
        LoginPresenter instance = loader.getController();
        instance.setPrimaryController(primaryController);

        return instance;
    }
}

this is my App.class

public class App extends Application {

   // private static Scene scene;


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


    @Override
    public void start(Stage stage) {
        Service service = new ServiceProxy();
        PrimaryController primaryController = new PrimaryController(stage,service);
        primaryController.showLogin();
    }
}

and finnaly this is my login.fxml

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

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<BorderPane fx:id="root" prefHeight="200.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.orleans.univ.projet.view.LoginPresenter">
   <top>
      <Label text="Login" BorderPane.alignment="CENTER">
         <font>
            <Font size="24.0" />
         </font>
      </Label>
   </top>
   <center>
      <GridPane BorderPane.alignment="CENTER">
         <columnConstraints>
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="94.0" minWidth="10.0" prefWidth="72.0" />
            <ColumnConstraints hgrow="SOMETIMES" maxWidth="158.0" minWidth="10.0" prefWidth="128.0" />
         </columnConstraints>
         <rowConstraints>
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
         </rowConstraints>
         <children>
            <Label focusTraversable="false" text="Username" />
            <Label focusTraversable="false" text="Password" GridPane.rowIndex="1" />
            <TextField fx:id="username" GridPane.columnIndex="1" />
            <PasswordField fx:id="password" GridPane.columnIndex="1" GridPane.rowIndex="1" />
         </children>
      </GridPane>
   </center>
   <bottom>
      <Button defaultButton="true" mnemonicParsing="false" onAction="#login" text="Login" BorderPane.alignment="CENTER">
         <opaqueInsets>
            <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
         </opaqueInsets></Button>
   </bottom>
</BorderPane>
James_D
  • 201,275
  • 16
  • 291
  • 322
Fraxn
  • 23
  • 8
  • 1
    The exception is raised simply because the path to the FXML is wrong. – James_D Apr 18 '20 at 14:41
  • i don't understand why it is wrong, my fxml file is here "src/main/java/ressources/login.fxml" – Fraxn Apr 18 '20 at 14:46
  • How are you running it? Since it doesn't appear to be in a package folder then you'll need to specify the absolute location. ie "/login.fxml" then you need to make sure your ressources folder is included either with your compiled classes, or is on your classpath. You ide should help you with that. – matt Apr 18 '20 at 14:49
  • 1
    Is `LoginPresenter` in a package? `getClass().getResourceAsStream("login.fxml")` will look for `login.fxml` in the same package. The important thing is not where everything is in the `src` layout, but in the actual build. – James_D Apr 18 '20 at 14:49
  • Slightly off-topic: I don't recommend using the `load(InputStream)` method (unless you're doing something really weird, like loading the FXML from a server, or generating it on the fly). Use `load(URL)` instead: `getClass().getResource("path/to/file.fxml")`. This won't solve this problem, but it might avoid others. – James_D Apr 18 '20 at 14:51
  • my LoginPresenter is in a package yes, i did a Rebuild to my Project and the problem is always here – Fraxn Apr 18 '20 at 15:03
  • Actually, I can see that `LoginPresenter` is in `fr.orleans.univ.projet.view`, while according to your comment, `login.fxml` is in the default package. So, either do as @matt suggests and use the absolute path: `getClass().getResourceAsStream("/login.fxml")`, or (better, imo) place `login.fxml` in the same package, by putting it in `src/main/java/resources/fr/orleans/univ/projet/view`. – James_D Apr 18 '20 at 15:05
  • As @matt has already stated, just place a '/' in front of your file name. In Eclipse the resources folder would have to be marked as a source folder. If your project is a Maven or Gradle project, the Eclipse Maven/Gradle plugin should have taken care of that automatically, so that you don't have to care. – mipa Apr 18 '20 at 15:05

1 Answers1

2

Your LoginPresenter class is (according to the stack trace) in the package fr.orleans.univ.projet.view.

Using LoginPresenter.class.getResourceAsStream("login.fxml") will look for the resource login.fxml in the same package that LoginPresenter is located in. According to your comment, you placed login.fxml in the source folder src/main/java/resources (I assume "ressources" is a typo), which (with standard configuration in most IDEs or build tools) will place it in the default package in the build.

You can fix this either

  1. By providing the absolute path to the FXML file. Since you have this in the default package, this means using

    LoginPresenter.class.getResourceAsStream("/login.fxml")
    

    (note the leading /)

  2. or by placing login.fxml in the same package, which you would do by putting it in the source folder src/main/java/resources/fr/orleans/univ/projet/view.

Generally, I think the latter solution is better.

You also need to ensure the FXML file is deployed during the build; if you're using a build tool such as Maven or Gradle this should happen by default; if you are using a vanilla build from your IDE, you may need to configure it to ensure this happens.

If you need further troubleshooting, you should check the layout of the buid folder (not the source folder). Depending on your build tool or IDE, this can be one of build,bin, target, target/classes, etc. Look in the build folder and check the relationship between LoginPresenter.class and login.fxml.

One slightly off-topic point; I strongly recommend using a resource URL to load the FXML, rather than a stream; i.e. use

LoginPresenter.class.getResource(...)

instead of

LoginPresenter.class.getResourceAsStream(...)

The reason is that the stream version of the load method fails to set the FXMLLoader's location property (because there's no location specified); consequently, for example, location resolution will not work in the FXML file.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • I'm using intellIj, so when i move the login.fxml to the view package, the method getRasourceAsStream() update the location automatically. and still not working when i run, if i use getClass(), this will create another problem because my class is static and use it in my controller to getInstance(this) – Fraxn Apr 18 '20 at 15:20
  • Yes, there's no need to use `getClass()`; I updated that. What do you mean by "the method `getResourceAsStream()` update the location automatically? What did it update it to? – James_D Apr 18 '20 at 15:22
  • @Fraxn Also check the build folder, as I describe in the update to the answer. – James_D Apr 18 '20 at 15:24
  • i just tried getResource("login.fxml") not working too :/, i meant that wherever when i move my login.fxml file the value in getResourcesAstream("path") get updated automatically by intellij – Fraxn Apr 18 '20 at 15:27
  • @Fraxn Updated to what? Did you check the build folder and make sure the FXML file is there? – James_D Apr 18 '20 at 15:28
  • it update it to the new location (location that where i put my file) – Fraxn Apr 18 '20 at 15:37
  • @Fraxn It shouldn't change it; if you move it to that folder and the build is configured correctly, then just `login.fxml` (without the leading `/`) is the correct path. Suggests maybe that something's misconfigured, but I don't use IntelliJ. – James_D Apr 18 '20 at 15:42
  • Thank you for your help i appreciate it !! – Fraxn Apr 18 '20 at 15:44