-1

I write a Library login page with Java Swing and try to run it. The page can run properly but when I type in any username, choose a type and press login, it raises an AWT-EventQueue-0: NullPointerException.

The Library class deserializes two files containing the user and book info, and initialize them into objects.

User is the parent class of Member and Staff, Book class represents a book with its title, description, copy. The methods of these classes are all correct.

LoginWindow.java

import java.awt.EventQueue;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class LoginWindow {

    private JFrame frmLogIn;
    private JTextField textField;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    LoginWindow window = new LoginWindow();
                    window.frmLogIn.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Initialize the contents of the frame.
     */
    public LoginWindow() {

        frmLogIn = new JFrame();

        JLabel lblName = new JLabel("Name:");
        lblName.setBounds(23, 25, 46, 14);
        frmLogIn.getContentPane().add(lblName);

        JLabel lblType = new JLabel("Type:");
        lblType.setBounds(23, 56, 46, 14);
        frmLogIn.getContentPane().add(lblType);

        JTextField textField = new JTextField();
        textField.setBounds(71, 22, 158, 20);
        frmLogIn.getContentPane().add(textField);
        textField.setColumns(10);

        JComboBox comboBox = new JComboBox();
        comboBox.setModel(new DefaultComboBoxModel(new String[] {"Staff", "Member"}));
        comboBox.setBounds(71, 53, 158, 20);
        frmLogIn.getContentPane().add(comboBox);

        JButton btnNewButton = new JButton("Login");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {

                if (!Library.users.containsKey(textField.getText())) {
                    new CreateUserWindow();
                    frmLogIn.dispose();
                }

                else if (!Library.users.get(textField.getText()).getUserType().equals(comboBox.getActionCommand())) {
                    JOptionPane.showMessageDialog(null,
                            "The user name and user type do not match, please try again.",
                            "User information mismatch", JOptionPane.ERROR_MESSAGE);
                }

                else {
                    String type = comboBox.getActionCommand();
                    if (type.equals("Staff")) new StaffWindow((Staff)Library.users.get(textField.getText()));
                    else new MemberWindow((Member)Library.users.get(textField.getText()));
                }
            }
        });
        btnNewButton.setBounds(23, 88, 206, 23);
        frmLogIn.getContentPane().add(btnNewButton);


        frmLogIn.setTitle("Log in");
        frmLogIn.setBounds(100, 100, 268, 185);
        frmLogIn.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmLogIn.getContentPane().setLayout(null);
        frmLogIn.setVisible(true);
    }
}

Library.java

import java.io.*;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class Library implements Serializable{

    public static HashMap<String, User> users;
    public static HashMap<String, Book> books;

    public Library(boolean readFromSerialized) throws IOException, ClassNotFoundException {
        users = new HashMap<>();
        books = new HashMap<>();

        if (readFromSerialized) {
            ObjectInputStream u_in = new ObjectInputStream(new FileInputStream("./Assignment/data/Users.txt"));
            ObjectInputStream b_in = new ObjectInputStream(new FileInputStream("./Assignment/data/Books.txt"));

            users = (HashMap<String, User>) u_in.readObject();
            books = (HashMap<String, Book>) b_in.readObject();

            u_in.close();
            b_in.close();
        }
    }

    public static void serializeToFile() {
        try {
            ObjectOutputStream u_out = new ObjectOutputStream(new FileOutputStream("./Assignment/data/Users.txt"));
            ObjectOutputStream b_out = new ObjectOutputStream(new FileOutputStream("./Assignment/data/Books.txt"));

            u_out.writeObject(Library.users);
            b_out.writeObject(Library.books);

            u_out.close();
            b_out.close();
        } catch (Exception ex) {}
    }
}

Error message shows that the following code snippet contains some error, the code is about user info validation:

if (!Library.users.containsKey(textField.getText())) {
                    new CreateUserWindow();
                    frmLogIn.dispose();
                }
Frakcool
  • 10,088
  • 9
  • 41
  • 71
Duludulu
  • 37
  • 4
  • Please don't use the `back button` of your browser to edit your question. It breaks the changes made by others – Frakcool Jun 07 '19 at 19:40
  • And even if this wouldn't be the thousands repetition of the same question, your request is nowhere close to be a [mcve]. Please learn how and what to ask here before writing more questions. – GhostCat Jun 07 '19 at 20:03

1 Answers1

1

You have several issues in your code:

  1. Use of setBounds and use of null-layout (setLayout(null)), which is evil and frowned upon, as it might lead to annoying issues such as this, use proper Layout Managers in order to make your application to render correctly in all OS and PLAFs.

  2. Use of public static members, this might lead to inconsistencies in your application flow.

  3. Now, your issue is that you create a global textfield variable but never initialize it (so it's null)

    private JTextField textField;
    

    But then, on your constructor you create another one with the same name, but it's a local variable:

    JTextField textField = new JTextField();
    

    And when you call this line:

    else if (!Library.users.get(textField.getText()).getUserType().equals(comboBox.getActionCommand())) {
    

    Java is using the global variable (which remember it's null), not the local one (which is initialized), in order to fix this, remove JTextField on the declaration of the local variable:

    JTextField textField = new JTextField();
    

    So, it becomes:

    textField = new JTextField();
    

    That's going to initialize the global variable and you will be able to use it in your ActionListener

Frakcool
  • 10,088
  • 9
  • 41
  • 71
  • I just fixed the scope issue but it still raises the same exception. – Duludulu Jun 07 '19 at 20:09
  • Well, unless you post the stack trace AND a [mcve] that addresses all the above recommendations made by me, I think I can't provide any more help. My guess is that it has something to do with your `static users` variable in the `Library` class – Frakcool Jun 07 '19 at 20:12