Search code examples
javajavafxinvocationtargetexception

JavaFx invocation target exception when I try to initialize class


Im really new to javafx and i guess im missing some of the logic here. My class BankApplication contains instance variables Customer and SavingsAccount. I want to initialize those so my application will run, with the name of customer and the ID on the top, as well as the balance. So I want to create an instance of BankApplication , to give the app this information. It gives me an error.

This is just a part of the code..

public class BankApplication extends Application implements 
EventHandler<ActionEvent>{

public static void main(String[] args) {

    Customer Amanda = new Customer("Amanda" , 1009);
    SavingsAccount AmandaBANK = new SavingsAccount(Amanda , 150);
    BankApplication app1 = new BankApplication(Amanda,AmandaBANK);

    launch(args);

}

protected Customer customer;
protected SavingsAccount bankAccount;

public BankApplication(Customer customer, SavingsAccount bankAccount) {
    this.customer = customer;
    this.bankAccount = bankAccount;
}

private Button executeButton = new Button("Execute");
Label customerNameLabel = new Label("Customer name: " + customer.getName());
Label customerIDLabel = new Label("Customer ID: "+ customer.getID());

Label balanceLabel = new Label("Current balance: $" + 
bankAccount.getBalance() + ".");
TextField depositTextField = new TextField("Amt to deposit");
TextField withdrawTextField = new TextField("Amt to withdraw");



@Override
public void start(Stage primaryStage) throws Exception {

    FlowPane root = new FlowPane();
    Scene scene = new Scene(root,400,300);
    primaryStage.setScene(scene);
    primaryStage.setTitle("Bank application");

    executeButton.setOnAction(this);

    HBox middle = new HBox(depositTextField,withdrawTextField);
    middle.setSpacing(8);
    middle.setPadding(new Insets(8));

    VBox top = new VBox(customerNameLabel,customerIDLabel);
    VBox bottom = new VBox(executeButton,balanceLabel);
    top.setSpacing(8);
    bottom.setSpacing(8);
    top.setPadding(new Insets(8));
    bottom.setPadding(new Insets(8));

    root.getChildren().add(top);
    root.getChildren().add(middle);
    root.getChildren().add(bottom);


    primaryStage.show();


}

@Override
public void handle(ActionEvent event) {
    if (event.getSource() == executeButton) {

        String depositAmount = depositTextField.getText();
        String withdrawAmount = withdrawTextField.getText();

        if (isDouble(depositAmount) == true) {

            double old_balance = bankAccount.getBalance();

            bankAccount.deposit(Double.parseDouble(depositAmount));

            double new_balance = bankAccount.getBalance();

            if (new_balance != old_balance) { 
                updateBalanceLabel();
                depositTextField.clear();
                depositTextField.setText("Amt to deposit"); 
            }

            else if (new_balance == old_balance) { 
                depositTextField.clear();
                depositTextField.setText("Amt to deposit"); 
            }
        }

And the javafx error..

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)


Caused by: java.lang.NullPointerException
at BankAccount.BankApplication.<init>(BankApplication.java:37)
at BankAccount.BankApplication.main(BankApplication.java:22)
... 11 more
Exception running application BankAccount.BankApplication

Solution

  • You initialize several instance variables (customerIDLabel, customerIDLabel) based on customer and account that are passed to constructor. The problem is, java calls your constructor after the field initialization block. This is easy to fix: just move field initialization code into your constructor:

    protected Customer customer;
    protected SavingsAccount bankAccount;
    private Button executeButton = new Button("Execute");
    private Label customerIDLabel;
    private Label balanceLabel;
    private TextField depositTextField;
    private TextField withdrawTextField;
    private Label customerNameLabel;
    
    public BankApplication(Customer customer, SavingsAccount bankAccount) {
        this.customer = customer;
        this.bankAccount = bankAccount;
        customerNameLabel = new Label("Customer name: " + customer.getName());
        customerIDLabel = new Label("Customer ID: " + customer.getID());
    
        balanceLabel = new Label("Current balance: $" +
                bankAccount.getBalance() + ".");
        depositTextField = new TextField("Amt to deposit");
        withdrawTextField = new TextField("Amt to withdraw");
    }
    

    This would fix your NullPointerException, but did you notice that app1 is ignored? In JavaFX, you are not supposed to create instances of your Application. Instead, you have to let JavaFx runtime to do it for you. Here it is generally considered acceptable to use statics.

    public class BankApplication extends Application implements
        EventHandler<ActionEvent> {
    private static Customer customer;
    private static SavingsAccount bankAccount;
    
    private Button executeButton = new Button("Execute");
    private Label customerIDLabel;
    private Label balanceLabel;
    private TextField depositTextField;
    private TextField withdrawTextField;
    private Label customerNameLabel;
    
    public static void main(String[] args) {
        customer = new Customer("Amanda", 1009);
        bankAccount = new SavingsAccount("Amanda", 150);
    
        Application.launch(args);
    
    }
    
    public BankApplication() {
        customerNameLabel = new Label("Customer name: " + customer.getName());
        customerIDLabel = new Label("Customer ID: " + customer.getID());
    
        balanceLabel = new Label("Current balance: $" +
                bankAccount.getBalance() + ".");
        depositTextField = new TextField("Amt to deposit");
        withdrawTextField = new TextField("Amt to withdraw");
    }
    
    
    @Override
    public void start(Stage primaryStage) throws Exception {
    
        FlowPane root = new FlowPane();
        Scene scene = new Scene(root, 400, 300);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Bank application");
    
        executeButton.setOnAction(this);
    
        HBox middle = new HBox(depositTextField, withdrawTextField);
        middle.setSpacing(8);
        middle.setPadding(new Insets(8));
    
        VBox top = new VBox(customerNameLabel, customerIDLabel);
        VBox bottom = new VBox(executeButton, balanceLabel);
        top.setSpacing(8);
        bottom.setSpacing(8);
        top.setPadding(new Insets(8));
        bottom.setPadding(new Insets(8));
    
        root.getChildren().add(top);
        root.getChildren().add(middle);
        root.getChildren().add(bottom);
    
    
        primaryStage.show();
    
    
    }
    
    @Override
    public void handle(ActionEvent event) {
        if (event.getSource() == executeButton) {
    
            String depositAmount = depositTextField.getText();
            String withdrawAmount = withdrawTextField.getText();
    
            if (isDouble(depositAmount) == true) {
    
                double old_balance = bankAccount.getBalance();
    
                bankAccount.deposit(Double.parseDouble(depositAmount));
    
                double new_balance = bankAccount.getBalance();
    
                if (new_balance != old_balance) {
                    updateBalanceLabel();
                    depositTextField.clear();
                    depositTextField.setText("Amt to deposit");
                } else if (new_balance == old_balance) {
                    depositTextField.clear();
                    depositTextField.setText("Amt to deposit");
                }
            }
        }
    }//...