2

I'm writing a program in Java that will allow a person to input data into a form as jobs for a help desk. The submitted form is then used to create a helpRequest object which is entered into a generic Queue for storage in a binary file. However, the onus of the project (it's a school assignment) is to make the program failsoft using exceptions. One specific stipulation of the program is that it must handle any situation where it cannot continue by attempting to save the current helpRequest queue before terminating "gracefully". I've got all of this set up in code, but when the handler runs (by a division by zero in my test), the program hangs as soon as it tries to do anything with the helpQueue.

I've tried looking up Java global variables and global exception handlers, but nothing seems to address the topic of using a structure or variable from another/the throwing class.

Here is the code for the handler. I have helpQueue declared as public and static in the throwing class HelpDeskForm, and NetBeans accepts all the code I have here. The induced exception occurs after the queue has been worked with.

public class GlobalExceptionHandler implements Thread.UncaughtExceptionHandler {

    BinaryOutputFile emergencyOutput;

    public void uncaughtException(Thread t, Throwable e) {
        Frame f = new Frame();
        JOptionPane.showMessageDialog(f, "Program error.  Please select a file for queue output.");
        emergencyOutput = new BinaryOutputFile();
        while(!HelpDeskForm.helpQueue.isEmpty())
            emergencyOutput.writeObject(HelpDeskForm.helpQueue.remove());
        emergencyOutput.close();        
        System.exit(1);
    }

}

Rather than a specific solution to my issue, I'd appreciate it if someone could explain why helpQueue is seemingly not actually visible/usable in this exception handler, or what I'm doing horribly wrong.

EDIT: I didn't want to overcomplicate my explanation, but here is the HelpDeskForm code up until my division by zero exception.

public class HelpDeskForm {

    BinaryDataFile input;
    BinaryOutputFile output; 
    CheckedForm c;
    helpRequest r;
    public static Queue<helpRequest> helpQueue;
    int inputSize;

    public HelpDeskForm() {

        GlobalExceptionHandler h = new GlobalExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(h);

        input = new BinaryDataFile();
        inputSize = input.readInt();
        for(int i = 0; i < inputSize; i++) {
            helpQueue.add((helpRequest)input.readObject());
        }
        input.close();

        int y = 0;
        int z = 2;
        z = z/y;
        ... // GUI code follows 
    }
}    
Corryn
  • 93
  • 7
  • It is better to provide some code for the `HelpDeskForm` and `helpQueue` implementations. – evanwong Oct 16 '14 at 15:28
  • 'why seems like helpQueue isn't visible' -- is it declared as `volatile`? Is that queue thread-safe (e.g., kind of `BlockingQueue`)? And can you make thread-dump and see what statement is being executed by `UncaughtExceptionHandler`? – Victor Sorokin Oct 16 '14 at 15:29
  • And will it work if you remove UI code? – Victor Sorokin Oct 16 '14 at 15:30
  • ...why would you need a global exception handler? Is there some issue with `try/catch` blocks in the location you actually try to do the operations? – Powerlord Oct 16 '14 at 15:31
  • Have you registered the UncaughtExceptionHandler to your threads? – Nathanael Oct 16 '14 at 15:51
  • @evanwong helpQueue is just a standard generic Queue from the Java library, but I added the relevant code of HelpDeskForm. – Corryn Oct 16 '14 at 17:32
  • @VictorSorokin The HelpDeskForm code should also address anything related to the declaration of helpQueue itself. I will look into doing a thread-dump. Removing all attempts to use helpQueue in the handler results in the program terminating successfully with System.exit(1). – Corryn Oct 16 '14 at 17:33
  • @Powerlord The handler has to be global because this assignment requires that any and all exceptions (even logically impossible ones) be handled. – Corryn Oct 16 '14 at 17:33
  • If the `HelperDeskForm` is real. It looks like to me you will be getting `NullPointerException` when you are calling `HelpDeskForm.helpQueue.isEmpty()`. If not, your information is not enough to help to diagnose the problem. – evanwong Oct 16 '14 at 17:37
  • @evanwong That's kind of what I want to get out of asking this. I have helpQueue declared as public static, which from my searching seems to mean it is global (I try to avoid globals in general). However, despite it being global and instantiated by the time the exception occurs, trying to access it in the handler causes another exception (probably NullPointer as you said). There's literally no other code involved in this issue, so if any more semantic information is necessary, please ask. – Corryn Oct 16 '14 at 17:50
  • @Corryn Code seem to lack initialization of `helpQueue`, so the very first `helpQueue.add` will produce NPE. Your earlier comment says ` queue instantiated by the time the exception occurs`, but code seems to contradict this. – Victor Sorokin Oct 16 '14 at 18:56
  • @Corryn plus, comments to this SO answer suggests that NPE inside UncaughtExcHandler _may_ cause endless loops: http://stackoverflow.com/a/7241026/162634 – Victor Sorokin Oct 16 '14 at 19:00
  • `public static Queue helpQueue;` <-- This is a `Queue` object whose current value is null. Perhaps you meant `public static Queue helpQueue = new LinkedList<>();` ? – Powerlord Oct 16 '14 at 19:47
  • @VictorSorokin Thank you, your observation made me realize my mistake. NetBeans was taking issue when I attempted to instantiate helpQueue, so I mistakenly thought that my initial declaration was all that was necessary. Not having used Java's library for structures before, I didn't realize that Queue was only an interface and not an implementation. I looked up some old generic structures I did and I'm sure the issue was my misinterpretation of Java's library generics rather than what I initially thought it was. – Corryn Oct 16 '14 at 19:47
  • @Corryn ok, fine. One needs to initialize all references, otherwise they'll be `null`, if they are member or static member references (like `helpQueue`) and will produce `NPE`, or, for method's local references, compiler won't let you use uninitialized values. And, sure, you can't instantiate interface (although, you can instantiate anonymous class which implements an interface). – Victor Sorokin Oct 16 '14 at 19:52
  • @VictorSorokin I changed helpQueue from a Queue to a LinkedList from the same library and the exception handler now completes just fine. Thanks so much for observing my mistake even when I had already discounted it as a cause. I'm new to question asking on SO; how can I credit you for your help? – Corryn Oct 16 '14 at 21:06

1 Answers1

1

HelpDeskForm seems to lack initialization for queue being used, so NPE is inevitable. Try to add initialization to declaration:

public static Queue<helpRequest> helpQueue = new ArrayBlockingQueue<helpRequest>(100);

Plus, for the posted code, it would be logical to add volatile keyword to queue declaration:

public static volatile BlockingQueue<helpRequest> helpQueue;

public void createQueue() {
   // make sure createQueue() is called at the very beginning of your app,
   // somewhere in main()
   helpQueue = new ArrayBlockingQueue...
}

This way all other threads, if any, will see correct reference to the queue, and thread safety of BlockingQueue guarantees correct visibility of its' contents.

Victor Sorokin
  • 11,878
  • 2
  • 35
  • 51