1

My current project is a JavaFX Application with RMI. Currently I have two three classes, which I'd like to reduce to two, but I am unable to find out how.

The three classes: StartClient.java BannerController.java AEXBanner.java

Codes and the errormessage:

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:497) 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(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767) Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = main at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:236) at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423) at javafx.stage.Stage.(Stage.java:241) at javafx.stage.Stage.(Stage.java:227) at client.BannerController.(BannerController.java:71) at client.BannerController.main(BannerController.java:174) ... 11 more Exception running application client.BannerController D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:1051: The following error occurred while executing this line: D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:805: Java returned: 1 BUILD FAILED (total time: 17 seconds)

Upon starting the program with StartClient (whilst the RMI server is running) everything works fine. But when I directly start the application with the BannerController class, Netbeans gives me the error posted above.

I am 100% sure the RMI server works fine, so no need to worry about that.

The three classes can be found below:

StartClient:

package client;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 *
 * @author Max
 */
public class StartClient extends Application {

    @Override
    public void start(Stage primaryStage) {
        BannerController.main(null);
    }

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

BannerController: package client;

/**
 *
 * @author Max
 */
import shared.IEffectenBeurs;
import shared.IFonds;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.stage.Stage;

public class BannerController extends Application {

    private AEXBanner banner;
    private IEffectenBeurs effectenbeurs;
    private Timer pollingTimer;
    private String bindingName = "Effectenbeurs";
    private Registry registry = null;
    private static boolean locateRegistry = true;

    public BannerController(String ip, int port) {
        banner = new AEXBanner();
        pollingTimer = new Timer();

        System.out.println("Client: IP Address: " + ip);
        System.out.println("Client: Port number " + port);

        if (locateRegistry) {
            // Locate registry at IP address and port number
            registry = locateRegistry(ip, port);

            // Print result locating registry
            if (registry != null) {
                printContentsRegistry();
                System.out.println("Client: Registry located");
            } else {
                System.out.println("Client: Cannot locate registry");
                System.out.println("Client: Registry is null pointer");
            }
            if (registry != null) {
                effectenbeurs = bindEffectenbeursUsingRegistry();
            }
        } else {
            // Bind fonds using Naming
            effectenbeurs = bindEffectenbeursUsingNaming(ip, port);
        }
        if (effectenbeurs != null) {
            System.out.println("Client: Effectenbeurs bound");
        } else {
            System.out.println("Client: Effectenbeurs is null pointer");
        }
        banner.start(new Stage());
        pollingTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    StringBuilder sb = new StringBuilder();
                    for (IFonds f : effectenbeurs.getKoersen()) {
                        sb.append(f.toString() + " ");
                    }
                    System.out.println(sb.toString());
                    banner.setKoersen(sb.toString());
                } catch (RemoteException ex) {
                    Logger.getLogger(BannerController.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        }, 0, 2000);

    }

    // Print contents of registry
    private void printContentsRegistry() {
        try {
            String[] listOfNames = registry.list();
            System.out.println("Client: list of names bound in registry:");
            if (listOfNames.length != 0) {
                for (String s : registry.list()) {
                    System.out.println(s);
                }
            } else {
                System.out.println("Client: list of names bound in registry is empty");
            }
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot show list of names bound in registry");
            System.out.println("Client: RemoteException: " + ex.getMessage());
        }
    }

    private IEffectenBeurs bindEffectenbeursUsingRegistry() {
        IEffectenBeurs effectenbeurs1 = null;
        try {
            Object object = registry.lookup(bindingName);
            effectenbeurs1 = (IEffectenBeurs) registry.lookup(bindingName);
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: RemoteException: " + ex.getMessage());
            effectenbeurs1 = null;
        } catch (NotBoundException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: NotBoundException: " + ex.getMessage());
            effectenbeurs1 = null;
        }
        return effectenbeurs1;
    }

    private Registry locateRegistry(String ipAddress, int portNumber) {
        Registry registry = null;
        try {
            registry = LocateRegistry.getRegistry(ipAddress, portNumber);
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot locate registry");
            System.out.println("Client: RemoteException: " + ex.getMessage());
            registry = null;
        }
        return registry;
    }

