Search code examples
javanetbeansjlist

Adding items to JList caused java.lang.NullPointerException


I have been searching for a problem in my code for more than 4 hours, but couldn't find it... The problem is, I have one java class with one JFrame, where I have put the JList with a DefaultListModel. Then I have another java class where I try to add items to the DefaultListModel. The problem is, that everything works just fine exept the adding items to the DefaultListModel. Any ideas about what's wrong here?

main java class:

package ledpanelplayer;

imports; //IMPORTS

/**
 *
 * @author Dominik
 */
public class LedPanelPlayer extends JFrame {

    public static String RUN_PATH;
    public static String LIB_PATH;
    public static String PREFERENCES_FILE;
    public static String LOG_FILE;

    public static file_helper f;
public static json_helper j;
public static Player player;
public static Preferences preferences;
public static Schedule s;
public static Console c; 

    public static JFrame WINDOW_FRAME;
    public static int WINDOW_W;
    public static int WINDOW_H;
    public static String WINDOW_TITLE;

    public static JList SCHEDULE_LIST;
    public static DefaultListModel SCHEDULE_LIST_MODEL;

    public static void main(String[] args) {
        setLookAndFeel();
        setUIFont(new javax.swing.plaf.FontUIResource("Arial",Font.PLAIN,12));
        init(); //Init application
    }

    private static void setLookAndFeel() {} //Doesn't matter
    public static void setUIFont (javax.swing.plaf.FontUIResource f){} //Doesn't matter

    public static void init() {
        RUN_PATH = new File("").getAbsolutePath()+"\\"; //Get local directory
        LIB_PATH = RUN_PATH + "\\lib"; //Set libs directory
        PREFERENCES_FILE = RUN_PATH + "\\preferences.lpp"; //Set preferences file path
        LOG_FILE = RUN_PATH + "\\log.txt"; //Set log file path

        f = new file_helper(); //Create new file_helper()
    c = new Console(); //Create new Console()
    c.init_files();
    j = new json_helper(); //Create new json_helper()
    player = new Player(); //Create new Player()
    preferences = new Preferences(); //Create new Preferences()
    s = new Schedule(); //Create new Schedule()

        WINDOW_FRAME = new JFrame(); //Create new JFrame()
        WINDOW_W = 800;
        WINDOW_H = 540;
        WINDOW_TITLE = "Demo";

        WINDOW_FRAME.setSize(WINDOW_W,WINDOW_H);
        WINDOW_FRAME.setLocationRelativeTo(null);
        WINDOW_FRAME.setVisible(true);
        WINDOW_FRAME.setTitle(WINDOW_TITLE);
        WINDOW_FRAME.setDefaultCloseOperation(EXIT_ON_CLOSE);
        WINDOW_FRAME.getContentPane().setLayout(null);
        WINDOW_FRAME.getContentPane().setBackground(new Color(237, 237, 237));
        WINDOW_FRAME.setResizable(false);

        SCHEDULE_LIST_MODEL = new DefaultListModel();
        SCHEDULE_LIST = new JList(SCHEDULE_LIST_MODEL); //Create new JList()
        SCHEDULE_LIST.setBounds(20, 20, 382, 444);
        SCHEDULE_LIST.setBackground(new Color(226,226,226));
        //SCHEDULE_LIST_MODEL.addElement("<html><b>1.</b> Demo <p> duration: 10s | file: demo.mp4 | repeat: *36000</p></html>");
        WINDOW_FRAME.add(SCHEDULE_LIST);
    }

    public static void addElement(String e) {
        SCHEDULE_LIST_MODEL.addElement(e);
    }
}

other class:

public static void updateList() {
        for (int i = 0; i < SCHEDULE.size(); i++) {
            try {
                JSONObject object = (JSONObject)SCHEDULE.get(i);
                String name = object.get("name").toString();
                String duration = object.get("duration").toString();
                String file = object.get("file").toString();
                String repeat = object.get("repeat").toString();
                LedPanelPlayer.addElement("<html><b>"+i+".</b> "+name+" <p> duration: "+(Integer.parseInt(duration)/1000)+"s | file: "+file+" | repeat: *"+repeat+"</p></html>");
            }
            catch(Exception e) {e.printStackTrace();c.err("Schedule.updateList() : " + e.toString());}
        }
    }

Thank you in advance!

The stacktrace:

java.lang.NullPointerException
    at ledpanelplayer.LedPanelPlayer.addElement(LedPanelPlayer.java:369)
    at ledpanelplayer.Schedule.updateList(Schedule.java:69)
    at ledpanelplayer.Preferences.load(Preferences.java:50)
    at ledpanelplayer.LedPanelPlayer.init(LedPanelPlayer.java:142)
    at ledpanelplayer.LedPanelPlayer.main(LedPanelPlayer.java:98)

Solution

  • While VGR's answer (move SCHEDULE_LIST_MODEL so that it is not null when Preferences is intialized) does solve your immedate problem, I would argue that the problem you have is merely a symptom of circular dependency issues, which will make maintaining your program tedious (as you spent about 4 hours discovering), and that simply moving where SCHEDULE_LIST_MODEL is assigned a value is a band-aid fix at best.

    Your program structure is as follows: LedPanelPlayer has dependencies on Preferences and Schedule, Preferences has a dependency on Schedule, and Schedule has a dependency on LedPanelPlayer. The circular dependency problem you have is in that LedPanelPlayer and Schedule are both co-dependent on each other to function. Schedule needs LedPanelPlayer.addElement, and LedPanelPlayer constructs a schedule (and presumably uses it in some part of the LedPanelPlayer you haven't posted, otherwise it's just hanging around and being useless).

    Consider removing SCHEDULE_LIST_MODEL out of LedPanelPlayer entirely, and make it an instance field of the class that's actually managing it (Schedule). Then add Schedule.getScheduleListModel() to Schedule so anything that needs to deal with Scheduling can simply reference that, and make the updateList not static and refer to ScheduleListModel's new home. Since Preferences wants to deal with scheduling info, it will require a schedule instance in its constructor.

    In this way, LedPanelPlayer will depend on Preferences and Schedule, Preferences has a dependency on Schedule, but now Schedule will no longer depend on LedPanelPlayer to function properly, solving not only your immediate problem, but the root cause (and made your code much nicer to read, understand, and maintain to boot!).