0

Currently, I have a JavaFX Application running and working perfectly, but now I want to achieve communication via sockets with an external server which can command and demand information about the App.

I save information about the system in an instance of a class called Storage, then I want to receive commands from remote, in another thread running a TCP socket, to change these parameters in storage and then the App thread could update the graphics.

Currently, I am aware that only the App thread can update the graphics on the primary stage, but I am trying to share a reference to the storage unit within the App and the socket thread. This approach seems to be non-possible, or is it?

Could something like this work?


public class Main{
    public static void main(String args[]) {
        Storage storage = new Storage();
        AppView appView = new AppView(storage);

        /* Endpoint for remote communication */
        Communicator communicator = new Communicator(storage);
        communicator.start();
    }
    static class AppView extends Application(){
        
        public AppView(Storage st){
            storage = st;
            launch();
        }

        public void start(Stage primaryStage){
            // scene
        }

        Storage storage;
    }
}

I've tried to run the communication endpoint on a secondary thread and on the primary thread, then moving the App to a secondary thread, but can't get it right.

I found a previous question similar: Make JavaFX Application non static

But the answers are not what i'm looking for.

Thanks for any help.

  • 3
    This won’t work, probably for a number of reasons, but the one that is most obvious to me is that the `Application` class just have a no-arg constructor. What’s wrong with just having a regular `Application` class and instantiating your `Storage` instance (and other required objects) in the `start()` (or `init()`) method? – James_D Dec 03 '22 at 02:48
  • 1
    I don't really understand your question, so cannot precisely answer it. This is an example of a [JavaFX app communicating with a server overs TCP socket](https://stackoverflow.com/questions/70870998/how-to-return-objects-from-inputstream-client-to-a-javafx-controller/70888362#70888362), it initializes the client communication class in the `init` method as suggested by James. Other communication options are websockets with STOMP or HTTP with REST/long polling, which might be preferred if you want to communicate over the public internet or if there are firewalls where only http ports are open. – jewelsea Dec 03 '22 at 06:09
  • @James_D Originally i instanced a Storage instance inside the Application, but in that scenario i don't know how to use this instance for the constructor of my Communicator instance. When i tried to make this Storage instance (inside the Application) non-static and visible outside, i have issues to access it from the main static context. – Killer Potato Dec 03 '22 at 21:52
  • @jewelsea I am comtemplating communication on the public internet and maybe bradcasting on a local network, as you suggested i will consider HTTP. My idea is to run the communication on a secondary thread, but i will look at the reference provided, thanks. – Killer Potato Dec 03 '22 at 21:53
  • In an attempt to clarify; my main issue is how to share an instance of Storage between my main thread (which runs the Application) and a secondary thread which runs the Communicatior instance. I do not really have a clear idea how to address this issue, since previously my Application had every instance necessary inside the start() method. – Killer Potato Dec 03 '22 at 21:59
  • The *only* thing that should be in your `main()`method is a call to `launch()`. Do all the application initialization in your `Application` subclass `init()` and/or `start()` methods. There is no need to share anything back to the main thread: calling `launch()` will block that thread anyway, so it won’t be able to do anything until the GUI exits. – James_D Dec 04 '22 at 15:35
  • If you want your Communicator instance to know about your storage instance, you can pass the storage instance to your Communicator instance in the Communicator constructor. If you then access the Storage instance from another thread, that could cause concurrency issues unless you are careful. One way around that is only access the storage instance from the communicator thread via Platform.runLater wrapping a Runnable or FutureTask, or using a shared BlockingDeque for example passing data between threads. – jewelsea Dec 05 '22 at 20:21

0 Answers0