Skip to content

Conversation

@ZiadAbdElFatah
Copy link
Contributor

@ZiadAbdElFatah ZiadAbdElFatah commented Feb 3, 2026

User description

Closes #14185

I added Update with bibliographic info from web to let the users update their bibliographies using information from various sources on web. I also edited Get bibliographic data from ... messages as requested in the issue.

Steps to test

First select an entry, it is a must, as the feature only works when selecting one entry, then from the menu select LookUp.
image
From LookUp select Update with bibliographic information from the web via entry data.
image
Finally, select the entry data you want to merge from.

Mandatory checks

  • 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 described the change in CHANGELOG.md in a way that is understandable for the average user (if change is visible to the user)
  • I checked the user documentation: Is the information available and up to date? If not, I created an issue at https://github.com/JabRef/user-documentation/issues or, even better, I submitted a pull request updating file(s) in https://github.com/JabRef/user-documentation/tree/main/en.

PR Type

Enhancement


Description

  • Added new feature to update bibliographic information from web sources

  • Implemented UpdateWithBibliographicInformationFromTheWeb action class

  • Improved menu labels for merge operations with clearer terminology

  • Updated localization strings for new and existing menu items


Diagram Walkthrough

flowchart LR
  A["User selects entry"] --> B["Lookup menu"]
  B --> C["Update with bibliographic info from web"]
  C --> D["MultiMergeEntriesView dialog"]
  D --> E["Web fetchers retrieve data"]
  E --> F["Merge results"]
Loading

File Walkthrough

Relevant files
Enhancement
StandardActions.java
Add new action and update menu labels                                       

jabgui/src/main/java/org/jabref/gui/actions/StandardActions.java

  • Added new UPDATE_WITH_WEB_INFO action enum constant
  • Updated MERGE_WITH_FETCHED_ENTRY label to use clearer terminology
  • Updated BATCH_MERGE_WITH_FETCHED_ENTRY label for consistency
+3/-2     
MainMenu.java
Integrate new web update action into menu                               

jabgui/src/main/java/org/jabref/gui/frame/MainMenu.java

  • Added import for UpdateWithBibliographicInformationFromTheWeb class
  • Integrated new menu item for updating with web bibliographic
    information
  • Connected action to the Lookup menu with proper dependencies
+5/-0     
UpdateWithBibliographicInformationFromTheWeb.java
Implement web bibliographic information update action       

jabgui/src/main/java/org/jabref/gui/mergeentries/UpdateWithBibliographicInformationFromTheWeb.java

  • New class implementing the web bibliographic update feature
  • Retrieves entry-based fetchers from WebFetchers for available sources
  • Creates MultiMergeEntriesView dialog to display original and fetched
    entries
  • Executes only when exactly one entry is selected
+66/-0   
Documentation
CHANGELOG.md
Document new web update feature                                                   

CHANGELOG.md

+1/-0     
Localization
JabRef_en.properties
Add and update localization strings                                           

jablib/src/main/resources/l10n/JabRef_en.properties

  • Added localization strings for new menu items and dialog labels
  • Added Original Entry label for merge dialog
  • Added Update with bibliographic information from the web via entry
    data label
  • Added Update with bibliographic information via identifier(s) labels
  • Reordered existing localization entries for consistency
+4/-1     

@github-actions github-actions bot added the good first issue An issue intended for project-newcomers. Varies in difficulty. label Feb 3, 2026
@ZiadAbdElFatah ZiadAbdElFatah changed the title Fix for issue 14185 Added updating bibliographic info from web Feb 3, 2026
@github-actions github-actions bot added the status: changes-required Pull requests that are not yet complete label Feb 3, 2026
@github-actions github-actions bot removed the status: changes-required Pull requests that are not yet complete label Feb 3, 2026
@ZiadAbdElFatah ZiadAbdElFatah marked this pull request as ready for review February 3, 2026 07:22
@qodo-free-for-open-source-projects
Copy link
Contributor

