Skip to content
Advertisement

null pointer Exception after writeObject to OutputStream

This is code for a basic chat server. The user is asked to enter a username and password on the Chat_Client, which is then encrypted using EncryptedMessage’s encrypt method and sent to the Chat_Server via the ClientOutputStream using writeObject.

When code line clientOutputStream.writeObject(uname) is run it is returning a nullPointerException. I am able to output the encrypted username before this line of code but not after. Why is this?

Chat_Client

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import javax.swing.text.*;
public class Chat_Client extends JFrame
{   // socket to communicate with server
    Socket mySocket;
    // input stream - data sent by the server will be read from this stream
    ObjectInputStream clientInputStream;
    // output stream - data sent to the server will be written to this stream
    ObjectOutputStream clientOutputStream;

    // variables for the GUI components of the game
    Container c;
    ButtonHandler bHandler;
    NameButtonHandler nbHandler;
    ImageButtonHandler ibHandler;
    JButton sendButton, logonButton;
    JButton[] nameButtons, imageButtons;
    ImageIcon[] images = {new ImageIcon("smile.gif"), new ImageIcon("frown.gif"), new ImageIcon("wink.gif"), new ImageIcon("eek.gif"), new ImageIcon("confused.gif"), new ImageIcon("embarrassed.gif"), new ImageIcon("stop.gif")};
    JPasswordField password;
    JTextField username;
    JTextPane outputArea,inputArea;
    StyledDocument docInputArea, docOutputArea;
    Style style;
    JPanel namesPanel, imageButtonsPanel, nameButtonsPanel, sendButtonPanel, inputAreaPanel, logonFieldsPanel, logonButtonPanel, leftPanel, rightPanel, cCenterPanel, lowerPanel, outputAreaPanel;
    JLabel namesLabel, usernameLabel, passwordLabel, imageLabel;

    String[] names = {"Arken", "Ben", "Darklark", "Free"};

    //everybody offline to start with
    boolean[] loggedOn = {false, false, false, false};
    String recipients = "";

    public Chat_Client()
    {   super("Chat_Client");
        addWindowListener
        (   new WindowAdapter()
            {   public void windowClosing(WindowEvent e)
                {   System.exit(0);
                }
            }
        );

        // create and add GUI components
        c = getContentPane();
        c.setLayout(new BorderLayout());

        // GUI components for the username
        logonFieldsPanel = new JPanel();
        logonFieldsPanel.setLayout(new GridLayout(2,2,5,5));
        usernameLabel = new JLabel("Enter Username: ");
        logonFieldsPanel.add(usernameLabel);
        username = new JTextField(10);
        logonFieldsPanel.add(username);

        // GUI components for the password
        passwordLabel = new JLabel("Enter Password: ");
        logonFieldsPanel.add(passwordLabel);
        password = new JPasswordField(10);
        logonFieldsPanel.add(password);
        c.add(logonFieldsPanel,BorderLayout.CENTER);

        // panel for the logon button
        logonButtonPanel = new JPanel();
        logonButton = new JButton("logon");
        bHandler = new ButtonHandler();
        logonButton.addActionListener(bHandler);
        logonButtonPanel.add(logonButton);
        c.add(logonButtonPanel, BorderLayout.SOUTH);

        setSize(300,125);
        setResizable(false);
        setVisible(true);
    }


