Skip to content

Fix duplicate finder progress counter incrementing on empty queue polls#15781

Merged
Siedlerchr merged 1 commit into
JabRef:mainfrom
raphaelterencio:fix/duplicate-finder-counter-11848-v3
May 19, 2026
Merged

Fix duplicate finder progress counter incrementing on empty queue polls#15781
Siedlerchr merged 1 commit into
JabRef:mainfrom
raphaelterencio:fix/duplicate-finder-counter-11848-v3

Conversation

@raphaelterencio

Copy link
Copy Markdown
Contributor

Related issues and pull requests

Closes #11848

PR Description

The duplicate finder progress counter in DuplicateSearch.java was being incremented on every iteration of the polling loop, including iterations where the queue was empty and no pair was shown to the user. This fix moves the increment to the point where a duplicate pair is actually presented to the user, and corrects the title binding to use the observable property directly instead of a static captured value

image

Steps to test

  1. Open a library with several duplicate entries (at least 50+ total entries so the search takes a moment)
  2. Go to Quality -> Find Duplicates
  3. Observe the counter in the dialog title, it should now start at (1/N) and increment sequentially as you resolve each pair
  4. Before this fix, the counter would start at a number higher than 1 (e.g. 5/10) due to empty queue poll iterations being counted
Captura de tela 2026-05-19 001640 (Screenshots: before fix showing 5/10 on first dialog, after fix showing 1/10) Captura de tela 2026-05-19 010900

AI usage

Claude Code (claude-sonnet-4-6) -> Only used to find the source of the problem and a way to correct it

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • If AI tools were used, I disclosed them in the "AI usage" section and reviewed, understood, and take full ownership of all AI-generated code
  • I manually tested my changes in running JabRef (always required)
  • [/] I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description (if change is visible to the user)
  • I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • [/] I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository

@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Fix duplicate finder progress counter incrementing logic

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Fixed progress counter incrementing on empty queue polls
• Counter now increments only when duplicate pair shown
• Corrected title binding to use observable property
• Updated changelog with fix description
Diagram
flowchart LR
  A["Empty queue poll"] -->|Before| B["Counter incremented"]
  C["Duplicate pair found"] -->|Before| B
  A -->|After| D["Counter unchanged"]
  C -->|After| E["Counter incremented"]
  E --> F["Dialog title updated"]
  B --> G["Incorrect progress display"]
  F --> H["Correct progress display"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java 🐞 Bug fix +3/-3

Move counter increment to pair presentation point

• Moved progress counter increment from polling loop to duplicate pair presentation
• Counter now increments only when a duplicate pair is shown to user
• Fixed title binding to use duplicateProgress observable property instead of static getValue()
 call
• Ensures counter starts at 1 and increments sequentially as pairs are resolved

jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java


2. CHANGELOG.md 📝 Documentation +1/-0

Document duplicate finder counter fix

• Added entry documenting fix for duplicate finder progress counter issue
• References issue #11848
• Describes the fix in user-friendly language

CHANGELOG.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0)

Context used

Grey Divider


Action required

1. duplicateProgress.set() off FX thread 📘 Rule violation ☼ Reliability
Description
duplicateProgress (a JavaFX property bound to the dialog title) is incremented inside
verifyDuplicates(), which is executed via a BackgroundTask and therefore may run off the JavaFX
Application Thread. Updating an FX-observed property from the worker thread can notify
bindings/listeners on the wrong thread, causing intermittent UI exceptions, crashes, or undefined
behavior.
Code

jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[154]

+                duplicateProgress.set(duplicateProgress.getValue() + 1);
Evidence
PR Compliance ID 47 requires JavaFX UI reads/writes to occur on the JavaFX Application Thread, yet
the PR adds/increments duplicateProgress.set(...) inside verifyDuplicates() while
verifyDuplicates() is run through BackgroundTask.wrap(this::verifyDuplicates) (whose call()
executes on a background thread in UiTaskExecutor). Since askResolveStrategy() binds
dialog.titleProperty() to observe duplicateProgress, any increment performed before switching to
the FX thread can trigger title updates (and other listener notifications) from the worker thread;
the surrounding codebase pattern also shows UI-related updates are normally marshaled to the FX
thread (e.g., duplicateTotal updates via runAndWaitInJavaFXThread).

jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[98-101]
jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[151-156]
jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[95-101]
jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[122-156]
jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[162-166]
jabgui/src/main/java/org/jabref/gui/util/UiTaskExecutor.java[108-110]
jabgui/src/main/java/org/jabref/gui/util/UiTaskExecutor.java[186-190]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`duplicateProgress` is a JavaFX `SimpleIntegerProperty` that is bound into the dialog title, but it is currently incremented inside `verifyDuplicates()` while that method runs via `BackgroundTask` on a worker thread. Because bindings/listeners may be notified on the worker thread, this can drive JavaFX UI updates off the FX Application Thread, leading to unstable UI behavior or runtime exceptions.

