Skip to content

PDF import keep merge dialog#15287

Merged
Siedlerchr merged 1 commit into
JabRef:mainfrom
faneeshh:fix-15127
Mar 8, 2026
Merged

PDF import keep merge dialog#15287
Siedlerchr merged 1 commit into
JabRef:mainfrom
faneeshh:fix-15127

Conversation

@faneeshh

@faneeshh faneeshh commented Mar 7, 2026

Copy link
Copy Markdown
Collaborator

Related issues and pull requests

Closes #15127

PR Description

When dragging and dropping a PDF into JabRef, the merge dialog was closing instantly before the user could interact with it which resulted in entries being created with only the filename and no metadata or DOI. The root cause was that MultiMergeEntriesView was configured with ACTIVE_COLUMNS_MINIMUM = 2 meaning the dialog would automatically close if fewer than 2 PDF importers returned metadata. For many valid PDFs only 1 importer like XMP succeeds, so the dialog was dismissing itself immediately.

This PR changes ACTIVE_COLUMNS_MINIMUM from 2 to 1 so the merge dialog stays open as long as at least one importer returns data. Only when zero sources succeed does it close and fall back to creating an empty entry with just the filename.

Note: The NullPointerException in Notifications.java that was also triggered during PDF import has already been fixed in main via hotfix #15288 by @calixtus.

Steps to test

  1. Download the open access PDF for DOI 10.1063/5.0266356. Here's the link https://pubs.aip.org/aip/apl/article/126/12/120401/3340873/Ultra-wide-bandgap-semiconductors-for-extreme
image
  1. Run JabRef and drag the PDF onto the application
