简体   繁体   中英

Logging is not working from exe created with jpackage, but works when running the jar file directly

Ok, so the problem is this. I create an application and create a windows installer with jpackage. If I run the \application.exe it does not create the application log file. However if i run the \App\application.jar everything works as expected.

The system is using Java 17, Log4J2 2.19.0, slf4j 2.0.4, maven-shade-plugin 3.2.4 and edgwiz log4j-maven-shade-plugin-extensions. Without the last one logging with log4j2 on shaded applications doesn't seem to work at all.

The setup may be a bit unorthodox. My log4j.properties looks like this:

# Root logger option
log4j.rootLogger=INFO, DEBUG, file, stdout

# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=application.log
log4j.appender.file.File=${app.root}/application.log
log4j.appender.file.MaxFileSize=200KB
log4j.appender.file.MaxBackupIndex=4
log4j.appender.file.layout.ConversionPattern=%i %-6p [%-30c{1} :%4L]  %m%n
log4j.appender.file.layout=MyPatternLayoutWithQualifiedPath

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout.ConversionPattern=%i %-6p [%-30c{1} :%4L]  %m%n
log4j.appender.stdout.layout=MyPatternLayoutWithQualifiedPath

In order for the application to process the app.root system property I write that value in my main class and reload the configuration like this:

public static void main(String[] args) {
    // enable use of log4j1 properties file
    System.setProperty("log4j1.compatibility", "true");
    URL mySource = Main.class.getProtectionDomain().getCodeSource().getLocation();
    File applicationRootDirectory = new File(new File(mySource.getPath()).getParent());
    // set app root - log and setting files should reside here
    System.setProperty("app.root", applicationRootDirectory.getAbsolutePath().replaceAll("%20", " "));
    // reload log4j.properties
    LoggerContext.getContext(false).reconfigure();

// rest of Main class

Like I said. This works just fine when I run the jar file, but not when I run the exe. If I change the log4j.appender.file.File property to log4j.appender.file.File=application.log logging works basically just fine. The problem is that then the log file is created into the working directory instead of the application's root directory. The application is able to take in a file as a command line argument, so the application writes the log file in the directory of the input file which is unwanted behaviour.

The jpackage command that I use looks like this, in case it's of any help:

jpackage.exe ^
--name "the name of the app" ^
--app-version %version% ^
--vendor "vendor name" ^
--icon "icon.ico" ^
--license-file license.txt ^
--file-associations file-association.properties ^
--input input_directory ^
--main-jar application.jar ^
--main-class path.to.MainClass ^
--type exe ^
--win-per-user-install ^
--win-dir-chooser ^
--win-menu ^
--win-menu-group menuGroupName ^
--win-shortcut

The problem seems to have been with the timing of initialising any loggers. Moving

private static final Logger log = LoggerFactory.getLogger(Main.class);

from the Main class field definition to after reconfiguring the logger context solved the problem. I still don't understand why the previous solution worked when running the JAR but not when running the EXE.

So the new version of the Main class looks now like this:

// enable use of log4j1 properties file
    System.setProperty("log4j1.compatibility", "true");
    URL mySource = Main.class.getProtectionDomain().getCodeSource().getLocation();
    File applicationRootDirectory = new File(new File(mySource.getPath()).getParent());
    // set app root - log and setting files should reside here
    System.setProperty("app.root", applicationRootDirectory.getAbsolutePath().replaceAll("%20", " "));
    // reload log4j.properties
    LoggerContext.getContext(false).reconfigure();

    Logger log = LoggerFactory.getLogger(Main.class);

// Rest of Main class

Hopefully this will be helpful to someone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM