2
\$\begingroup\$

A few days ago I posted a question about my code. It was obviously awful and thanks to some advice from Hosch250 I learnt a lot of things about OOP.

Now, I rewrote the program. To me it seems a little bit better than the previous one but I still feel that something is wrong.

In ServerSide.java there are 2 threads: one accepts new clients, and the other listens for messages from the clients. Since the second thread starts only after the first thread creates a Client, I don't know why I should synchronize them. Both of the classes share a static list so I don't see the point to use synchronization.

I would like to avoid using the methods userClicksSubmit(String messages) and appendMessage(String text) as static, but I don't know how to.

ServerSide.java

public class ServerSide extends Thread {
private ServerSocket ss;
private Socket sock;
private int ID;
private static Map<Client, Integer> clientList = new HashMap<Client, Integer>();
private static PrintWriter pw;
int port;

// Main Constructor takes the port to connect to a server
// in order to chat with the clients
public ServerSide(int port) throws IOException {
    this.port = port;
    this.run();
}

@Override
public void run() {
    try {
        ss = new ServerSocket(port);
    } catch (IOException e) {
        e.printStackTrace();
    }
    receivingClients();
}

public void receivingClients() {
    while (true) {
        try {
            sock = ss.accept();
            clientList.put(new Client(sock, ID), ID);
            ID++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
//Static method that is called every time the server's user submits a message
public static void userClicksSubmit(String messages) throws IOException {
    for (Map.Entry<Client, Integer> client : clientList.entrySet()) {
        System.out.println(messages);
        pw = new PrintWriter(client.getKey().getSock2().getOutputStream());
        pw.println(messages);
        pw.flush();
    }
}
   //////////////////////////// Receives the clients' messages ////////////////////////////
private class Client extends Thread{

    private InputStreamReader inReader;
    private BufferedReader buffReader;
    private Socket sock2;
    private PrintWriter pw2;
    private int ID;
    private String messages;

    public Client(Socket sock2, int ID) throws IOException {
        this.sock2 = sock2;
        this.ID = ID;
        this.start();
    }
    public void getMessages() throws IOException {
        inReader = new InputStreamReader(sock2.getInputStream());
        buffReader = new BufferedReader(inReader);

        while ((messages = buffReader.readLine()) != null) {
            //Static method of the Graphic Interface.It appends the messages to the textArea of the application
            GraphicSide.appendMessage(messages);
            //Send the received messages to all the clients of the map list with the exception of the sender
            for (Map.Entry<Client, Integer> client : clientList.entrySet()) {
                pw2 = new PrintWriter(client.getKey().getSock2().getOutputStream());
                if (client.getValue() != ID) {
                    pw2.println(messages);
                    pw2.flush();
                }
            }
        }
    }
    public Socket getSock2() {
        return sock2;
    }
    @Override
    public void run() {
        try {
            getMessages();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 }

}

GraphicSide.java

public class GraphicSide extends JFrame {
private JPanel contentPane;
private static JTextField textPort;
private JTextField textId;
private JButton submit;
private int port;
private static JTextArea textArea;
private static boolean agree = false;
private  String text;
private String id;


public GraphicSide() {
    setTitle("Login of the Server");
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setBounds(100, 100, 250, 355);
    setVisible(true);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);


    JLabel portName = new JLabel("Port:");
    portName.setHorizontalAlignment(SwingConstants.CENTER);
    portName.setBounds(106, 102, 46, 14);
    contentPane.add(portName);

    textPort = new JTextField();
    textPort.setHorizontalAlignment(SwingConstants.CENTER);
    textPort.setToolTipText("e.g. 81");
    textPort.setBounds(77, 127, 103, 20);
    contentPane.add(textPort);
    textPort.setColumns(10);

    JLabel idLabel = new JLabel("Id:");
    idLabel.setHorizontalAlignment(SwingConstants.CENTER);
    idLabel.setBounds(106, 174, 46, 14);
    contentPane.add(idLabel);

    textId = new JTextField();
    textId.setHorizontalAlignment(SwingConstants.CENTER);
    textId.setToolTipText("e.g. Mike");
    textId.setBounds(77, 199, 103, 20);
    contentPane.add(textId);
    textId.setColumns(10);

    submit = new JButton("Submit");
    submit.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            if (textId.getText().length() == 0 || textPort.getText().length() == 0) {
                JOptionPane.showMessageDialog(null, "Compile all the fields", "Error", JOptionPane.WARNING_MESSAGE);
                return;
            }
            setVisible(false);
            try {
                id = textId.getText();
                new ChatWindow();
                agree = true;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });

    submit.setBounds(94, 257, 74, 23);
    contentPane.add(submit);

}

private class ChatWindow extends JFrame {
    {
        this.setTitle("Server");
        this.setSize(750, 480);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setMinimumSize(new Dimension(750, 480));

        GridBagLayout gridBagLayout_1 = new GridBagLayout();
        gridBagLayout_1.columnWidths = new int[] { 0, 640, 70 };
        gridBagLayout_1.rowHeights = new int[] { 387, 0, 0, 41, 40 };
        gridBagLayout_1.columnWeights = new double[] { 1.0, 1.0 };
        gridBagLayout_1.rowWeights = new double[] { 1.0, 0.0, 0.0, 1.0, Double.MIN_VALUE };
        this.getContentPane().setLayout(gridBagLayout_1);

        textArea = new JTextArea();
        JScrollPane scroll = new JScrollPane(textArea);
        DefaultCaret caret = new DefaultCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        textArea.setEditable(true);
        textArea.setBorder(BorderFactory.createEtchedBorder());
        GridBagConstraints gbc_textArea = new GridBagConstraints();
        gbc_textArea.gridwidth = 3;
        gbc_textArea.insets = new Insets(2, 2, 5, 2);
        gbc_textArea.fill = GridBagConstraints.BOTH;
        gbc_textArea.gridx = 0;
        gbc_textArea.gridy = 0;
        this.getContentPane().add(scroll, gbc_textArea);

        JTextField textField = new JTextField();
        textField.setBorder(BorderFactory.createEtchedBorder());
        GridBagConstraints gbc_textArea_1 = new GridBagConstraints();
        gbc_textArea_1.gridheight = 2;
        gbc_textArea_1.gridwidth = 2;
        gbc_textArea_1.fill = GridBagConstraints.BOTH;
        gbc_textArea_1.insets = new Insets(2, 2, 2, 5);
        gbc_textArea_1.gridx = 0;
        gbc_textArea_1.gridy = 3;
        this.getContentPane().add(textField, gbc_textArea_1);
        this.setVisible(true);


        JButton btnNewButton = new JButton("Send");
        btnNewButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                text = textField.getText();
                try {
                    ServerSide.userClicksSubmit(textId.getText()+" : " +text);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                textArea.append(text + '\n');
                textField.setText("");
            }
        });

        textField.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter");
        AbstractAction pressedAction = new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent arg0) {

                // Here you put the code that is run when you press the key
                btnNewButton.doClick();
                System.out.println("Key pessed");

            }

        };
        textField.getActionMap().put("enter", pressedAction);

        GridBagConstraints gbc_btnNewButton = new GridBagConstraints();
        gbc_btnNewButton.gridheight = 2;
        gbc_btnNewButton.gridx = 2;
        gbc_btnNewButton.gridy = 4;
        this.getContentPane().add(btnNewButton, gbc_btnNewButton);

    }
}
public static void appendMessage(String text) {
    textArea.append(text + '\n');
}

