Reputation: 163
I want to add a custom handler to every logger for every class of my project. I have a logging.properties file, which is read at the very beginning using:
try (InputStream in = ReportingService.class.getResourceAsStream("logging.properties")) {
LogManager.getLogManager().readConfiguration(in);
} catch (IOException ex) {
Logger.getLogger(myClass.class.getName()).log(Level.SEVERE, null, ex);
}
The logging.properties file looks like this:
handlers=java.util.logging.ConsoleHandler,myPackage.AlertHandler
.level=SEVERE
java.util.logging.ConsoleHandler.level=SEVERE
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
myPackage.AlertHandler.level=SEVERE
myPackage.AlertHandler.formatter=java.util.logging.SimpleFormatter
And myPackage.AlertHandler.java looks like this:
package myPackage;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import javafx.scene.control.Alert;
public class AlertHandler extends Handler {
@Override
public void publish(LogRecord lr) {
Alert a = new Alert(Alert.AlertType.ERROR);
a.setTitle("Exception!");
a.setHeaderText("Exception was thrown, here is the StackTrace:");
a.setContentText(getFormatter().formatMessage(lr));
Platform.runLater(()->{a.showAndWait();});
}
@Override
public void flush() {
//no real handler is open, nothing to flush
}
@Override
public void close() throws SecurityException {
//no real handler is open, nothing to close
}
}
The logging file is read without issues, as no more INFO or WARNING messages are printed to the console, only SEVERE. But my custom handler is never called, as no Alert windows are ever opened. I also tried adding the handler to the global logger, in hopes of every other logger inheriting its handlers, but it doesn't work either:
Logger.getGlobal().addHandler(new AlertHandler());
Logger.getLogger("").addHandler(new AlertHandler());
Adding the handler to a specific logger works as intended: if an error is thrown anywhere in the class, an alert window is opened with the stacktrace.
Logger.getLogger("mySecondClass").addHandler(new AlertHandler());
But I want to add this handler to EVERY logger in any class!
Upvotes: 2
Views: 7440
Reputation: 11045
But I want to add this handler to EVERY logger in any class!
If you want this handler to see all logger output then you just have to install one instance on the root logger. For example, Logger.getLogger("").addHandler(new AlertHander());
By default, child loggers are going to publish the log records to the parent handers.
The main problem is your code is going to always generate a NullPointerException because you never assigned a formatter to be used with the handler. So the call to getFormatter is going to return null and then fail.
public static void main(String[] args) {
Handler h = new Handler() {
@Override
public void publish(LogRecord record) {
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
};
System.out.println(h.getFormatter());
}
You also need to:
Make life easy and create unit tests to ensure your handler actually works before you try to use it in the wild.
Upvotes: 6