Search code examples
javawhitespacewindows-subsystem-for-linuxjava.util.logging

java.util.logging breaks on wsl with spaces in paths


I have a small Java project setup with the 3 files Foo.java, logging.properties and build.gradle as below.

In the Foo.java, I run the below

package foo;
import java.util.logging.Logger;

public class Foo {

    public static void  main(String[] args) {
        var file = Foo.class.getClassLoader().getResource("logging.properties").getFile();
        System.setProperty("java.util.logging.config.file", file);
        var l = Logger.getLogger(Foo.class.getName());
        l.info("HOLA!");
    }
}

and the corresponding properties file is simply

handlers=java.util.logging.ConsoleHandler

The gradle file is simple enough.

apply plugin: 'java'

sourceCompatibility = 11
targetCompatibility = 11

they are structured like below

foo/
├─ src/
│  ├─ java/
│  │  ├─ main/
│  │  │  ├─ foo/
│  │  │  │  ├─ Foo.java
│  ├─ resources/
│  │  ├─ logging.properties
├─ build.gradle

to run the code, I write

gradle build
java -cp build/classes/java/main/:build/resources/main/ foo.Foo

Now to my problem: if I locate root in /mnt/c/Users/Ludvig/Desktop/logtest/root, all works well. If I change the path be /mnt/c/Users/Ludvig/Desktop/log test/root I get no log output. Notice that it fails silently! So the program runs, but the logging fails. What to do?


Solution

  • You can convert URL to File by doing:

    package foo;
    import java.util.logging.Logger;
    import java.io.File;
    
    public class Foo {
    
        public static void  main(String[] args) throws Exception {
            var file = new File(Foo.class.getResource("logging.properties").toURI());
            System.setProperty("java.util.logging.config.file", file.getCanonicalPath());
            var l = Logger.getLogger(Foo.class.getName());
            l.info("HOLA!");
        }
    }
    

    You don't have to convert the URL to a file. The LogManager supports InputStream objects as long as your code explicitly reconfigures the loggers before any other code is run.

    package foo;
    import java.util.logging.Logger;
    
    private static final Logger logger;
        static {
            try (InputStream in = Foo.class.getClassLoader().getResourceAsStream("logging.properties")) {
               //LogManager.getLogManager().readConfiguration(in); //JDK 8
               LogManager.getLogManager().updateConfiguration(in, (k) -> ((o, n) -> n)); //JDK 9+
            } catch(IOException ioe) {
               throw new ExceptionInInitializerError(ioe);
            }
         logger = Logger.getLogger(Foo.class.getName());
    }
    
    public class Foo {
    
        public static void  main(String[] args) throws Exception {
            logger.info("HOLA!");
        }
    }