Uri
Uri

Reputation: 89799

Can implementations of Handler.publish() throw runtime exceptions?

I have a question about java.util.logging.Handler:

Is an implementation of this abstract method allowed to throw RuntimeExceptions, or should it always report to the error manager?

The documentation does not specify, but other methods in the class explicitly state what they can throw:

public abstract void publish(LogRecord record) Publish a LogRecord. The logging request was made initially to a Logger object, which initialized the LogRecord and forwarded it here.

The Handler is responsible for formatting the message, when and if necessary. The formatting should include localization.

Parameters: record - description of the log event. A null record is silently ignored and is not published

[Link: https://docs.oracle.com/javase/7/docs/api/java/util/logging/Handler.html#publish(java.util.logging.LogRecord)]

Upvotes: 0

Views: 190

Answers (1)

jmehrens
jmehrens

Reputation: 11045

This is a case where the API spec doesn't always match the implementation. The unwritten rules from the source code seem to be:

  1. Handling of a null record can be hostile or ignored. Subclasses of StreamHandler ignore null and the MemoryHandler is null hostile. The logger never passes null to publish and JDK-8216363: NullPointerException in java.util.logging.Handler#isLoggable makes it so null records are treated as ignored.
  2. Any runtime exception thrown from isLoggable will escape the Handler. Which means any exception thrown from a filter escapes the publish method and is not trapped by the error manager. Notice how there is no enum ErrorManager.FILTER_FAILURE so that implies that the behavior is intentional.
  3. Exceptions that the publish should not throw are enumerated in the ErrorManager documentation. Most cases are formatting and writing errors.

Really publish should delegate to the error manager to determine if publish throws exceptions or not. From the Handler.setErrorManager documentation:

The ErrorManager's "error" method will be invoked if any errors occur while using this Handler.

This implies that publish should obey the behavior of the error manager which by default doesn't throw.

If you want to get an exception through Handler.reportError you have to use a sneaky throw.

public class HostileErrorManager extends ErrorManager {
    public HostileErrorManager() {
    }

    @Override
    protected void reportError(String msg, Exception ex, int code) {
        sneakyThrow(new Throwable(msg + ": " + code, ex));
    }

    @SuppressWarnings("unchecked")
    private <T extends RuntimeException> void sneakyThrow(Throwable t) throws T {
        throw (T) t;
    }
}

Upvotes: 0

Related Questions