    private IEffectenBeurs bindEffectenbeursUsingNaming(String ipAddress, int portNumber) {
        IEffectenBeurs Effectenbeurs = null;
        try {
            Effectenbeurs = (IEffectenBeurs) Naming.lookup("rmi://" + ipAddress + ":" + portNumber + "/" + bindingName);
        } catch (MalformedURLException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: MalformedURLException: " + ex.getMessage());
            Effectenbeurs = null;
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: RemoteException: " + ex.getMessage());
            Effectenbeurs = null;
        } catch (NotBoundException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: NotBoundException: " + ex.getMessage());
            Effectenbeurs = null;
        }
        return Effectenbeurs;
    }

    public static void main(String[] args) {
        if (locateRegistry) {
            System.out.println("CLIENT USING LOCATE REGISTRY");
        } else {
            System.out.println("CLIENT USING NAMING");
        }

//        // Get ip address of server
        Scanner input = new Scanner(System.in);
        System.out.print("Client: Enter IP address of server: ");
        String ipAddress = input.nextLine();

        // Get port number
        System.out.print("Client: Enter port number: ");
        int portNumber = input.nextInt();
        // Create client
        BannerController client = new BannerController(ipAddress, portNumber);
    }

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

    }
}

I highly doubt the third class has anything to do with this problem, but just in case: I included it.

AEXBanner: package client;

import java.rmi.RemoteException;
import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class AEXBanner extends Application {

    public static final int WIDTH = 1000;
    public static final int HEIGHT = 100;
    public static final int NANO_TICKS = 20000000;
    // FRAME_RATE = 1000000000/NANO_TICKS = 50;

    private Text text;
    private double textLength;
    private double textPosition;
    private BannerController controller;

    private AnimationTimer animationTimer;
    private Timeline timeline;
    private int TIMERTICK = 200;
    private int frame = 0;
    private String koersen;

    public void setController(BannerController banner) {
        //controller = banner(this);
    }
    @Override
    public void start(Stage primaryStage) {

        Font font = new Font("Arial", HEIGHT);
        text = new Text();
        //controller = new BannerController(this);

        text.setFont(font);
        text.setFill(Color.BLACK);

        Pane root = new Pane();
        root.getChildren().add(text);
        Scene scene = new Scene(root, WIDTH, HEIGHT);

        primaryStage.setTitle("AEX banner");
        primaryStage.setScene(scene);
        primaryStage.show();
        primaryStage.toFront();

        timeline = new Timeline();
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.setAutoReverse(false);

        // Start animation: text moves from right to left
        animationTimer = new AnimationTimer() {
            private long prevUpdate;

            @Override
            public void handle(long now) {
                long lag = now - prevUpdate;
                if (lag >= NANO_TICKS) {
                    // calculate new location of text
                    // TODO
                    if (textPosition < 0 - textLength) {
                        textPosition = WIDTH;
                    }
                    textPosition -= 5;

                    text.relocate(textPosition, 0);
                    prevUpdate = now;
                }
            }

            @Override
            public void start() {
                prevUpdate = System.nanoTime();
                textPosition = WIDTH;
                text.relocate(textPosition, 0);
                //setKoersen("Nothing to display");
                super.start();
            }
        };
        animationTimer.start();
    }

    public void setKoersen(String koersen) {

        text.setText(koersen);

        textLength = text.getLayoutBounds().getWidth();
    }
}

So to conclude with my question (just to make it clear): when the RMI server is running, I need to start this project with the StartClient. The StartClient launches the BannerController. I'd like to be able to start the program directly with the BannerController class.

Any tips or possible solutions would be greatly appreciated!

EDIT: After the changeg suggested by Lasagna, this error comes up directly when I start the BannerController:

Exception in Application constructor
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:497)
    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(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class client.BannerController
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoSuchMethodException: client.BannerController.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:818)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    ... 1 more
Exception running application client.BannerController
D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:1051: The following error occurred while executing this line:
D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:805: Java returned: 1
BUILD FAILED (total time: 0 seconds)
Joris Borza
  • 51
  • 1
  • 9
  • Can you please post some code in here, as well as errors, for those of us who do not want to click your link. Thanks. – XaolingBao Apr 11 '16 at 20:27
  • I fail to post the code in the correct manner (four spaces are not doing it somehow). I also can not post more than 2 links because I do not have 1500 reputation points. I will try again right now, lets hope it works this time. – Joris Borza Apr 11 '16 at 20:38
  • You can format your code by selecting the code and doing "ctrl + k." Next to each post is a "Help" link, if you click that it will add some examples, but if you click "Learn more..." it will send you here to the formatting guide :). http://stackoverflow.com/editing-help#comment-formatting – XaolingBao Apr 11 '16 at 20:41

1 Answers1

1

Lets take a look at your error.

sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767) Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = main

This is saying that you have no "FX Application Thread" and your current Thread is "main."

This is because you are trying to work with the main method as your "main method" but in FX, it doesn't work like that (funky huh? :) ). main is just a method to launch the FX Application itself, which is why you get this error.


The start method of your Application is where things happen.

In your first class "StartClient" you use the main of "BannerController" and then in your main you "launch(args)" which is how you launch your FX Application.

In your Banner Application, you have a main class with a bunch of stuff, but no launch(args)

I also am not sure why "start" is throwing an exception with no code inside of it.


So what you need to do is

  1. Remove Application from all classes except the main class.
  2. Make sure the main class has "launch(args)" within the main method.
  3. Make sure the main class overrides the "start" method, and that you "launch" your code from there.

so take this code

public static void main(String[] args) {
        if (locateRegistry) {
            System.out.println("CLIENT USING LOCATE REGISTRY");
        } else {
            System.out.println("CLIENT USING NAMING");
        }

//        // Get ip address of server
        Scanner input = new Scanner(System.in);
        System.out.print("Client: Enter IP address of server: ");
        String ipAddress = input.nextLine();

        // Get port number
        System.out.print("Client: Enter port number: ");
        int portNumber = input.nextInt();
        // Create client
        BannerController client = new BannerController(ipAddress, portNumber);
    }

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

    }

and change it to

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

    @Override
    public void start(Stage primaryStage) throws Exception {
 if (locateRegistry) {
            System.out.println("CLIENT USING LOCATE REGISTRY");
        } else {
            System.out.println("CLIENT USING NAMING");
        }

//        // Get ip address of server
        Scanner input = new Scanner(System.in);
        System.out.print("Client: Enter IP address of server: ");
        String ipAddress = input.nextLine();

        // Get port number
        System.out.print("Client: Enter port number: ");
        int portNumber = input.nextInt();
        // Create client
        BannerController client = new BannerController(ipAddress, portNumber);
    }
XaolingBao
  • 1,034
  • 1
  • 18
  • 34
  • The error I get when I change this is even weirder:
    – Joris Borza Apr 11 '16 at 21:39
  • Hmm... Post it up! You can try here, or make an edit in your original post. If you do ------------------------- it will make a new line and you can split things easier into sections. – XaolingBao Apr 11 '16 at 21:40
  • I seem to not be able to post the whole message, maybe this is enough to help you out:
    Exception in Application constructor java.lang.reflect.InvocationTargetException

    And a bit further down:
    Caused by: java.lang.RuntimeException: Unable to construct Application instance: class client.BannerController at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    – Joris Borza Apr 11 '16 at 21:41
  • Nope, need the whole thing! Try editing your original message, and using the code formatting of course:). Also remmeber you have a bunch of stuff in the "start' method of your AEXBanner class, and need to make a new method, as well as call that method... I'm not really sure how this is running though. – XaolingBao Apr 11 '16 at 21:41
  • Well, for what it's worth you are calling BannerController client = new BannerController(ipAddress, portNumber); from within it's own class, why not create a method that does what you need to do with this, instead of a constructor? As for the error... There seems to be just a few things you need to clean up in your code. IT seems you are a Swing user (coming from Scanner), so you might want to read up a little bit more on FX structuring and such. – XaolingBao Apr 11 '16 at 21:57
  • I changed the constructor to one without parameters and I made the ip and port variable global fields. This was the solution to the problem. Thanks a lot for your help! – Joris Borza Apr 12 '16 at 11:43