    void setUpChatClient(boolean chatting)
    {   // remove iniial GUI components (textfield, password field, logon button)
        c.remove(logonButtonPanel);
        c.remove(logonFieldsPanel);

        if(!chatting)
            // if the user has not logged on an error message will be displayed
            c.add(new JTextArea("Logon unsuccessful"));
        else
        {   // if the user has logged on the message service GUI will be set up
            c.setLayout(new BorderLayout());
            leftPanel = new JPanel(new GridLayout(2,1));
            leftPanel.setBackground(Color.WHITE);
            rightPanel = new JPanel(new GridLayout(2,1));

            imageLabel = new JLabel(new ImageIcon("people1.jpg"));
            imageLabel.setBackground(Color.WHITE);
            leftPanel.add(imageLabel);

            // name buttons enable user to choose message recipient(s)
            nameButtonsPanel = new JPanel(new GridLayout(5,1));
            nameButtons = new JButton[names.length];
            nbHandler = new NameButtonHandler();
            for(int r = 0; r < nameButtons.length; r++)
            {   nameButtons[r] = new JButton(names[r]);
                nameButtons[r].addActionListener(nbHandler);
                nameButtons[r].setEnabled(loggedOn[r]);
                nameButtonsPanel.add(nameButtons[r]);
            }
            leftPanel.add(nameButtonsPanel);

            outputAreaPanel = new JPanel();
            outputAreaPanel.setBackground(Color.WHITE);
            // messages from the server will be displayed in this JTextPane
            outputArea = new JTextPane();
            outputArea.setEditable(false);
            Dimension d = new Dimension(300,150);
            outputArea.setPreferredSize(d);
            docOutputArea = (StyledDocument) outputArea.getDocument();
            style = docOutputArea.addStyle("StyleName", null);
            JScrollPane outputScrollPane = new JScrollPane(outputArea);
            outputAreaPanel.add(outputScrollPane);
            rightPanel.add(outputAreaPanel);

            inputAreaPanel = new JPanel();
            inputAreaPanel.setBackground(Color.WHITE);
            // image buttons enable user to add an image to a text message
            imageButtonsPanel = new JPanel();
            imageButtonsPanel.setBackground(Color.WHITE);
            d = new Dimension(25,25);
            ibHandler = new ImageButtonHandler();
            imageButtons = new JButton[images.length];
            for(int j = 0; j < imageButtons.length; j++)
            {   imageButtons[j] = new JButton(images[j]);
                imageButtons[j].setPreferredSize(d);
                imageButtons[j].setBorderPainted(false);
                imageButtons[j].addActionListener(ibHandler);
                imageButtonsPanel.add(imageButtons[j]);
            }
            inputAreaPanel.add(imageButtonsPanel);

            d = new Dimension(300,60);
            // text messages will be entered into this JTextPane
            inputArea = new JTextPane();
            inputArea.setPreferredSize(d);
            docInputArea = (StyledDocument) inputArea.getDocument();
            style = docInputArea.addStyle("StyleName", null);
            JScrollPane scrollPane = new JScrollPane(inputArea);
            inputAreaPanel.add(scrollPane);

            // the send button enables user to send a text message
            sendButtonPanel = new JPanel();
            sendButtonPanel.setBackground(Color.WHITE);
            bHandler = new ButtonHandler();
            sendButton = new JButton("send");
            sendButton.addActionListener(bHandler);
            sendButtonPanel.add(sendButton);
            inputAreaPanel.add(sendButtonPanel);
            rightPanel.add(inputAreaPanel);

            c.add(rightPanel, BorderLayout.CENTER);
            c.add(leftPanel, BorderLayout.WEST);
            setSize(425, 375);
        }
        setResizable(false);
        setVisible(true);
    }

    void changeNameButton(int i, Color c)
    {   /* change the colour of the text on a name 
           button - red indicates that this friend
           is a recipient of next message */
        nameButtons[i].setForeground(c);
    }

    void changeNameButtons(Color c)
    {   /* change the colour of the text on all the 
           name buttons */
        for(int r = 0; r < nameButtons.length; r++)
           changeNameButton(r, c);
    }

    void changeNameButtons()
    {   /* disable or enable each name button - a
           button is enabled if that friend is online,
           otherwise it is disabled */
        for(int r=0; r<nameButtons.length; r++)
        {
            //if user is logged on
            if(loggedOn[r] == true)
            {
                //enable the name button
                nameButtons[r].setEnabled(true);
            }
            else
            {
                nameButtons[r].setEnabled(false);
            }
        }//end of for loop
    }

    void changeFriends(String n, boolean b)
    {   // change a friend's "online" status
        //for loop to iterate through names
        for(int r=0; r < names.length; r++)
        {
            //if loggedOn is true, set boolean to true
            if(n.equals(names[r]))
            {
                loggedOn[r] = b;
            }
        }//end of for loop

        // call method to update buttons
        changeNameButtons();
    }

