Search code examples
javajvmsystem-properties

System.setProperty for logger not modified after static method call in another class


I have a program in which I need to set the logger formatting, but since there are several entry points (I don't control all of them) I want to place the System.setProperty() call in the constructor of the class where all of the entry points converge.

Main class

public static void main(String[] args) throws Exception {
    String foo = "bar";
    String baz = "boo";
    static final String FORMATTER_CONFIG = "%1$tb %1$td, %1$tY %1$tr %4$s: %5$s%n";

    SomeClass sc = new SomeClass();
    sc.method1(foo);
    sc.method2(baz);

    try {
        SomeOtherClass soc = SomeOtherClass.newInstance();
    } catch (Exception e) {;
    }
    // Next line will update the property of the logging formatter for this instance
    System.setProperty("java.util.logging.SimpleFormatter.format", FORMATTER_CONFIG);
    MyThirdClass mtc = MyThirdClass.getStaticMethod(foo, baz);

    Logger logger = Logger.getLogger("myProject.main");
    Handler h = new FileHandler("LogHere.txt");
    h.setFormatter(new SimpleFormatter());
    logger.addHandler(h);
    logger.setLevel(Level.INFO);
    logger.info("Info level log");
    logger.fine("Fine level log");
    logger.finer("Finer level log");
    logger.finest("Finest level log");
}

Constructor of MyThirdClass:

public MyThirdClass() throws SecurityException {
    this.classStaticVar = EntirelyDifferentClass.getVar();
    logger = Logger.getLogger(this.getClass().getName());
    Handler h = null;
    try {
        h = new FileHandler("MTC_LogHere.txt");
    } catch (IOException ex) {
        logger.warning("Failed to initialize custom FileHandler for MTC_LogHere.txt");
    }
    h.setFormatter(new SimpleFormatter());
    logger.addHandler(h);
    logger.setLevel(Level.INFO);
}

I want to put the call to System.setProperty as the first line of the constructor in MyThirdClass (before the call to EntirelyDifferentClass) but when I do the logging is not formatted according to the custom rules. If I leave it right where it is, the line before the call to MyThirdClass in the main method, it works as intended. Note that I've also tried putting the code block for System.setProperty in the getStaticMethod() method.

I understand that the system.properties are all static variables, so I have to believe that whatever is happening in the JVM during the method call to MyThirdClass.getStaticMethod is locking in the static properties before I can change it.

  1. Am I understanding what is happening in the JVM correctly?
  2. Since I don't control all entry points in the actual production version of this program, and I also don't control the compile settings nor can I issue a -Djava line command to set the properties that way (which I've also verified will work) I need to be able to do this programmatically in MyThirdClass. What am I missing/overlooking, or am I just out of luck?

Solution

  • This answer was originally edited into the question above by the OP Bryan, I have posted this here and requested him to do so himself:

    For anyone wanting to know the answer, I added a static block at the class level of MyThirdClass:

      protected static Logger logger = null;
    
      static {
          System.setProperty("java.util.logging.SimpleFormatter.format", FORMATTER_CONFIG);
          logger = Logger.getLogger("myProject.MyThirdClass");
          Handler h = null;
          try {
             h = new FileHandler("LogHere.txt");
          }
          catch (Exception ex) {
              System.out.println("Exception");
          }
          h.setFormatter(new SimpleFormatter());
          logger.addHandler(h);
          logger.setLevel(Constants.LOGGING_LEVEL);
      }