tomcatloggingjava.util.logging

How to set a property of a customer handler of `logging.properties`


On trying to have a custom handler for Tomcat (using java.util.logging), I could not find a way to have a custom property added.

E.g. how to set a value of abc property of the handler?

# logging.properties

handlers = java.util.logging.ConsoleHandler, com.company.tomcat.JdbcHandler

.handlers = java.util.logging.ConsoleHandler, com.company.tomcat.JdbcHandler

com.company.tomcat.JdbcHandler.level = FINE
com.company.tomcat.JdbcHandler.abc=hello
package com.company.tomcat;

public class JdbcHandler extends Handler {
  private String abc;

  public void setAbc(String abc) {
    this.abc = abc;                             // this is not set
  }

  @Override
  public void publish(LogRecord record) {
    System.out.println("record " + record);     // this is called
  }
  ...
}

Solution

  • For the JDK and Tomcat the custom handler must interact with the LogManager on creation to read the parsed and loaded values. You have to set all of the properties defined by the java.util.logging.Handler class along with your new properties.

    Here is an example to get you started:

    import java.util.logging.LogManager; //Use the JUL LogManager
    
    public class JdbcHandler extends Handler {
      private String abc;
    
      public JdbcHandler() {
         final LogManager m = LogManager.getLogManager();
         final String p = getClass().getName(); //property prefix
     
         String lvl = m.getProperty(p + ".level"); //parse and set the level
         try {
            super.setLevel(lvl == null ? Level.ALL : Level.parse(lvl));
         } catch(RuntimeException failed) {
            this.reportError("Unable to set level", failed, ErrorManager.OPEN_FAILURE);
            super.setLevel(Level.ALL);
         }
    
        //TODO set other handler properties for formatter, filter, encoding, and errorManager.
    
    
         //set your property for JDK, Tomcat, etc.
         initAbc(m.getProperty(p + ".abc"));
      }
    
      //WildFly will support this way of assigning the property.
      public void setAbc(String abc) {
         initAbc(abc);
      }
    
      private void initAbc(String abc) {
        this.abc = abc;
      }
    
      @Override
      public void publish(LogRecord record) {
        if (!isLoggable(record) {
           return;
        }
    
        System.out.println("record " + record);     // this is called
      }
      public void close() {
         super.setLevel(Level.OFF);
      }
       
      public void flush() {
      }
    }
    

    It is worth keeping the public setAbc method as WildFly will use that method to assign the property.