    void addOutput(String str)
    {   /* this will split the message string into words using the space
           character as a delimiter, the words will be stored in consecutive 
           elements of array "words" */
        String[] words = str.split(" \s*");
        try
        {   // travese array, taking each word in turn
            for(int i = 0; i < words.length; i++)
            {   /* if the first character of this word is $ this indicates that
                    this string represents an image in the text message */
                if(words[i].charAt(0) == '$')
                {   /* the remainder of this word will be a number indicating the 
                       array element in which the image is stored - retrieve this 
                       number from the string */
                    String position = words[i].substring(1, words[i].length());
                    // cast this string number to an int value 
                    int pos = Integer.parseInt(position);
                    // retrieve the appropriate image from the array
                    StyleConstants.setIcon(style, images[pos]);
                    // add the image to the text output area
                    docOutputArea.insertString(docOutputArea.getLength(), " $" + pos + " ", style);
                }
                else
                    // otherwise add the next text word to the text output area
                    docOutputArea.insertString(docOutputArea.getLength(), words[i] + " ", null);
            }
            // add a newline character to the text output area
            docOutputArea.insertString(docOutputArea.getLength(), " n", null);
            // set the caret position in the text output area
            outputArea.setCaretPosition(docOutputArea.getLength());
        }
        catch(BadLocationException ee)
        {   System.out.println(ee);
            System.exit(1);
        }
    }

    void closeChatClient()
    {   // user has quit the message service - disable GUI components
        // disable send message button
        sendButton.setEnabled(false);

        // disable all name buttons
        for(int r=0; r<names.length; r++)
        {
            nameButtons[r].setEnabled(false);
        }

        // disable all image buttons
        for(int s=0; s<imageButtons.length; s++)
        {
            imageButtons[s].setEnabled(false);
        }

        // set input area to prevent text entry
        inputArea.setEditable(false);
    }

    void sendLoginDetails()
    {   
        try
        {   
            // get username from text field and encrypt
            EncryptedMessage uname = new EncryptedMessage(username.getText());
            uname.encrypt();

            // get password from password field and encrypt
            EncryptedMessage pword = new EncryptedMessage(new String (password.getPassword()));
            pword.encrypt();

            System.out.println("1 " + uname);
            // send encrypted username and password to server
            clientOutputStream.writeObject(uname);
            System.out.println("2 " + uname);
            clientOutputStream.writeObject(pword);                                  

        }
        catch(IOException e) // thrown by methods writeObject
        {   System.out.println(e);
            System.exit(1);
        }           
    }

    void getConnections()
    {   try
        {   // initialise a socket and get a connection to server
        //server using post 7500
            mySocket = new Socket(InetAddress.getLocalHost(), 7500);

            // get input & output object streams
            clientInputStream = new ObjectInputStream(mySocket.getInputStream());
            clientOutputStream = new ObjectOutputStream(mySocket.getOutputStream());

            /* create a new thread of Chat_ClientThread, sending input
               stream variable as a parameter */
            Chat_ClientThread newThread = new Chat_ClientThread(clientInputStream);

            // start thread - execution will begin at method run
            newThread.start();
        }
        catch(UnknownHostException e) // thrown by method getLocalHost
        {   System.out.println(e);
            System.exit(1);
        }
        catch(IOException e) // thrown by methods ObjectOutputStream, ObjectInputStream
        {   System.out.println(e);
            System.exit(1);
        }
    }

    void sendMessage(String str)
    {   try
        {   /* if you have not chosen any recipients this message will be 
               sent to all friends by default */
            if(recipients.equals(""))
                recipients = names[names.length - 1] + ",";

            // separate recipients and the message by inserting # character  
            str = recipients + "#" + str;
            // compress message
            CompressedMessage cm = new CompressedMessage(str);
            cm.compress();
            // send message to server
            clientOutputStream.writeObject(cm);
            // clear recipients for next message
            recipients = "";
            // clear the input area
            inputArea.setText("");
            // change the colour of text on name buttons of friends online
            changeNameButtons(Color.BLACK);
        }
        catch(IOException e) // thrown by method writeObject
        {   System.out.println(e);
            System.exit(1);
        }
    }

    void closeStreams()
    {   
        try{
            clientInputStream.close();
            clientOutputStream.close();

            //close socket-good practice
            mySocket.close();
        }

        catch(IOException e) // thrown by method close
        {   System.out.println(e);
            System.exit(1);
        }
    }

