0

Trying to get better at Java, I'm attempting to create a mutlithreaded Client & Server messenger, in which a Client sends a message to the Server, and the Server then redirects & sends the message to the user the first client wanted to send it to. I've also been researching a lot about concurrency and multithreading and such. My current problem, which I've concluded, is that my BufferedReader/InputStream from my Client isn't "ready" when I start my run thread, and it thus returns a nullPointerException. A few other questions:

  • Should I do my drawGUI() method in a SwingUtilities.invokeLater() statement or does it not matter since I'm not really interacting with the GUI in that method
  • Wondering if the HashMap usersIP would work well for key-value pair, to pair clients to their IP. There's also one of these in the Server class
  • Was gonna ask another question, but forgot what it was. Will edit in later if I remember

Client code(cut down to the useful stuff)

public class Client extends Thread {
public static Socket socket;
public static PrintStream os;
public static BufferedReader is;
public static StringBuffer toAppend = new StringBuffer("");
public static StringBuffer toSend = new StringBuffer("");

//Some variables for use with the JMenuBarItems


public static Map<String, String> usersIP = new HashMap<String, String>();
public static String[] friends;

//Swing variables

public static void drawGUI() {

    //JMenuBar set up

    //Some JMenuItem stuff and adding their action listeners

    //Adding the JMenuBarItems to the JMenuBar

    //Main GUI Window set up

    //Initializing the JTextArea and setting some properties
    chatField = new JTextField();
    chatField.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            String s = chatField.getText();

            if(!s.equals("")) {
                appendToChatBox(s);
                //textArea.append(username + "> " + s);
                chatField.setText("");
                sendString(s);
                System.out.println("In Chat Field: To Send: " + toSend.toString());
            }
        }
    });
    //Adding some panels to the JFrame
            //Setting some stuff for the JFrame
}

    //Some of these methods below may be unneeded, but I left them there just in case
public static void appendToChatBox(String s) {
    synchronized(toAppend) {
        toAppend.append(s);
    }
}

public static void appendToChatBox(String username, String s) {
    synchronized(toAppend) {
        toAppend.append(username + "> " + s);

    }
}

public static void sendString(String s) {
    synchronized(toAppend) {
        toAppend.append(s);
    }
}

public static void cleanUp() {
    try {
        if(socket != null) {
            socket.close();
            socket = null;

        }
    } catch(IOException e) {
        socket = null;

    }

    try {
        if(is != null) {
            is.close();
            is = null;

        } 
    } catch(IOException e) {
        is = null;

    }

    if(os != null) {
        os.close();
        os = null;
    }
}

public static void connect() {
    try {
        System.out.println("In connect method"); //Debug

        socket = new Socket(host, port);
        os = new PrintStream(socket.getOutputStream());
        is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        appendToChatBox("Successfully Connected");
        System.out.println("ToAppend in connect method: " + toAppend.toString()); //Debug
        System.out.println("Successfully Connected");

    } catch(UnknownHostException e) {
        System.err.println("Don't know about host: " + host);

    } catch(IOException e) {
        System.err.println("Couldn't get I/O for the connection to the host " + host);
    }

    if(socket != null && os != null && is != null) {
        try {

            while(!closed) {
                if(toSend.length() != 0) {
                    System.out.println("In connect()> ToSend.length isn't = to 0"); //Debug
                    os.println(toSend);
                    os.flush();
                    toSend.setLength(0);
                }
            }
        } catch(Exception e) {
            System.err.println("Error in sending a message to the Server " + e);
            cleanUp();
        }
    }
}

public static void reconnect() {
    cleanUp();
    connect();

}

public static void main(String args[]) {
    SwingUtilities.invokeLater(new Thread(new Runnable() {
        @Override
        public void run() {
            drawGUI();

        }
    }));

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Attempting to connect to server..."); //Debug
            connect();
        }
    }).start();

    new Client().start();
}

@Override
public void run() {
    String servermessage;

    System.out.println("Client.run() invoked"); //Debug


    try {
        System.out.println("In try-catch statement in Client.run()"); //Debug

        while(is.ready()) {
            System.out.println("Input Stream isn't null & is ready in Client.run()"); //Debug

            servermessage = is.readLine().trim();

            if(servermessage != null && servermessage.length() != 0) {
                if(servermessage.equalsIgnoreCase("client_disconnect")) {
                    break;

                } else if(servermessage.equals(Integer.toString(USERNAME_REQUEST))) {

                } else {
                    appendToChatBox("Server" + servermessage);
                    System.out.println("Server> " + servermessage);

                }
            }

            if(toSend.length() > 0) { //Debug
                System.out.println("ToSend in Client.run's while loop: " + toSend.toString());

            } else { //Debug
                System.out.println("ToSend is empty");

            }
        }
    } catch(Exception e) {
        e.printStackTrace();

    }

    if(toAppend.length() != 0) {
        appendToChatBox("From Client.run() " + toAppend.toString());

    } else { //Debug
        System.out.println("ToAppend is empty");

    }
}
N1ghtk1n9
  • 89
  • 3
  • 12
  • You are violating Swing's threading policy by calling `textArea.append` in the main thread and not in the EDT. Violation of Swing's threading policy **will** result in undefined behavior which will result in bugs and (possibly) death. – Boris the Spider Mar 20 '14 at 14:54
  • @BoristheSpider That was a typo(not saying I'm right) I meant to put `appendToChatBox(...)`. When I change that in my code and run it, the console output is the same, except the nullPointerException is at the top of the console(before everything else), which is weird – N1ghtk1n9 Mar 20 '14 at 15:04
  • Use `EventQueue.invokeLater()`, for [example](http://stackoverflow.com/a/3245805/230513). – trashgod Mar 20 '14 at 17:22
  • @trashgod Where do you mean I should use `EventQueue.invokeLater()`? Do you mean at the `appendToChatBox("From Client.run() " + toAppend.toString());`? Cause when I call those methods they're already in threads, or are those threads not on the EDT, where they need to be? That may not be right, but that's what I'm guessing – N1ghtk1n9 Mar 21 '14 at 14:20

0 Answers0