2

I've made an abstract Thread that processes some streams in its run() method. I'd like to be able to have the subclasses handle these exceptions rather than the abstract parent class, but I don't know the most elegant way to do that. Right now, I'm doing something like this:

import org.apache.logging.log4j; // (I use log4j for logging)

public interface Loggable {
     Logger getLogger();
}

public abstract class ParentThread extends Thread implements Loggable {
    private final static Logger logger =
      Logger.getLogger(ParentThread.class); // Logger with no Appenders

    @Override
    public void run() {
        try {
            // Do some stuff that throws exceptions
            doAbstractStuff();
        } catch (SomeSortOfException ex) {
            getLogger().error("Oh noes!", ex);
        } catch (SomeOtherException ex) {
            getLogger().error("The sky is falling!", ex);
        }
    }

    public Logger getLogger() { return logger; }

    protected abstract void doAbstractStuff();
}

public class ChildThread extends ParentThread {

    @Override
    public Logger getLogger() { /* return a logger that I actually use */ }

    @Override
    public void doAbstractStuff() { /* Implementation */ }
}

I guess I should mention that the ChildThread is actually an inner class of my main form, and that its logger belongs to that form.

Another approach I thought of was to have an

abstract void handleException(Exception ex);

in ParentThread, but then I'm not able to handle individual exceptions from the ChildThread.

Wind Owl
  • 23
  • 1
  • 4
  • what do you mean "not able to handle individual exceptions from the ChildThread"? – skaffman Apr 23 '11 at 09:34
  • Well, I'd have to guess at what the exception is based on its class or by parsing its messages, rather than being able to just handle exactly what caused it. – Wind Owl Apr 23 '11 at 09:39

3 Answers3

0

Well there's no difference between

} catch (SomeSortOfException ex) {
    getLogger().error("Oh noes!", ex);
} catch (SomeOtherException ex) {
    getLogger().error("The sky is falling!", ex);
}

and

if (ex instanceof SomeSortOfException) {
    getLogger().error("Oh noes!", ex);
} else if (ex instanceof SomeOtherException) {
    getLogger().error("The sky is falling!", ex);
}

although the latter may require some casting.

Your abstract handleException(Exception ex) idea is sound, I'd go with that. I'd be inclined to not make it abstract, though, and define a sensible default implementation in ParentThread, and allow ChildThread to override it if required.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • There's no difference, assuming I'm only using one try block. But what if I have, say, a write method and a close method in separate try blocks? – Wind Owl Apr 23 '11 at 09:49
0

Your first solution seems conceptually wrong to me: mixing application-specific error-handling with generic logging.

Your second idea (the callback) seems a better solution and offers the possibility of abstracting away the implementation-specific exceptions for custom events, for example:

public abstract class Parent {

    public void run() {

        InputStream in = null;    
        try {
            in = new URL("bladiebla").openConnection().getInputStream();    
            String text = // ...read text from InputStream     
            if (text == null || text.length() == 0) {
                handleMyEvent(new NoInputEvent());
                return;
            }           
            doWork(text);
        } catch (MalformedURLException e) {
            handleMyEvent(new MyEvent(e));                
        } catch (IOException e) {
            handleMyEvent(new MyEvent(e));
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch(IOException e) {
                    handleMyEvent(e);
                }
            }
        }
    }            

    abstract void doWork(String text);

    abstract void handleMyEvent(MyEvent myEvent);
}

public class MyEvent {
    private Exception exception;
    public MyEvent() {}
    public MyEvent(Exception exception) {//set it}
}

public class NoInputEvent extends MyEvent {        
}
Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60
  • Ah, I like the idea of creating an event class to handle it, although I think I'll make it a nested `protected static` class. Thanks. – Wind Owl Apr 23 '11 at 11:20
0

Why is your base class logging exceptions ? Why not use what the platform provide Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) and let it do whatever instead of mixing logging w/ your do-stuff component.

mP.
  • 18,002
  • 10
  • 71
  • 105
  • I actually do set `Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)` much higher up in the chain. But you still can't even *throw* unhandled exceptions from `Runnable.run()`. – Wind Owl Apr 23 '11 at 11:21
  • Your getting your terms wrong, you can throw any unchecked exception and it will escape a Runnable. There are ways to throw Exceptions using Thread.stop(Throwable). – mP. Apr 24 '11 at 04:08