Reputation: 3828
Is there no way (regardless of how "hacky" it is) to detect when Java's System.err
has been written to in order to be able to execute logic if and when this happens? — I'm currently working with a custom subclass of Thread
(let's call it SwallowingThread
) which swallows a number of exceptions in its implementation of Thread.run()
in a manner similar to the following code:
public final class SwallowingThread extends Thread {
...
@Override
public void run() {
ServerSocket socket = new ServerSocket(80, 100);
try {
Socket connected = socket.accept();
// Do stuff with socket here
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In my code, however, I want to be able to handle cases of UnknownHostException
and IOException
which occur while using an instance of SwallowingThread
; Is there no way to detect that this catching and printing to standard error after it has occured? — I had originally tried writing a UncaughtExceptionHandler
to do this only to find out that it isn't catching the exceptions because they were swallowed rather than simply being e.g. wrapped in a RuntimeException
and thrown onward.
Of course, a "better" way of solving this problem is to re-write the logic for the class, but is there no quick-and-dirty way of solving this issue without having to touch SwallowingThread
?
Upvotes: 2
Views: 1257
Reputation: 17534
As several persons already suggested, you may go with a custom PrintStream
.
It will replace the standard error stream but also encapsulate it and call it when needed.
Since the exceptions and stack traces are what you are interested in, overriding print(String)
should be enough (println(String)
already calls this method + newLine()
).
The stream could look like that :
import java.io.PrintStream;
public class CustomPrintStream extends PrintStream {
public CustomPrintStream(final PrintStream out) {
super(out);
}
@Override
public void print(final String s) {
super.print(s);
// some String is written to the error stream, Do something !
}
}
You would use it that way, at the beginning of your application, just call
System.setErr(new CustomPrintStream(System.err));
Upvotes: 3
Reputation: 1018
You can implement your own class (I call it DelegatingErrorPrintStream) derived from PrintStream which notifies you if there's new output, and then delegates to System.err And now you can set YOUR DelegatingErrorPrintStream as output stream for System.err using System.setErr(err);
Full example including usage:
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
public class ErrorNotifierExample {
private static final class ErrorDelegatingPrintStream extends PrintStream {
public ErrorDelegatingPrintStream(PrintStream defaultErr)
throws FileNotFoundException, UnsupportedEncodingException {
super(defaultErr);
}
@Override
public void print(boolean b) {
super.print(b);
notifyListener(b);
}
@Override
public void print(char c) {
super.print(c);
notifyListener(c);
}
@Override
public void print(int i) {
super.print(i);
notifyListener(i);
}
@Override
public void print(long l) {
super.print(l);
notifyListener(l);
}
@Override
public void print(float f) {
super.print(f);
notifyListener(f);
}
@Override
public void print(double d) {
super.print(d);
notifyListener(d);
}
@Override
public void print(char[] s) {
super.print(s);
notifyListener(s);
}
@Override
public void print(String s) {
super.print(s);
notifyListener(s);
}
@Override
public void print(Object obj) {
super.print(obj);
notifyListener(obj);
}
@Override
public PrintStream append(CharSequence csq, int start, int end) {
notifyListener(csq); // TODO will need some special handling
return super.append(csq, start, end);
}
private void notifyListener(Object string) {
// TODO implement your handling here. System.out printing is just an
// example.
System.out.println(String.valueOf(string));
}
}
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
ErrorDelegatingPrintStream errReplacement = new ErrorDelegatingPrintStream(System.err);
System.setErr(errReplacement);
System.err.println("TEST01");
throw new RuntimeException("just a test output for ERROR handling");
}
}
Upvotes: 5