Re: Adding a timeout to commands by wrapping + thread - suggestions?
Well, I have refined the example a bit, but have a new problem:
Exceptions from the thread...
If I wrap a command in a Runnable, it might throw a (runtime)
exception. Apparently such exceptions are only reported, but not
passed on to the calling thread.
I can catch them using an implementation of ThreadGroup that
implements uncaughtException, but re-throwing does not propagate to
the main thread either.
The code below outputs:
Caught exception - throwing a new one
Command was executed just fine
....where I had hoped it would instead die with an exception before
printing "Command was executed just fine".
-- code --
public class OnTimeoutExecuteCmd implements Command {
private Command wrappedCmd;
private Command onTimeoutCmd;
private long timeoutL;
public OnTimeoutExecuteCmd(Command wrappedCmd, Command
onTimeoutCmd, long timeoutL) {
this.wrappedCmd = wrappedCmd;
this.onTimeoutCmd = onTimeoutCmd;
this.timeoutL = timeoutL;
}
static class OverrideThreadGroup extends ThreadGroup {
public OverrideThreadGroup() {
super("Re-throw RTE");
}
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Caught exception - throwing a new
one");
throw new RuntimeException("Uncaught exception from
thread", e);
}
}
public void execute() {
Thread cmdThread = new Thread(new
CommandRunnable(wrappedCmd));
cmdThread.setUncaughtExceptionHandler(new
OverrideThreadGroup());
cmdThread.start();
try {
cmdThread.join(timeoutL);
} catch (InterruptedException e) {
throw new RuntimeException(
"I was interrupted while waiting for encapsulated command
to "
+ "join or timeout to expire");
}
if (cmdThread.isAlive()) {
onTimeoutCmd.execute();
}
try {
cmdThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(
"I was interrupted while waiting for encapsulated
command to join");
}
}
}
public class ThrowingCmd implements Command {
public void execute() {
System.out.println("Throwing now");
throw new RuntimeException("I threw in the towel");
}
}
public class TestOnTimeout {
public static void main(String[] args) {
Command ote = new OnTimeoutExecuteCmd(new ThrowingCmd(), new
HelloCmd(), 800L);
try {
ote.execute();
System.out.println("Command was executed just fine");
} catch (RuntimeException e) {
System.err.println("Runtime exception from ote");
}
}
}