public  boolean isAgree() {
    return agree;
}

public  int getPort() {
    return port = Integer.parseInt(textPort.getText());
}

}

MainClass.java

import java.io.IOException;
import javax.swing.JFrame;

public class MainClassApp extends JFrame {


private static final long serialVersionUID = 1L;

public static void main(String[] args) throws IOException, InterruptedException {

    GraphicSide gs = new GraphicSide();
    //Starts the server class only after the user inserts a port and presses the submit button on the GUI 
    //application
    while (true) {
        if (gs.isAgree() == true) {
            break;
        }
    }
    new ServerSide(gs.getPort());
  }
}
\$\endgroup\$
1
  • \$\begingroup\$ I could create a GraphicSide object and call it from the ServerSide class,inside its thread instead of calling it in the main class.Doing that would allows me to get rid of static in " appendMessage(String text) ". But how can i get rid of static in " userClicksSubmit(String messages) " ? \$\endgroup\$
    – TomCa
    Commented Dec 4, 2016 at 0:38

1 Answer 1

1
\$\begingroup\$

I made a few correction.In order to delete static from the 2 methods,i created a GraphicSide object diretly in the ServerSide class and built a method on the GraphicSide class that contains a ServerSide object.I also removed the HashMap and changed it in an ArrayList.Should i change something else? What do you think about this new code?

