0

I want the Java ConsoleHandler to use System.out instead of err, so I implemented my own handler that calls the protected void setOutputStream(OutputStream) of the parent StreamHandler class:

public class ConsoleHandler extends java.util.logging.ConsoleHandler {

    public ConsoleHandler() {

        setOutputStream(System.out); // or System.err
        setLevel(Level.ALL);
    }
}

I remove the default console logger from and add my own to the root logger:

Logger l = Logger.getLogger("");
for (Handler h : l.getHandlers())
    l.removeHandler(h);
l.addHandler(new ConsoleHandler());

System.out.println("OUT");
System.err.println("ERR");

Problem: "OUT" is always printed, but "ERR" never, independent of the output stream I set in my ConsoleHandler constructor.

Andi
  • 457
  • 3
  • 19

1 Answers1

1

The stacktrace (printed to System.err) is not printed any more, without my changes it is printed as usual

This is because setOutputStream closes the previously assigned System.err stream. This is a known issue filed under JDK-4827381: Invoking ConsoleHandler.setOutputStream(...) closes System.err. What should have happened with that bug report is that the StreamHandler.setOutputStream should call Handler.close instead of flushAndClose().

You need to wrap the existing System.err stream with a proxy that doesn't allow the stream to be closed. Or just extend StreamHandler and use the constructor that takes an OutputStream.

public class OutConsoleHandler extends StreamHandler {

   public OutConsoleHandler() {
        super(System.out, new SimpleFormatter());
        //TODO: Read level,filter,encoding from LogManager.
   }

    @Override
    public void publish(LogRecord record) {
        super.publish(record);
        super.flush();
    }

    @Override
    public void close() {
        super.flush();
    }
}
jmehrens
  • 10,580
  • 1
  • 38
  • 47
  • This was my guess. How is it possible that `System.err.close()` does not throw an UnsupportedOperationException? This shouldn't be allowed in Java land.I accept your solution while pointing to the JDK ConsoleHandler implementation which is a bit more complex: https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/logging/ConsoleHandler.java – Andi Aug 01 '18 at 21:12
  • @Andi If you are using the `logging.properties` then you have to roll your own. However, if you are using code and you control how things start up then you [use the existing console handler](https://stackoverflow.com/questions/194165/how-do-i-change-java-logging-console-output-from-std-err-to-std-out/35919737#35919737). – jmehrens Aug 02 '18 at 03:01
  • How is it possible? I guess because there are conceivable use-cases where you would really want System.err.close() to close the stream. – Stephen C Aug 02 '18 at 03:01