Skip to content

Merge properties files with the same path in the merged module instead of overwriting them - #370

Open
bjorndarri wants to merge 1 commit into
beryx:masterfrom
bjorndarri:merge-properties-files
Open

bjorndarri wants to merge 1 commit into
beryx:masterfrom
bjorndarri:merge-properties-files

Conversation

@bjorndarri

@bjorndarri bjorndarri commented Sep 13, 2026

Copy link
Copy Markdown

Hey there,

I've been working around this issue for quite a while, by using the extra-java-module-info plugin, see https://github.com/codion-is/chinook/blob/main/buildSrc/src/main/groovy/chinook.jasperreports.pdf.modules.gradle.

I figured it was time to see if Claude could help me solve this, which it did.

Below you'll find Claude's analysis and solution.


Problem

Several non-modular jars can contain a .properties file at the same path. prepareMergedJarsDir unpacks the jars one after another, so each file overwrites the one before. Only one survives, and which one depends on the order the file system lists nonmodjars.

Frameworks that find registrations through ClassLoader.getResources() silently lose entries. For example, in JasperReports 7 jasperreports and jasperreports-pdf are both automatic modules, and both ship jasperreports_extension.properties. The merged module keeps only one of them, with no warning:

  • If the pdf jar's file survives, all of core's extension registrations are lost (components, font families, the resource repository and more). Reporting then breaks in ways that are very hard to trace back to this.
  • If core's file survives, the only thing lost is the PDF handler for icon label elements (table header icons).

Which of the two happens can change with nothing more than a version upgrade. On ext4, a directory lists files in an order computed from their names and a per-filesystem seed, so the version in the jar names alone can flip the merge order. Here's what happened when the jar names were created in a fresh directory on the same disk:

JasperReports listed order file that survives
7.0.0 core, pdf pdf's (core registrations lost)
7.0.1 core, pdf pdf's (core registrations lost)
7.0.6 pdf, core core's (pdf registration lost)

Fix

  • Properties files with the same path are appended together, the way META-INF/services files have been merged since IIORegistry lookup #124. Identical files are kept once.
  • For a conflicting key, the value from the jar whose name sorts last wins, and a warning lists the keys (up to 5).
  • Jars are merged in name order, so the result is the same on every machine.
  • Content is appended byte for byte, so each file's encoding is preserved.

Compatibility

When no keys conflict, the merged file has everything the surviving file had before, plus the entries that used to be dropped. When keys conflict, the jar names now decide the winner instead of file system order, and the build logs it. To keep only one jar's file, use jarExclude("other-lib", "config.properties"), now documented in the user guide.

Tests

  • New MergedPropertiesSpec creates two jars with clashing extension.properties files, builds and runs an image, and checks that both sets of keys are visible. It fails on master.
  • Full suite: everything passes except two jpackage --type rpm tests, which fail the same way on master on machines without rpmbuild.
  • Tested on a JasperReports app, the Codion Chinook demo, without the module-info workaround: the merged jasperreports_extension.properties contains core's 11 registry factories plus the pdf one.

…d of overwriting them

When several non-modular jars contained a properties file with the same
path, each jar unpacked into the merged module overwrote the file from the
previous one, so only one of them survived. Which one depended on the
file system listing order. Frameworks that discover resources via
ClassLoader.getResources(), such as JasperReports with its
jasperreports_extension.properties, then silently lost registrations.

Properties files with the same path are now appended to each other, the
same way META-INF/services files are merged (beryx#124). Identical files are
kept once. Conflicting keys resolve to the value from the jar whose name
comes last, and a warning lists them. The jars are merged in name order,
so the result no longer depends on the file system.
@bjorndarri
bjorndarri force-pushed the merge-properties-files branch from c97b52f to c22af1b Compare September 13, 2026 11:56
@bjorndarri
bjorndarri marked this pull request as ready for review September 13, 2026 12:31
@xzel23 xzel23 self-assigned this Sep 14, 2026
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.

2 participants