ServerSide.java

public class ServerSide extends Thread {
private ServerSocket ss;
private Socket sock;
private int ID;
private static ArrayList<Client> clientList = new ArrayList<Client>();
private static PrintWriter pw;
int port;
private GraphicSide gs;

// Main Constructor 
public  ServerSide() throws IOException, InterruptedException {

     gs = new GraphicSide();
    // Starts the Thread  only after the user inserts a port and presses the submit button on the GUI
    // application
    while (true) {
        Thread.sleep(100);
        if (gs.isAgree()) {
            break;
        }
    }
    //Passes the current ServerSide object to the GraphicSideClass
    gs.setServerSide(this);
    this.run();

}

@Override
public void  run() {
    try {
        ss = new ServerSocket(gs.getPort());
    } catch (IOException e) {
        e.printStackTrace();
    }
    receivingClients();
}

public void receivingClients() {
    while (true) {
        try {
            sock = ss.accept();
            clientList.add(new Client(sock, ID));
            ID++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// Method that is called every time the server's user submits a
// message
public void userClicksSubmit(String messages) throws IOException {
    for (Client client : clientList) {
        System.out.println(messages);
        pw = new PrintWriter(client.getSock2().getOutputStream());
        pw.println(messages);
        pw.flush();
    }
}

//////////////////////////// Receives the clients' messages ////////////////////////////////////////////////////////
private class Client  {

    private InputStreamReader inReader;
    private BufferedReader buffReader;
    private Socket sock2;
    private PrintWriter pw2;
    private int ID;
    private String messages;

    public Client(Socket sock1, int ID) throws IOException {
        this.sock2 = sock1;
        this.ID = ID;
        t1.start();
    }

    public void getMessages() throws IOException {
        inReader = new InputStreamReader(sock2.getInputStream());
        buffReader = new BufferedReader(inReader);

        while ((messages = buffReader.readLine()) != null) {
            // Method of the Graphic Interface.It appends the
            // messages to the textArea of the application
            gs.appendMessage(messages);
            // Sends the received messages to all the clients of the          Arraylist
            // with the exception of the sender
            for (Client client : clientList) {
                pw2 = new PrintWriter(client.getSock2().getOutputStream());
                if (ID != client.getID()) {
                    pw2.println(messages);
                    pw2.flush();
                }
            }
        }
    }

    public Socket getSock2() {
        return sock2;
    }
    Thread t1 = new Thread(new Runnable(){

        @Override
        public void run() {
            try {
                getMessages();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });

    public int getID() {
        return ID;
    }       
 }
}

GraphicSide.java

public class GraphicSide extends JFrame {
private JPanel contentPane;
private static JTextField textPort;
private JTextField textId;
private JButton submit;
private int port;
private static JTextArea textArea;
private static boolean agree = false;
private  String text;
private String id;
private ServerSide ss;


public GraphicSide() {
    setTitle("Login of the Server");
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setBounds(100, 100, 250, 355);
    setVisible(true);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);


    JLabel portName = new JLabel("Port:");
    portName.setHorizontalAlignment(SwingConstants.CENTER);
    portName.setBounds(106, 102, 46, 14);
    contentPane.add(portName);

    textPort = new JTextField();
    textPort.setHorizontalAlignment(SwingConstants.CENTER);
    textPort.setToolTipText("e.g. 81");
    textPort.setBounds(77, 127, 103, 20);
    contentPane.add(textPort);
    textPort.setColumns(10);

    JLabel idLabel = new JLabel("Id:");
    idLabel.setHorizontalAlignment(SwingConstants.CENTER);
    idLabel.setBounds(106, 174, 46, 14);
    contentPane.add(idLabel);

    textId = new JTextField();
    textId.setHorizontalAlignment(SwingConstants.CENTER);
    textId.setToolTipText("e.g. Mike");
    textId.setBounds(77, 199, 103, 20);
    contentPane.add(textId);
    textId.setColumns(10);

    submit = new JButton("Submit");
    submit.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            if (textId.getText().isEmpty()  || textPort.getText().isEmpty()) {
                JOptionPane.showMessageDialog(null, "Compile all the fields", "Error", JOptionPane.WARNING_MESSAGE);
                return;
            }
            setVisible(false);
            try {
                id = textId.getText();
                new ChatWindow();
                agree = true;
            } catch (Exception e) {

                e.printStackTrace();
            }
        }
    });

    submit.setBounds(94, 257, 74, 23);
    contentPane.add(submit);

}

private class ChatWindow extends JFrame {
    {
        this.setTitle("Server");
        this.setSize(750, 480);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setMinimumSize(new Dimension(750, 480));

        GridBagLayout gridBagLayout_1 = new GridBagLayout();
        gridBagLayout_1.columnWidths = new int[] { 0, 640, 70 };
        gridBagLayout_1.rowHeights = new int[] { 387, 0, 0, 41, 40 };
        gridBagLayout_1.columnWeights = new double[] { 1.0, 1.0 };
        gridBagLayout_1.rowWeights = new double[] { 1.0, 0.0, 0.0, 1.0, Double.MIN_VALUE };
        this.getContentPane().setLayout(gridBagLayout_1);

        textArea = new JTextArea();
        JScrollPane scroll = new JScrollPane(textArea);
        DefaultCaret caret = new DefaultCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        textArea.setEditable(true);
        textArea.setBorder(BorderFactory.createEtchedBorder());
        GridBagConstraints gbc_textArea = new GridBagConstraints();
        gbc_textArea.gridwidth = 3;
        gbc_textArea.insets = new Insets(2, 2, 5, 2);
        gbc_textArea.fill = GridBagConstraints.BOTH;
        gbc_textArea.gridx = 0;
        gbc_textArea.gridy = 0;
        this.getContentPane().add(scroll, gbc_textArea);

        JTextField textField = new JTextField();
        textField.setBorder(BorderFactory.createEtchedBorder());
        GridBagConstraints gbc_textArea_1 = new GridBagConstraints();
        gbc_textArea_1.gridheight = 2;
        gbc_textArea_1.gridwidth = 2;
        gbc_textArea_1.fill = GridBagConstraints.BOTH;
        gbc_textArea_1.insets = new Insets(2, 2, 2, 5);
        gbc_textArea_1.gridx = 0;
        gbc_textArea_1.gridy = 3;
        this.getContentPane().add(textField, gbc_textArea_1);
        this.setVisible(true);


        JButton btnNewButton = new JButton("Send");
        btnNewButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                text = textField.getText();
                try {
                    setServerSide(ss);
                    System.out.println(ss);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                textArea.append(text + '\n');
                textField.setText("");
            }
        });

        textField.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter");
        AbstractAction pressedAction = new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent arg0) {


                btnNewButton.doClick();
                System.out.println("Key pessed");

            }

        };
        textField.getActionMap().put("enter", pressedAction);

        GridBagConstraints gbc_btnNewButton = new GridBagConstraints();
        gbc_btnNewButton.gridheight = 2;
        gbc_btnNewButton.gridx = 2;
        gbc_btnNewButton.gridy = 4;
        this.getContentPane().add(btnNewButton, gbc_btnNewButton);

    }
}
public void appendMessage(String text) {
    textArea.append(text + '\n');
 }

public  boolean isAgree() {
    return agree;
 }

public  int getPort() {
    return port = Integer.parseInt(textPort.getText());
 }
public void setServerSide(ServerSide ss) throws IOException {
    this.ss = ss;
    ss.userClicksSubmit(textId.getText()+" : " +text);

 }
}

MainClassApp.java

public class MainClassApp extends JFrame {

/**
 * 
 */
private static final long serialVersionUID = 1L;

public static void main(String[] args) throws IOException, InterruptedException {

    new ServerSide();

 }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.