Skip to content

Fix persistence upgrader - #5211

Closed
mherwege wants to merge 1 commit into
openhab:mainfrom
mherwege:persistence_upgrade
Closed

Fix persistence upgrader#5211
mherwege wants to merge 1 commit into
openhab:mainfrom
mherwege:persistence_upgrade

Conversation

@mherwege

Copy link
Copy Markdown
Contributor

Closes #5210

Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
@mherwege
mherwege requested a review from a team as a code owner December 19, 2025 16:25
@mherwege

Copy link
Copy Markdown
Contributor Author

@kaikreuzer For your review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the persistence upgrader to properly handle persistence addon configurations without explicit configuration files. The fix addresses issue #5210 by creating default persistence configurations for installed persistence addons that don't have unmanaged (file-based) configurations.

Key Changes:

  • Added logic to detect installed persistence addons and create default configurations for those without explicit .persist files
  • Modified the file creation logic to handle cases where the persistence configuration database doesn't exist
  • Implemented default strategy configurations for various persistence services (rrd4j, mapdb, inmemory, jdbc, influxdb, dynamodb)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +164 to +165
return Files.list(persistenceConfigPath).filter(configFile -> configFile.endsWith(".persist"))
.map(configFile -> configFile.getFileName().toString().replace(".persist", "")).toList();

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method does not handle the case where the persistence directory does not exist, which will cause an IOException when calling Files.list(). Consider checking if the directory exists first and returning an empty list if it doesn't, rather than propagating the exception.

Suggested change
return Files.list(persistenceConfigPath).filter(configFile -> configFile.endsWith(".persist"))
.map(configFile -> configFile.getFileName().toString().replace(".persist", "")).toList();
if (Files.notExists(persistenceConfigPath)) {
return List.of();
}
try (var stream = Files.list(persistenceConfigPath)) {
return stream.filter(configFile -> configFile.endsWith(".persist"))
.map(configFile -> configFile.getFileName().toString().replace(".persist", "")).toList();
}

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $OPENHAB_CONF/persistence path will always exist. (If it doesn't there serious things went wrong.)

configLines = Files.readAllLines(addonsConfigPath);

for (int i = 0; i < configLines.size(); i++) {
String line = Objects.requireNonNull(configLines.get(i));

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Objects.requireNonNull() call is unnecessary since configLines.get(i) will never return null for a valid list index. The call also causes confusion about the actual nullability contract. Remove this call to improve code clarity.

Copilot uses AI. Check for mistakes.
return true;
// No configuration, but persistence addons are installed and there is no unmanaged configuration for it, so
// it needs to be created
try {

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating the parent directories before creating the file is missing. If the jsondb directory doesn't exist, Files.createFile() will fail with a NoSuchFileException. Use Files.createDirectories() on the parent directory first to ensure the path exists.

Suggested change
try {
try {
Path parentDir = persistenceJsonDatabasePath.getParent();
if (parentDir != null) {
Files.createDirectories(parentDir);
}

Copilot uses AI. Check for mistakes.

@florian-h05 florian-h05 Dec 19, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parent directory will be present => jsondb directory is created by openHAB.

Comment on lines +149 to +150
for (int i = 0; i < configLines.size(); i++) {
String line = Objects.requireNonNull(configLines.get(i));

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loop variable i is declared but never used except to iterate through the list. Replace the traditional for-loop with an enhanced for-loop to improve readability and eliminate the unused loop variable.

Suggested change
for (int i = 0; i < configLines.size(); i++) {
String line = Objects.requireNonNull(configLines.get(i));
for (String lineRaw : configLines) {
String line = Objects.requireNonNull(lineRaw);

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +66
managedConfigs = managedPersistenceConfigs(installedPersistenceAddons(userdataPath),
unmanagedPersistenceConfigs(confPath));

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The confPath parameter is not null-checked before being passed to unmanagedPersistenceConfigs(). If confPath is null, this will cause a NullPointerException when the method tries to resolve the persistence path. Add a null check for confPath similar to the check for userdataPath.

Copilot uses AI. Check for mistakes.

private List<String> unmanagedPersistenceConfigs(Path configPath) throws IOException {
Path persistenceConfigPath = configPath.resolve("persistence");
return Files.list(persistenceConfigPath).filter(configFile -> configFile.endsWith(".persist"))

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Path.endsWith() method expects a Path argument, not a String. This call should use getFileName().toString().endsWith(".persist") to properly check the file extension. The current code will cause a compilation error or unexpected behavior.

Suggested change
return Files.list(persistenceConfigPath).filter(configFile -> configFile.endsWith(".persist"))
return Files.list(persistenceConfigPath)
.filter(configFile -> configFile.getFileName().toString().endsWith(".persist"))

Copilot uses AI. Check for mistakes.
Comment on lines +164 to +165
return Files.list(persistenceConfigPath).filter(configFile -> configFile.endsWith(".persist"))
.map(configFile -> configFile.getFileName().toString().replace(".persist", "")).toList();

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Files.list() operation returns a Stream that must be closed to avoid resource leaks. Wrap this operation in a try-with-resources block to ensure the stream is properly closed after use.

Copilot uses AI. Check for mistakes.
@florian-h05

Copy link
Copy Markdown
Contributor

I will take care of Copilot and the build failure.

@florian-h05

Copy link
Copy Markdown
Contributor

See #5212.

@mherwege mherwege closed this Dec 19, 2025
@mherwege

Copy link
Copy Markdown
Contributor Author

Superseeded

@mherwege
mherwege deleted the persistence_upgrade branch December 21, 2025 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PersistenceUpgrader does not consider default persistence settings, if there is no configuration so far

3 participants