Question

So I am modifying an existing open source project, I've created a new monitor class which I use to observe changes in the existing classes using the observer pattern, this itself is being monitored by a few more monitor classes.

In the main class of the original system I've got it working, however when the program switches to other classes I have tried to pass the manager in through the constructor of the new classes (passed through represented by the interface Manager which contains the send() function which the program updates the monitor with. However when I try to call send from the other class it doesn't work (it does in the first class, called Main).

When I call send() in a 'MouseHandler' class declared within this new class, I get the following error:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at kabalpackage.GameArea$MouseHandler.mouseReleased(GameArea.java:565)
    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$000(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)

I have tried declaring another Manager variable in this MouseHandler class, and passing it through in the constructor, but got the same error.

This is the class where it works, I've omitted quite a lot of code though for simplicity.

/*added necessary imports */
import java.util.*;
import monitors.Manager;
import monitors.MonManager;


 public class Main
 extends JFrame
 {
//  added manager variable
public static Manager manager;

public Main(Manager m)
{
     // this is where I set the manager provided in the constructor
             this.manager = m;

    // ..... lots of code skipped

    //  I try and pass the manager in to the new class here
private GameArea gameArea = new GameArea(manager);

private class MenuBar
extends JMenuBar
{
    //.....lots of code skipped
    }

    private class MenuListener
    implements ActionListener
    {
        private MenuListener() {}

        public void actionPerformed(ActionEvent e)
        {
            String event = e.getActionCommand();
            if (event.equals("New Game"))
            {


                // here is where i call send on the monitor
                                    System.out.println("Sending win 0"); 
                manager.send("win 0");
                Main.this.gameArea.newGame();
                System.out.println("New game");

                    }
                }
            }
        }
    }
}

As you can see, a new class is declared within the class. Here is the class GameArea which is called from the above class, as you can see I modified the constructor to take a manager (interface) object, so I can pass the SAME monitor manager into this next class. I've omitted a lot of code once again from this class, including a few imports (it still has import java.util.*; which I believe is needed to send events).

import monitors.MonManager;
import monitors.Manager;

public class GameArea
extends JPanel
{
public static Manager manager;
    // loads of variables omitted //

// heres the constructor for the class, a manager is passed in and set to variable Manager
    public GameArea(Manager m)
{
    setLayout(null);
    setBackground(this.BACKGROUND_COLOR);
    setCursor(new Cursor(12));
    this.manager = m;

    loadImages();
}
    // more code omitted //
public void newGame()
{
    removeAll();
            // this creates the mouse handler class where i try to call manager.send
    MouseHandler mh = new MouseHandler();


}


    // more code omitted //

public class MouseHandler
extends MouseInputAdapter
{   
    // variables omitted

    private MouseHandler() {
    }

    public void mouseMoved(MouseEvent e)
    {
         //
    }

    public void mousePressed(MouseEvent e)
    {
        // omitted code //
    }    
    public void mouseDragged(MouseEvent e)
    {
        // omitted code //
    }

    public void mouseClicked(MouseEvent e)
    {
        // omitted code
    }

    public void mouseReleased(MouseEvent e)
    {
        // more omitted code
            if ((this.SRC_STACK instanceof DealtCardsStack)) {
                GameArea.this.moves.clear();
                // a call of manager
                System.out.println("Sending moves");
                manager.send("moves");
            } else {
                GameArea.this.moves.add(new Move(this.SRC_STACK, this.DST_STACK, this.TMP_LIST));
                // Here is the call for the manager, which creates an error.
                System.out.println("Sending moves");
                manager.send("moves");
            }
        }
        else
        {
            this.SRC_STACK.showCards(this.TMP_LIST);
        }
    // skipped some code//
}

}

and finally here is the code in my manager interface which is implemented by the monitor manager:

package monitors;

public interface Manager {

    public void send(String message);
} 

Sorry if the question is not clear. There was a lot of code to omit so it looks pretty messy, but I don't think anything I left out has an impact on the errors. So basically in the Main class my messages are being sent to the monitor implementing Manager, but in the other class they are not, and I don't know why.

Thanks very much to anyone who had the patience to read through that, and special thanks if you can tell what my problem is!

Was it helpful?

Solution

Fields initializations are done before the actual constructor execution so the line

private GameArea gameArea = new GameArea(manager);

was passing an uninitialized manager, thus causing the NullPointerException.

Simply putting the initialization inside the constructor as gameArea = new GameArea(manager); solves the problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top