Matthew McPeak
Matthew McPeak

Reputation: 17944

Deploy a writable properties file in jpackaged Java application

I have a Java client application that I am going to package as a stand-alone application using jpackage.

But the application has a Properties file which must be both read and written to by the application. My initial attempts to do this run in the IDE, but when I package the application it fails because the location of the properties file is actually located inside the packaged .jar.

Is there a canonical / "right" way to maintain a writable properties file with a jpackaged application?

Upvotes: 0

Views: 258

Answers (1)

VGR
VGR

Reputation: 44414

Package default settings in your application. At runtime, store a writable copy of them in a known file location, typically in a directory that is a descendant of the user’s home directory:

String applicationName = /* ... */;

Properties configuration;

String os = System.getProperty("os.name");
String home = System.getProperty("user.home");

Path localSettingsDir;
if (os.contains("Mac")) {
    localSettingsDir = Path.of(home, "Library", "Application Support");
} else if (os.contains("Windows")) {
    String appData = System.getenv("APPDATA");
    if (appData != null) {
        localSettingsDir = Path.of(appData);
    } else {
        localSettingsDir = Path.of(home, "AppData", "Roaming");
    }
} else {
    String configHome = System.getenv("XDG_CONFIG_HOME");
    if (configHome != null) {
        localSettingsDir = Path.of(configHome);
        if (!localSettingsDir.isAbsolute()) {
            localSettingsDir = Path.of(home, ".config");
        }
    } else {
        localSettingsDir = Path.of(home, ".config");
    }
}

Path localSettings = localSettingsDir.resolve(
    Path.of(applicationName, "config.properties"));

configuration = new Properties();
if (!Files.exists(localSettings)) {
    Files.createDirectories(localSettings.getParent());
    try (InputStream defaultSettings =
        MyApplication.class.getResourceAsStream("config.properties")) {

        Files.copy(defaultSettings, localSettings);
    }
}

try (Reader settingsSource = Files.newBufferedReader(localSettings)) {
    configuration.load(settingsSource);
}

For more details on determining a system’s application configuration directory, see Find place for dedicated application folder.

Upvotes: 3

Related Questions