## Issue Context
- `verifyDuplicates()` is executed via `BackgroundTask.wrap(this::verifyDuplicates)`, and in JabRef’s `UiTaskExecutor` the task `call()` runs on a background thread.
- `askResolveStrategy()` binds `dialog.titleProperty()` to `duplicateProgress`, making `duplicateProgress` a UI-observed property.
- The codebase already marshals UI-related changes to the JavaFX thread (e.g., `duplicateTotal` is updated via `runAndWaitInJavaFXThread`).

## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[98-101]
- jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[122-166]
- jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[151-156]

## Suggested approach
Move the `duplicateProgress` increment so it always executes on the JavaFX Application Thread (e.g., into the existing `UiTaskExecutor.runAndWaitInJavaFXThread(...)` block around `askResolveStrategy()` or by wrapping just the increment in `UiTaskExecutor.runInJavaFXThread(...)`), and remove the worker-thread `duplicateProgress.set(...)` call.

Optionally, ensure the dialog title binding is unbound after the dialog is closed to avoid keeping bindings/listeners alive longer than needed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@raphaelterencio

raphaelterencio commented May 19, 2026

Copy link
Copy Markdown
Contributor Author

Sorry for the confusion and the noise on this PR, I know that the auto-merge was already enabled,but I had some problems. During the process of addressing review feedback, I accidentally performed a force push which invalidated the previous approval and caused CI failures related to that. While trying to fix the resulting issues, the CHANGELOG entry ended up duplicated multiple times due to repeated rebasing, and the CI kept failing. To avoid further complications on an already messy history, I decided to close this PR and open a clean one from scratch with a single commit on top of upstream/main. The fix itself is unchanged, same two line logic correction

DuplicateResolverType resolverType = askAboutExact ? DuplicateResolverType.DUPLICATE_SEARCH_WITH_EXACT : DuplicateResolverType.DUPLICATE_SEARCH;

// Increment only when a pair is actually shown to the user
duplicateProgress.set(duplicateProgress.getValue() + 1);

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.

Action required

1. duplicateprogress.set() off fx thread 📘 Rule violation ☼ Reliability

duplicateProgress (a JavaFX property bound to the dialog title) is incremented inside
verifyDuplicates(), which is executed via a BackgroundTask and therefore may run off the JavaFX
Application Thread. Updating an FX-observed property from the worker thread can notify
bindings/listeners on the wrong thread, causing intermittent UI exceptions, crashes, or undefined
behavior.
Agent Prompt
## Issue description
`duplicateProgress` is a JavaFX `SimpleIntegerProperty` that is bound into the dialog title, but it is currently incremented inside `verifyDuplicates()` while that method runs via `BackgroundTask` on a worker thread. Because bindings/listeners may be notified on the worker thread, this can drive JavaFX UI updates off the FX Application Thread, leading to unstable UI behavior or runtime exceptions.

## Issue Context
- `verifyDuplicates()` is executed via `BackgroundTask.wrap(this::verifyDuplicates)`, and in JabRef’s `UiTaskExecutor` the task `call()` runs on a background thread.
- `askResolveStrategy()` binds `dialog.titleProperty()` to `duplicateProgress`, making `duplicateProgress` a UI-observed property.
- The codebase already marshals UI-related changes to the JavaFX thread (e.g., `duplicateTotal` is updated via `runAndWaitInJavaFXThread`).

## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[98-101]
- jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[122-166]
- jabgui/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java[151-156]

## Suggested approach
Move the `duplicateProgress` increment so it always executes on the JavaFX Application Thread (e.g., into the existing `UiTaskExecutor.runAndWaitInJavaFXThread(...)` block around `askResolveStrategy()` or by wrapping just the increment in `UiTaskExecutor.runInJavaFXThread(...)`), and remove the worker-thread `duplicateProgress.set(...)` call.

Optionally, ensure the dialog title binding is unbound after the dialog is closed to avoid keeping bindings/listeners alive longer than needed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@Siedlerchr Siedlerchr enabled auto-merge May 19, 2026 21:24
@koppor koppor added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label May 19, 2026
@Siedlerchr Siedlerchr added this pull request to the merge queue May 19, 2026
Merged via the queue into JabRef:main with commit 5f25cbb May 19, 2026
115 of 124 checks passed
Siedlerchr added a commit that referenced this pull request May 20, 2026
* upstream/main:
  Update PULL_REQUEST_TEMPLATE.md (#15788)
  New Crowdin updates (#15787)
  Update heylogs to 0.18.0 and use github-actions format (#15786)
  Grand refactoring of the AI features (#15688)
  Chore(deps): Bump com.fasterxml:aalto-xml in /versions (#15782)
  Chore(deps): Bump org.junit:junit-bom from 6.0.3 to 6.1.0 in /versions (#15783)
  Fix default value for unwanted characters (#15743)
  Fix runner tag
  Fix runner for JBang (PR)
  Fix duplicate finder progress counter incrementing on empty queue polls (#15781)
  Refine JabKit CLI: positional input argument and check command group (#15759)
  Ignore exception in unregisterListener to prevent exception (#15761)
  Fix wrong usage of "key" (#15779)
  Fix Hayagriva export to nest identifiers under serial-number (#15750)
f0restron07 pushed a commit to f0restron07/jabref that referenced this pull request May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Compliance violation status: no-bot-comments status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duplicate finder counter makes no sense

3 participants