qodo-free-for-open-source-projects bot commented Feb 3, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🟢
🎫 #14185
🟢 Add "Update with bibliographic information from the web via entry data" menu item below
"Get bibliographic data from DOI/ISBN/... (fully automated)"
Implement logic using `org.jabref.gui.mergeentries.multiwaymerge.MultiMergeEntriesView`
Update localization from Localization.lang("Get bibliographic data from %0",
"DOI/ISBN/...") to Localization.lang("Update with bibliographic information via
identifier(s)") for both regular and fully automated options
Use MultiMergeEntriesView#addSource(String, Supplier) to add entries to merge dialog with
fetcher name as title and supplier invoking the fetcher
Read list of fetchers from `org.jabref.logic.importer.WebFetchers#getEntryBasedFetchers`
Only use first result from org.jabref.logic.importer.EntryBasedFetcher#performSearch in
merge dialog
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Silent Null Handling: The code returns null on FetcherException without logging or providing user feedback about
the failure

Referred Code
try {
    return webFetcher.performSearch(originalEntry).getFirst();
} catch (FetcherException e) {
    return null;
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Missing Input Validation: No validation of the fetched entry data before processing, which could expose the
application to malicious or malformed data

Referred Code
for (EntryBasedFetcher webFetcher : webFetchers) {
    mergedEntriesView.addSource(Localization.lang(webFetcher.getName()), () -> {
        try {
            return webFetcher.performSearch(originalEntry).getFirst();
        } catch (FetcherException e) {
            return null;
        }
    });

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-free-for-open-source-projects
Copy link
Contributor

qodo-free-for-open-source-projects bot commented Feb 3, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Consider a more controlled fetcher selection

Instead of automatically querying all web fetchers, first present a list of
available fetchers to the user and allow them to select which ones to use for
the update. This will reduce unnecessary network traffic and prevent a cluttered
UI.

Examples:

jabgui/src/main/java/org/jabref/gui/mergeentries/UpdateWithBibliographicInformationFromTheWeb.java [44-62]
        SortedSet<EntryBasedFetcher> webFetchers = WebFetchers.getEntryBasedFetchers(
                guiPreferences.getImporterPreferences(),
                guiPreferences.getImportFormatPreferences(),
                guiPreferences.getFilePreferences(),
                stateManager.getActiveDatabase().get()
        );
        MultiMergeEntriesView mergedEntriesView = new MultiMergeEntriesView(guiPreferences, taskExecutor);

        mergedEntriesView.addSource(Localization.lang("Original Entry"), () -> originalEntry);


 ... (clipped 9 lines)

Solution Walkthrough:

Before:

// In UpdateWithBibliographicInformationFromTheWeb.java
public void execute() {
    BibEntry originalEntry = stateManager.getSelectedEntries().getFirst();
    // Get ALL available fetchers
    SortedSet<EntryBasedFetcher> webFetchers = WebFetchers.getEntryBasedFetchers(...);
    
    MultiMergeEntriesView mergedEntriesView = new MultiMergeEntriesView(...);
    mergedEntriesView.addSource("Original Entry", () -> originalEntry);
    
    // Add a source for every fetcher, triggering all of them
    for (EntryBasedFetcher webFetcher : webFetchers) {
        mergedEntriesView.addSource(webFetcher.getName(), () -> {
            return webFetcher.performSearch(originalEntry).getFirst();
        });
    }
    
    dialogService.showCustomDialogAndWait(mergedEntriesView);
}

After:

// In UpdateWithBibliographicInformationFromTheWeb.java
public void execute() {
    BibEntry originalEntry = ...;
    SortedSet<EntryBasedFetcher> allFetchers = WebFetchers.getEntryBasedFetchers(...);
    
    // 1. Show a dialog to let the user select which fetchers to use
    Optional<List<EntryBasedFetcher>> selectedFetchers = dialogService.showChoiceDialog(
        "Select Sources", "Which sources do you want to query?", allFetchers
    );
    
    if (selectedFetchers.isEmpty() || selectedFetchers.get().isEmpty()) {
        return;
    }
    
    // 2. Use only the selected fetchers
    MultiMergeEntriesView mergedEntriesView = new MultiMergeEntriesView(...);
    mergedEntriesView.addSource("Original Entry", () -> originalEntry);
    for (EntryBasedFetcher webFetcher : selectedFetchers.get()) {
        mergedEntriesView.addSource(webFetcher.getName(), () -> {
            return webFetcher.performSearch(originalEntry).getFirst();
        });
    }
    dialogService.showCustomDialogAndWait(mergedEntriesView);
}
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a significant design flaw in the new feature's workflow, where querying all fetchers can degrade user experience and cause network issues; the proposed change would be a major improvement.

Medium
Possible issue
Prevent crash when fetcher finds no results
Suggestion Impact:The commit directly implements both changes suggested: replacing getFirst() with stream().findFirst().orElse(null) on line 9, and removing Localization.lang() wrapper from webFetcher.getName() on line 6

code diff:

+            mergedEntriesView.addSource(webFetcher.getName(), () -> {
                 try {
-                    return webFetcher.performSearch(originalEntry).getFirst();
+                    return webFetcher.performSearch(originalEntry).stream().findFirst().orElse(null);

To prevent a crash from an unhandled NoSuchElementException, handle cases where
webFetcher.performSearch(originalEntry) returns an empty list by using
stream().findFirst().orElse(null) instead of getFirst().

jabgui/src/main/java/org/jabref/gui/mergeentries/UpdateWithBibliographicInformationFromTheWeb.java [55-61]

-mergedEntriesView.addSource(Localization.lang(webFetcher.getName()), () -> {
+mergedEntriesView.addSource(webFetcher.getName(), () -> {
     try {
-        return webFetcher.performSearch(originalEntry).getFirst();
+        return webFetcher.performSearch(originalEntry).stream().findFirst().orElse(null);
     } catch (FetcherException e) {
         return null;
     }
 });

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a potential NoSuchElementException if the search returns no results, which would cause a crash. This is a valid and important bug fix for the new feature.

Medium
General
Remove incorrect localization call
Suggestion Impact:The commit directly implements the suggestion by removing the Localization.lang() wrapper from webFetcher.getName() on line 5. The commit also includes an unrelated change on line 9 that modifies the performSearch() call implementation.

code diff:

-            mergedEntriesView.addSource(Localization.lang(webFetcher.getName()), () -> {
+            mergedEntriesView.addSource(webFetcher.getName(), () -> {

Remove the incorrect Localization.lang() wrapper around webFetcher.getName(), as
getName() already returns a display-ready string, not a localization key.

jabgui/src/main/java/org/jabref/gui/mergeentries/UpdateWithBibliographicInformationFromTheWeb.java [55-61]

-mergedEntriesView.addSource(Localization.lang(webFetcher.getName()), () -> {
+mergedEntriesView.addSource(webFetcher.getName(), () -> {
     try {
         return webFetcher.performSearch(originalEntry).getFirst();
     } catch (FetcherException e) {
         return null;
     }
 });

[Suggestion processed]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that webFetcher.getName() returns a display name, not a localization key, and that wrapping it with Localization.lang() is incorrect. This fix is important for correct UI text rendering.

Medium
Learned
best practice
Improve user-facing string clarity

The phrase "entry data" is vague and could be clearer. Consider using "entry
metadata" or "existing entry information" to better convey that the update uses
the current entry's fields to search for bibliographic information.

jablib/src/main/resources/l10n/JabRef_en.properties [1751]

-Update\ with\ bibliographic\ information\ from\ the\ web\ via\ entry\ data=Update with bibliographic information from the web via entry data
+Update\ with\ bibliographic\ information\ from\ the\ web\ via\ entry\ metadata=Update with bibliographic information from the web via entry metadata
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Fix typographical errors in comments, documentation, changelog entries, and user-facing strings to maintain professionalism and clarity.

Low
  • Update

@github-actions github-actions bot added status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete labels Feb 3, 2026
BATCH_MERGE_WITH_FETCHED_ENTRY(Localization.lang("Get bibliographic data from %0 (fully automated)", "DOI/ISBN/...")),
MERGE_WITH_FETCHED_ENTRY(Localization.lang("Update with bibliographic information via identifier(s)")),
BATCH_MERGE_WITH_FETCHED_ENTRY(Localization.lang("Update with bibliographic information via identifier(s) (fully automated)")),
UPDATE_WITH_WEB_INFO(Localization.lang("Update with bibliographic information from the web via entry data")),
Copy link
Member

Choose a reason for hiding this comment

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

"from the web" can be removed. Not contained in the strings above.


factory.createMenuItem(
StandardActions.UPDATE_WITH_WEB_INFO,
new UpdateWithBibliographicInformationFromTheWeb(dialogService, preferences, stateManager, taskExecutor)),
Copy link
Member

Choose a reason for hiding this comment

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

Class should get better name.

JabRef users "Fetch" as base term.

UpdateWithBibliographicInformationByWebFetchers

Is a good one, isn't it?


@Override
public void execute() {
if (stateManager.getActiveDatabase().isEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

This is more a assert, because line 34 ensures that this is not executed?

}

BibEntry originalEntry = stateManager.getSelectedEntries().getFirst();
SortedSet<EntryBasedFetcher> webFetchers = WebFetchers.getEntryBasedFetchers(
Copy link
Member

Choose a reason for hiding this comment

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

Can be a Set

Sort the statements differently

  1. mergedEntriesView
  2. addSource
  3. webFetchers
  4. for loop

CHANGELOG.md Outdated
- REST-API: Added more commands (`selectentries`, `open`, `focus`). [#14855](https://github.com/JabRef/jabref/pull/14855)
- REST-API: Added the possibility to trigger the import dialog. [#14855](https://github.com/JabRef/jabref/pull/14855)
- REST-API: Allow import of supported formats via `POST http://localhost:23119/libraries/current/entries`. [#14896](https://github.com/JabRef/jabref/pull/14896)
- We added the ability to update bibliographic information from web. [#14185](https://github.com/JabRef/jabref/issues/14185)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
- We added the ability to update bibliographic information from web. [#14185](https://github.com/JabRef/jabref/issues/14185)
- We added the ability to update bibliographic information based on the existing entry data. [#14185](https://github.com/JabRef/jabref/issues/14185)

@github-actions github-actions bot added the status: changes-required Pull requests that are not yet complete label Feb 3, 2026
koppor
koppor previously approved these changes Feb 3, 2026
@koppor koppor enabled auto-merge February 3, 2026 08:25
@koppor
Copy link
Member

koppor commented Feb 3, 2026

@ZiadAbdElFatah - you can also run LocalizationConsistencyTest locally to speed up things.



  org.opentest4j.AssertionFailedError: 
  DETECTED LANGUAGE KEYS WHICH ARE NOT IN THE ENGLISH LANGUAGE FILE.
  PASTE THESE INTO THE ENGLISH LANGUAGE FILE "JabRef_en.properties".
  Search for a proper place; typically related keys are grouped together.
  If a similar key is already present, please adapt your language instead of adding load to translators by adding a new key.
  
  Update with bibliographic information via entry data=Update with bibliographic information via entry data
  
   ==> expected: <[]> but was: <[Update with bibliographic information via entry data (../jabgui/src/main/java/org/jabref/gui/actions/StandardActions.java LANG)]>
      at app/org.jabref.jablib/org.jabref.logic.l10n.LocalizationConsistencyTest.findMissingLocalizationKeys(LocalizationConsistencyTest.java:131)

@ZiadAbdElFatah
Copy link
Contributor Author

@ZiadAbdElFatah - you can also run LocalizationConsistencyTest locally to speed up things.

Ok, I forgot to edit it too.

@koppor
Copy link
Member

koppor commented Feb 3, 2026

@ZiadAbdElFatah Can you submit a PR updating https://github.com/JabRef/jabref/blob/main/docs/getting-into-the-code/guidelines-for-setting-up-a-local-workspace/intellij-12-build.md

Rework section "Final build system checks" to locate and run LocalizationConsistencyTest -- when I wrote that part, I totally forgot that LocalizationConsistencyTest is the test every developer should run.

Update Test method findMissingLocalizationKeys

auto-merge was automatically disabled February 3, 2026 08:36

Head branch was pushed to by a user without write access

@ZiadAbdElFatah
Copy link
Contributor Author

@ZiadAbdElFatah Can you submit a PR updating https://github.com/JabRef/jabref/blob/main/docs/getting-into-the-code/guidelines-for-setting-up-a-local-workspace/intellij-12-build.md

Rework section "Final build system checks" to locate and run LocalizationConsistencyTest -- when I wrote that part, I totally forgot that LocalizationConsistencyTest is the test every developer should run.

Update Test method findMissingLocalizationKeys

Sure.

@github-actions github-actions bot removed the status: changes-required Pull requests that are not yet complete label Feb 3, 2026
@ZiadAbdElFatah
Copy link
Contributor Author

Rework section "Final build system checks" to locate and run LocalizationConsistencyTest -- when I wrote that part, I totally forgot that LocalizationConsistencyTest is the test every developer should run.

Just to make things clear for me. You want me to replace the BibEntryTest example with LocalizationConsistencyTest one, or you want the two tests to be shown in the docs ?

Update Test method findMissingLocalizationKeys

And sorry, what is needed to be updated here ?

@koppor
Copy link
Member

koppor commented Feb 3, 2026

Just to make things clear for me. You want me to replace the BibEntryTest example with LocalizationConsistencyTest one, or you want the two tests to be shown in the docs ?

Thank you for asking - I meant replacing.

And sorry, what is needed to be updated here ?

Not sure if you read and understood that section? 😅 Maybe you are not using IntelliJ and just AI tooling? Then, please make the tooling transparent. See https://github.com/JabRef/jabref/blob/main/AI_USAGE_POLICY.md#example-disclosure

If this is the case, the developer documentation update might not be the right task.

Otherwise, I try to guide you: What do you think is the play button at defaultConstructor doing? What do you think, I meant by findMissingLocalizationKeys?

@koppor koppor enabled auto-merge February 3, 2026 09:00
@ZiadAbdElFatah
Copy link
Contributor Author

ZiadAbdElFatah commented Feb 3, 2026

Not sure if you read and understood that section? 😅 Maybe you are not using IntelliJ and just AI tooling? Then, please make the tooling transparent. See https://github.com/JabRef/jabref/blob/main/AI_USAGE_POLICY.md#example-disclosure

If this is the case, the developer documentation update might not be the right task.

Otherwise, I try to guide you: What do you think is the play button at defaultConstructor doing? What do you think, I meant by findMissingLocalizationKeys?

Wait, do you mean replace defaultConstructor with findMissingLocalizationKeys?

Of course I know that the play button at defaultConstructor runs the test, I just thought you want me to update the findMissingLocalizationKeys logic.

@koppor
Copy link
Member

koppor commented Feb 3, 2026

I created #15012 - you can assign yourself or keep this free for someone else.

@ZiadAbdElFatah
Copy link
Contributor Author

I created #15012 - you can assign yourself or keep this free for someone else.

Ok, I will take it, and sorry for the confliction.
And again I don't use AI 😅.

@koppor koppor added this pull request to the merge queue Feb 3, 2026
@github-actions github-actions bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Feb 3, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Feb 3, 2026
@koppor koppor merged commit 10a564c into JabRef:main Feb 3, 2026
52 checks passed
@ZiadAbdElFatah ZiadAbdElFatah deleted the fix-for-issue-14185 branch February 3, 2026 09:59
@koppor
Copy link
Member

koppor commented Feb 3, 2026

Follow-up: #15014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

good first issue An issue intended for project-newcomers. Varies in difficulty. Review effort 2/5 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.

Refine "Update with bibliographic information from the web"

2 participants