Search code examples
java-metry-catchmidplcduinokia-s40

try/catch does nothing in Java ME


So I have the following code:

public class Minesweeper extends MIDlet implements CommandListener {
  public static String error = "";

  public void startApp() throws MIDletStateChangeException {
    Display display = Display.getDisplay(this);

    canvas = new MCanvas();

    canvas.addCommand(exitCommand);
    canvas.addCommand(okCommand);
    canvas.addCommand(newCommand);

    canvas.setCommandListener(this);

    try{
        display.setCurrent(canvas);
    } catch (Exception e) {
        error = e.toString();
    }
  }
}

When I leave display.setCurrent(canvas); outside of the try block, the app fails with a NullPointerException. When I comment out that line, the app works (although obviously no canvas is added). So the error is caused by that line, or something that that line causes.

So I suround that line with try/catch. Although the error is caused by that line, the error still happens when the line is surrounded by try/catch. How can I catch the error? (I've tried this using Throwable as well, and it is still not caught.

MCanvas:

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

public class MCanvas extends Canvas {

protected void paint(Graphics g){
    //Minesweeper.p("repaint");

    Space[] data = Minesweeper.topaint;

    for(int x=0; x<data.length; x++){
        data[x].print();

        int r = data[x].row * 10;
        int c = data[x].col * 10;
        int v = data[x].value;
        String s = "";

        //System.out.println("r:"+Integer.toString(r)+" c:"+Integer.toString(c)+" s:"+Integer.toString(v));

        g.setColor(250, 0, 0);

        //Minesweeper.p("if");

        if(data[x].open){
            switch(v){
            case 0:
                g.setColor(50, 50, 50);
                break;
            case 1:
                g.setColor(100, 50, 50);
                s = "1";
                break;
            case 2:
                g.setColor(150, 50, 50);
                s = "2";
                break;
            case 3:
                g.setColor(200, 50, 50);
                s = "3";
                break;
            case 4:
                g.setColor(250, 50, 50);
                s = "4";
                break;
            case 5:
                g.setColor(250, 100, 100);
                s = "5";
            break;
            case 6:
                g.setColor(250, 125, 125);
                s = "6";
                break;
            case 7:
                g.setColor(250, 150, 150);
                s = "7";
                break;
            case 8:
                g.setColor(250, 175, 175);
                s = "8";
                break;
            case 9:
                g.setColor(250, 200, 200);
                break;
            default:
                g.setColor(250, 100, 100);
            }
        } else {
            g.setColor(0,0,0);
        }


        g.fillRect(c, r, 10, 10);

        g.setColor(250, 250, 250);
        Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);  
        g.setFont(font);
        g.drawString(s, c+5, r+8, Graphics.HCENTER | Graphics.BASELINE);

        if(data[x].hover){
            g.setColor(250, 250, 250);
            g.drawLine(c, r, c, r+9);
            g.drawLine(c, r, c+9, r);
            g.drawLine(c+9, r, c+9, r+9);
            g.drawLine(c, r+9, c+9, r+9);
        }

        //Minesweeper.p("here?");
    }

    //Minesweeper.p("here");

    //Minesweeper.p(Minesweeper.error);

    if(Minesweeper.error != null){
        g.drawString(Minesweeper.error, 10, 10, Graphics.HCENTER | Graphics.BASELINE);
    }

    Minesweeper.p("msg:"+Minesweeper.message);

    g.setColor(0, 0, 0);
    Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE);  
    g.setFont(font);
    g.drawString(Minesweeper.message, this.getWidth()/2, this.getHeight()-10, Graphics.HCENTER | Graphics.BASELINE);

    Font fontsm = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);  
    g.setFont(fontsm);
}

protected void keyPressed(int keyCode) {
    int gameaction = getGameAction(keyCode);

    int c = Minesweeper.selected.col;
    int r = Minesweeper.selected.row;

    switch (gameaction) {
    case UP:
        Minesweeper.p("UP");

        if(r>0){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row - 1, Minesweeper.selected.col).gohere();
        }
        break;
    case DOWN:
        Minesweeper.p("DOWN");

        if(r<Minesweeper.height-1){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row + 1, Minesweeper.selected.col).gohere();
        }
        break;
    case LEFT:
        Minesweeper.p("LEFT");

        if(c>0){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col - 1).gohere();
        }
        break;
    case RIGHT:
        Minesweeper.p("RIGHT");

        if(c<Minesweeper.length-1){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col + 1).gohere();
        }
        break;
    }
    repaint();
  }
}

Solution

  • As explained in Display.setCurrent API javadocs,

    ...The setCurrent() method returns immediately, without waiting for the change to take place...

    Because of above, exceptions that may occur in calls triggered by setCurrent may (and most likely will) slip through your try-catch.

    To be able to catch and report such exceptions, one should study what calls are triggered by setCurrent (in your case, these are explained in API javadocs for Canvas, Event Delivery section), cover these by try-catch blocks where appropriate and design the appropriate way to report exceptions if these occur.

    In your case, try-catch could likely surround code in MCanvas.paint (this is where NPE likely occurs) and exceptions could be reported for example by showing appropriate screen with error message (eg Alert) by invoking setCurrent for that screen from catch block.