    public static void main(String args[])
    {   Chat_Client gameClient = new Chat_Client();
        gameClient.getConnections();
    }


    private class Chat_ClientThread extends Thread
    {   ObjectInputStream threadInputStream;

        public Chat_ClientThread(ObjectInputStream in)
        {   // initialise input stream
            threadInputStream = in;
        }

        // when method start() is called thread execution will begin in this method
        public void run()
        {   try
            {   
                boolean chatting = (Boolean)threadInputStream.readObject();
                // call method to change the client GUI
                setUpChatClient(chatting);
                if(!chatting)
                    // call method to close input & output streams & socket
                    closeStreams();
                else
                {   // this loop will continue until this client quits the chat service
                    while(chatting)
                    {   // read next compressed message from server
                        CompressedMessage nextMsg = (CompressedMessage)clientInputStream.readObject();

                        // decompressed message
                        nextMsg.decompress();

                        // retrieve decompressed message
                        String message = nextMsg.getMessage();

                        // if this client has quit the server will send this last message
                        if(message.equals("goodbye"))
                        {   // chatClient should be closed
                            //call method made above
                            closeChatClient();

                            // close input & output streams & socket
                            closeStreams();

                            // no more chatting - use boolean as above
                            chatting = false;
                        }
                        else
                        {   if(message.substring(0,4).equals("join"))
                            {  
                                changeFriends(message.substring(4,message.length()), true);
                                // output message in output area
                                addOutput(message.substring(4,message.length()) + " has joined");
                            }
                            else
                            {   if(message.substring(0,4).equals("quit"))
                                {  
                                    changeFriends(message.substring(4,message.length()), false);
                                    // output message in output area
                                    addOutput(message.substring(4,message.length()) + " has quit");
                                }
                                else
                                {   if(message.substring(0,6).equals("online"))
                                    {   /* if the first word in the message is "online" then this client
                                           has just joined the chat service and this message lists
                                           the names of all other friends that are online */
                                        // split string to separate names of friends online
                                        String[] online = message.substring(6,message.length()).split(",\s*");
                                        if(!online[0].equals("none"))
                                        {   for(int i = 0; i < online.length; i++)
                                                changeFriends(online[i], true);
                                        }
                                        // output message in output area
                                        addOutput("Your friends online : " + message.substring(6,message.length()-1));
                                    }
                                    else
                                        // output message in output area
                                        addOutput(message);
                                } // end else
                            } // end else
                        } // end else
                    } // end while
                } // end else
            } // end try
            catch(IOException e) // thrown by method readObject
            {   System.out.println(e);
                System.exit(1);
            }
            catch(ClassNotFoundException e) // thrown by method readObject
            {   System.out.println(e);
                System.exit(1);
            }
        } // end method run
    } // end of class Chat_ClientThread

    private class NameButtonHandler implements ActionListener
    {  
        public void actionPerformed(ActionEvent e)
        {   int pos = -1;
            // loop to identify which of the name buttons were clicked
            for(int r = 0; r < nameButtons.length; r++)
            {   if(e.getSource() == nameButtons[r])
                    pos = r;
            }
            // add this friend's name to recipients list
            recipients += names[pos] + ",";
            if(pos == names.length - 1)
               /* you have chosen to send the message to all 
                  friends - change the colour of all the name buttons */
               changeNameButtons(Color.RED);
            else
                /* you have chosen to send the message to an individual 
                   friend - change the colour of this friends name button */
                changeNameButton(pos, Color.RED);
            }
    }  // end of class NameButtonHandler

    private class ImageButtonHandler implements ActionListener
    {   // if any of the image buttons are clicked execution will continue in this method
        public void actionPerformed(ActionEvent e)
        {   int pos = -1; 
            // loop to identify which of the buttons were clicked
            for(int r = 0; r < imageButtons.length; r++)
            {   if(e.getSource() == imageButtons[r])
                    pos = r;
            }
            try
            {   // retrieve the appropriate image from the array
                StyleConstants.setIcon(style, images[pos]);
                // add the image to the text input area
                docInputArea.insertString(docInputArea.getLength(), " $" + pos + " ", style);
            }
            catch(BadLocationException ee)
            {   System.out.println(ee);
                System.exit(1);
            }
        }
    }  // end of class ImageButtonHandler

