Search code examples
javajavafxserverclient

Java server stop on button click with Javafx


I tried to make a interface for stopping on button click. When i run the server in main i receive: Server-ul a pornit... but without any interface. Should I implement the interface for stopping the server in the Client class? My server:

public class Server extends Application
{

    private final String _ip = "127.0.0.1";
    private final int _port = 9001;
    private ServerSocket _listener;
    private Socket _socket;
    private ObjectInputStream _input;

    Stage window;   
    Button button;

    public Server()
    {
        System.out.println("Server-ul a pornit...");

        try
        {
            _listener = new ServerSocket(_port);
            _socket = _listener.accept();
            _input = new ObjectInputStream(_socket.getInputStream());
        }
        catch (IOException ex)
        {
            System.out.println(ex.getMessage());
        }
    }

public void start()
    { ............}

My methods in Server class for JAVAfx interface:

 @Override
    public void start(Stage primaryStrage) {
        window=primaryStrage;
        window.setTitle("Close the server");
        button=new Button("Stop");
        button.setOnAction(e -> closeProgram());
        StackPane layoutPane=new StackPane();

        layoutPane.getChildren().add(button);
        Scene scene=new Scene(layoutPane,300,250);
        window.setScene(scene);
        window.show();


    }   

    private void closeProgram() {
        System.exit(0);
    }

Main program:

 public static void main(String[] args)
    {   
        Server s = new Server();
        s.start();


    }

Solution

  • You have to first close the Server Socket by adding the stop method in the server class:

    public void stopServer(){
         _listener.close();  
    }
    

    I am very confused as to why your server class extends Application. The only thing that should be extending application is the Class that runs the GUI. Furthermore you override the start method. So if both start methods are within the same class the override start method is going to override the existing one, hence your server is not going to start. You could either refactor the server class out of the GUI or leave it as is. If you choose the latter, you are going to have to rename the start method of the server to serverStart().

    Instead of initializing the server in the main you initialize it in the start method method of your GUI:

        @Override
        public void start(Stage primaryStrage) {
            Server s = new Server();
            s.serverStart();
            window=primaryStrage;
            window.setTitle("Close the server");
            button=new Button("Stop");
            StackPane layoutPane=new StackPane();
    
            layoutPane.getChildren().add(button);
            Scene scene=new Scene(layoutPane,300,250);
            button.setOnAction(e -> {
                 s.serverStop();
                Stage stage = scene.getWindow(); // if you also want to exit the application
                stage.close(); // otherwise remove it
               });
            window.setScene(scene);
            window.show();
    
        }
    

    Now your whole Server class should look like this:

    public class ServerTest extends Application {
            Stage window;   
            Button button;
    
        public class Server{
            private final String _ip = "127.0.0.1";
            private final int _port = 9001;
            private ServerSocket _listener;
            private Socket _socket;
            private ObjectInputStream _input;
    
            public Server(){
                System.out.println("Server-ul a pornit...");
    
                try
                {
                    _listener = new ServerSocket(_port);
                    _socket = _listener.accept();
                    _input = new ObjectInputStream(_socket.getInputStream());
                }
                catch (IOException ex)
                {
                    System.out.println(ex.getMessage());
                }
            }
    
           public void serverStart(){
            //DO server start stuff
            }
           public void stopServer(){
               _listener.close();  
            }
        }
        @Override
        public void start(Stage primaryStrage) {
            Server s = new Server();
            s.serverStart();
            window=primaryStrage;
            window.setTitle("Close the server");
            button=new Button("Stop");
            StackPane layoutPane=new StackPane();
    
            layoutPane.getChildren().add(button);
            Scene scene=new Scene(layoutPane,300,250);
            button.setOnAction(e -> {
                 s.serverStop();
                Stage stage = scene.getWindow(); // if you also want to exit the application
                stage.close(); // otherwise remove it
               });
            window.setScene(scene);
            window.show();
    
        }
    
     public static void main(String[] args) {
                launch(args);
            }
    
    

    Some Notes:

    1. Your constructor shouldn't be really starting the Server instead it should be used to initialize the server parameters such as: _ip and _port:
    public Server(String  ip, int port){
          this._ip = ip;
          this._port = posrt;
    }
    

    and you should delegate the server starting operations to the serverStart method:

    public void serverStart(){
          try {
              _listener = new ServerSocket(_port);
              _socket = _listener.accept();
              _input = new ObjectInputStream(_socket.getInputStream());
          }
          catch (IOException ex) {
              System.out.println(ex.getMessage());
          }
    }
    
    1. Ideally you should refactor the logic code in a separate class than directly including it in the GUI class.