15127.Test.mp4
  1. The merge dialog should appear and stay open
  2. After clicking Merge Entries the resulting entry should contain real metadata including a clean DOI (10.1063/5.0266356) with no .org/ prefix or trailing dot.
  3. No Null Pointer Exception occurs as well as stated in Fixed nullable eventhandlers #15288

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • 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 PDF import NPE and keep merge dialog open with single importer

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Replace Optional.of() with Optional.ofNullable() to safely handle null event handlers
• Wrap event handlers in try/finally blocks to guarantee finishTask() execution
• Use Objects.toString() to prevent null task titles from propagating to JavaFX
• Reduce ACTIVE_COLUMNS_MINIMUM from 2 to 1 to keep merge dialog open with single importer
Diagram
flowchart LR
  A["PDF Drag & Drop"] --> B["TaskNotification Created"]
  B --> C["Event Handlers Registered"]
  C --> D["Optional.ofNullable()"]
  D --> E["Try/Finally Blocks"]
  E --> F["finishTask() Guaranteed"]
  C --> G["UiTaskExecutor.getJavaFXTask()"]
  G --> H["Objects.toString() for Title"]
  H --> I["No Null Propagation"]
  B --> J["MultiMergeEntriesView"]
  J --> K["ACTIVE_COLUMNS_MINIMUM = 1"]
  K --> L["Dialog Stays Open"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/Notifications.java 🐞 Bug fix +18/-9

Prevent NPE and guarantee finishTask execution

• Changed Optional.of() to Optional.ofNullable() for three event handlers to safely handle null
 values
• Wrapped each event handler invocation in try/finally blocks to ensure finishTask() always
 executes
• Prevents NullPointerException when event handlers are not set before task registration

jabgui/src/main/java/org/jabref/gui/Notifications.java


2. jabgui/src/main/java/org/jabref/gui/mergeentries/multiwaymerge/MultiMergeEntriesView.java 🐞 Bug fix +1/-1

Allow merge dialog with single importer result

• Changed ACTIVE_COLUMNS_MINIMUM constant from 2 to 1
• Allows merge dialog to remain open when only one PDF importer returns metadata
• Prevents automatic dialog closure for single-source imports like XMP-only results

jabgui/src/main/java/org/jabref/gui/mergeentries/multiwaymerge/MultiMergeEntriesView.java


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

Handle null task titles safely in JavaFX

• Replaced direct task.titleProperty().get() with `Objects.toString(task.titleProperty().get(),
 "")`
• Converts null task titles to empty strings instead of propagating null to JavaFX Task
• Prevents null values from reaching the JavaFX task title property

jabgui/src/main/java/org/jabref/gui/util/UiTaskExecutor.java


View more (1)
4. CHANGELOG.md 📝 Documentation +1/-0

Document PDF import and merge dialog fixes

• Added entry documenting the fix for PDF import NPE and merge dialog behavior
• References issues #15127 and #15283

CHANGELOG.md


Grey Divider

Qodo Logo

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

qodo-free-for-open-source-projects Bot commented Mar 7, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

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

Grey Divider


Action required

1. Changelog link/wording incorrect📘 Rule violation ✓ Correctness
Description
The new CHANGELOG entry is developer-focused/grammatically incorrect and references #15127 but
links to a different issue (/issues/15283), which can mislead users. This does not meet the
project requirements for user-facing, professional CHANGELOG text with correct references.
Code

CHANGELOG.md[31]

+- We fixed PDF import and prevent NPE in TaskNotification and keep merge dialog open when only one importer succeeds. [#15127](https://github.com/JabRef/jabref/issues/15283)
Evidence
PR Compliance ID 22 requires CHANGELOG entries to be end-user facing, and PR Compliance ID 24
requires user-facing text to be professional/precise and include correct references. The added line
contains technical terms (NPE, TaskNotification) with ungrammatical phrasing (prevent instead
of prevented) and a mismatched issue link target.

AGENTS.md
CHANGELOG.md[31-31]
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
The new `CHANGELOG.md` entry is not user-focused (mentions `NPE`/`TaskNotification`), contains grammatical issues, and the displayed issue reference `#15127` links to `/issues/15283`.
## Issue Context
Compliance requires CHANGELOG entries to be understandable to average users and user-facing text to be precise and correctly referenced.
## Fix Focus Areas
- CHANGELOG.md[31-31]

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



Remediation recommended

2. Handler exceptions bubble up 🐞 Bug ⛯ Reliability
Description
TaskNotification now guarantees UI cleanup via finally, but exceptions thrown by preserved
onSucceeded/onFailed/onCancelled handlers are still uncaught and can propagate on the JavaFX UI
thread, potentially triggering uncaught-exception dialogs/log spam.
Code

jabgui/src/main/java/org/jabref/gui/Notifications.java[R76-99]

+            Optional<EventHandler<WorkerStateEvent>> onSucceeded = Optional.ofNullable(task.getOnSucceeded());
           task.setOnSucceeded(event -> {
-                onSucceeded.ifPresent(handler -> handler.handle(event));
-                finishTask();
+                try {
+                    onSucceeded.ifPresent(handler -> handler.handle(event));
+                } finally {
+                    finishTask();
+                }
           });
-            Optional<EventHandler<WorkerStateEvent>> onFailed = Optional.of(task.getOnFailed());
+            Optional<EventHandler<WorkerStateEvent>> onFailed = Optional.ofNullable(task.getOnFailed());
           task.setOnFailed(event -> {
-                onFailed.ifPresent(handler -> handler.handle(event));
-                finishTask();
+                try {
+                    onFailed.ifPresent(handler -> handler.handle(event));
+                } finally {
+                    finishTask();
+                }
           });
-            Optional<EventHandler<WorkerStateEvent>> onCancelled = Optional.of(task.getOnCancelled());
+            Optional<EventHandler<WorkerStateEvent>> onCancelled = Optional.ofNullable(task.getOnCancelled());
           task.setOnCancelled(event -> {
-                onCancelled.ifPresent(handler -> handler.handle(event));
-                finishTask();
+                try {
+                    onCancelled.ifPresent(handler -> handler.handle(event));
+                } finally {
+                    finishTask();
+                }
           });
Evidence
The preserved handlers are invoked without a catch block, and project docs explicitly state these
handlers run on the FX UI thread; thus, any exception thrown in them will occur on the UI thread.

jabgui/src/main/java/org/jabref/gui/Notifications.java[75-99]
jabgui/src/main/java/org/jabref/gui/util/UiTaskExecutor.java[94-96]

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

## Issue description
`TaskNotification` ensures `finishTask()` runs, but exceptions thrown by preserved task event handlers still propagate on the JavaFX UI thread.
### Issue Context
This is not a regression from this PR (handlers could throw before too), but since this code is explicitly managing notification UI state, it’s a good choke point to prevent handler exceptions from surfacing as UI-thread uncaught exceptions.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/Notifications.java[75-99]
- jabgui/src/main/java/org/jabref/gui/Notifications.java[102-108]

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


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@github-actions github-actions Bot added the good second issue Issues that involve a tour of two or three interweaved components in JabRef label Mar 7, 2026
@faneeshh

faneeshh commented Mar 7, 2026

Copy link
Copy Markdown
Collaborator Author

This works for any invalid PDF file as well. It doesn't give the NPE anymore.

Comment thread CHANGELOG.md Outdated
@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 7, 2026
@testlens-app

This comment has been minimized.

@ThiloteE

ThiloteE commented Mar 7, 2026

Copy link
Copy Markdown
Member

@calixtus merged your solution with the nullable eventhandlers as a hotfix at #15288. Current main doesn't trigger the exceptions in the GUI anymore, but they still show up in the log. I will try to get rid of that broken PDF. For the user it would be nice to know which PDF in particular triggers the exceptions. Maybe something for the integrity check.

@testlens-app

This comment has been minimized.

Comment thread CHANGELOG.md Outdated

### Fixed

- We fixed PDF import and prevent NPE in TaskNotification and keep merge dialog open when only one importer succeeds. [#15283](https://github.com/JabRef/jabref/issues/15283)

@calixtus calixtus Mar 7, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Task notification was introduced after last release, so no changelog for that issue.
Don't mix separate issues in one pr and one changelog entry. Create a new pr for the merge dialog.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Task notification was introduced after last release, so no changelog for that issue. Don't mix separate issues in one pr and one changelog entry. Create a new pr for the merge dialog.

Alright I'll strip out the Notifications.java and UiTaskExecutor.java changes since those are now covered by #15288 and open a separate focused PR for just the MultiMergeEntriesView.java change that fixes #15127.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I ended up rebasing the code onto main and just stripped out the changes that were already covered by #15288. I can create a new PR as well if that would be cleaner but I did force push the changes onto this branch and I'll update PR description as well. Let me know however works best for you to review.

@testlens-app

testlens-app Bot commented Mar 7, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: bd7c8dd
▶️ Tests: 7635 executed
⚪️ Checks: 75/75 completed


Learn more about TestLens at testlens.app.

@jabref-machine

Copy link
Copy Markdown
Collaborator

Hey, we noticed that you force-pushed your changes. Force pushing is a bad practice when working together on a project (mainly because it is not supported well by GitHub itself). Commits are lost and comments on commits lose their context, thus making it harder to review changes.

When the pull request is getting integrated into main, all commits will be squashed anyway. Thus, your individual commit history will not be visible in main.

In future, please avoid that. For now, you can continue working.

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Mar 7, 2026
@Siedlerchr

Copy link
Copy Markdown
Member

Can you please adapt the title of the PR?

@Siedlerchr Siedlerchr changed the title PDF import and prevent NPE in TaskNotification and keep merge dialog PDF import keep merge dialog Mar 8, 2026
@Siedlerchr Siedlerchr added this pull request to the merge queue Mar 8, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Mar 8, 2026
Merged via the queue into JabRef:main with commit 68e16aa Mar 8, 2026
72 of 75 checks passed
Siedlerchr added a commit to statxc/jabref that referenced this pull request Mar 10, 2026
* upstream/main: (59 commits)
  Fix 15000 identifier (JabRef#15286)
  Chore(deps): Bump dev.langchain4j:langchain4j-bom in /versions (JabRef#15305)
  Supress JavaFX VirtualFlow Info log noise for large libraries (10k+). (JabRef#15298)
  Chore(deps): Bump commons-logging:commons-logging in /versions (JabRef#15304)
  Fix merge dialog closing immediately when only one PDF importer returns metadata (JabRef#15127) (JabRef#15287)
  Fixed nullable eventhandlers (JabRef#15288)
  New Crowdin updates (JabRef#15285)
  Fix the ESC key for GlobalSearchResultDialog (JabRef#15259)
  Remove jbang plugin banner (JabRef#15282)
  Chore(deps): Bump org.apache.httpcomponents.core5:httpcore5 in /versions (JabRef#15281)
  Udpate to latest gradle master (JabRef#15279)
  Migrate to GemsFX Notifications (JabRef#14762)
  Chore(deps): Bump JetBrains/junie-github-action from 0 to 1 (JabRef#15272)
  Chore(deps): Bump docker/setup-qemu-action from 3 to 4 (JabRef#15269)
  Feature/citation count dropdown (JabRef#15216)
  Update dependency org.apache.maven.plugins:maven-resources-plugin to v3.5.0 (JabRef#15275)
  Chore(deps): Bump jablib/src/main/resources/csl-styles (JabRef#15273)
  Fix more security
  Fix pr_body leakage
  Chore: add dependency-management.md (JabRef#15278)
  ...
FynnianB pushed a commit to FynnianB/jabref that referenced this pull request Mar 14, 2026
FynnianB pushed a commit to FynnianB/jabref that referenced this pull request Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

good second issue Issues that involve a tour of two or three interweaved components in JabRef status: changes-required Pull requests that are not yet complete 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.

DOI is parsed from PDF with preceeding .org/

5 participants