    private class ButtonHandler implements ActionListener
    {   // if the logon or send buttons are clicked execution will continue in this method
        public void actionPerformed(ActionEvent e)
        {   if(e.getSource() == logonButton)
                /* if the logon button is clicked call method to 
                   send the login details to the server */
                sendLoginDetails();
            else
            {   if(e.getSource() == sendButton)
                    /* if the send button is clicked call method to 
                       send the message to the server */
                    sendMessage(inputArea.getText());
            }
        }
    }  // end of class ButtonHandler
} // end of class Chat_Client

EncryptedMessage

import java.io.Serializable;

public class EncryptedMessage implements Serializable
{   // this instance variable will store the original, encrypted and decrypted message
    private String message;

    // this variable stores the key
    static String KEY = "cable"; 

    public EncryptedMessage(String message)
    {   // initialise original message
        this.message = message;
    }

    public String getMessage()
    {   // return (encrypted or decrypted) message
        return message;
    }

    public void encrypt()
    {   /* this variable stores the letters of the alphabet (in order) as a
       string - this string will be used to encrypt text */         
    String charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.,?0123456789 ";
        String cipherText = "";

        for(int i = 0; i < message.length(); i++)
        {   // find position of plaintext character in the character set
            int plainTxtCh = charSet.indexOf(message.charAt(i));

                // get position of next key character
            int keyPos = i % KEY.length();
                // find position of key character in the character set
                int keyCh = charSet.indexOf(KEY.charAt(keyPos));

            /* add key character to plaintext character - this shifts the
               plaintext character - then divide by length of
               character reference set and get remainder to wrap around */
            int cipherTxtCh = (plainTxtCh + keyCh) % charSet.length();
            /* get character at corresponding position in character reference
               set and add to cipherText */
            char c = charSet.charAt(cipherTxtCh);
            cipherText += c;
        }
        message = cipherText;
    }

    public void decrypt()
    {   /* this variable stores the letters of the alphabet (in order) as a
       string - this string will be used to decrypt text */
        //Must be able to handle numbers, punctuation marks - comma, full stop and questionmark
        String charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.,?0123456789 ";
        String plainText = "";

        for(int i = 0; i < message.length(); i++)
        {   // find position of ciphertext character
            int cipherTxtCh = charSet.indexOf(message.charAt(i));

                // get position of next key character
            int keyPos = i % KEY.length();
                // find position of key character in the character set
                int keyCh = charSet.indexOf(KEY.charAt(keyPos));

            /* subtract original shift from character reference set length to
               get new shift, add shift to ciphertext character then
               divide by character reference set length and get remainder to
               wrap around */
            int plainTxtCh = (cipherTxtCh + (charSet.length() - keyCh)) % charSet.length();

            /* get character at corresponding position in character reference
               set and add to plainText */
            char c = charSet.charAt(plainTxtCh);
            plainText += c;
        }
        message = plainText;
    }
}

Error in console

  1 EncryptedMessage@13b91982
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at Chat_Client.sendLoginDetails(Chat_Client.java:294)
    at Chat_Client$ButtonHandler.actionPerformed(Chat_Client.java:527)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

Line 294 in the chat client where the error is pointing to is

clientOutputStream.writeObject(uname);

Advertisement

Answer

Why is this?

If you get a NullPointerException on that line, there is only one possible explanation. That is that clientOutputStream is null.

The exception is not happening because of the value of uname. The act of passing a null does not and cannot1 throw a NullPointerException. Indeed, it is perfectly valid to write a null to an ObjectOutputStream.

Your next steps should be to:

  1. confirm that clientOutputStream is null at that point and then,

  2. figure out why it is null.

Your code is rather too long for “debugging by visual inspection”, but it looks like that field should be set when you call getConnections() in main(...). Maybe I’m missing something …


1 – There is an edge case where you pass a null instead of a boxed primitive type in a context where the method requires the primitive type. In that case, the unboxing will throw a NullPointerException. That looks like an NPE is being thrown in the the act of making the call, but in fact it is happening in the hidden unboxing operation.

Advertisement