Skip to content

Import & Add PDF Upload Endpoint#14907

Closed
sonthien22501 wants to merge 0 commit intoJabRef:mainfrom
sonthien22501:pr-14855-latest
Closed

Import & Add PDF Upload Endpoint#14907
sonthien22501 wants to merge 0 commit intoJabRef:mainfrom
sonthien22501:pr-14855-latest

Conversation

@sonthien22501
Copy link
Copy Markdown
Contributor

@sonthien22501 sonthien22501 commented Jan 23, 2026

PR Description

Sumary

This PR fixes critical UnsatisfiedDependencyException errors preventing the HTTP Import API from working (as introduced in #14855) and implements the missing PDF Upload endpoint (POST .../files) required for the Researcher Cockpit extension.

  1. Fix Dependency Injection (Server.java)

    • Problem: The server crashed with HTTP 500 because UiMessageHandler and CliPreferences were bound using Named Bindings ("uimessagehandler"), but Resources injected them without names. Additionally, addOneConstant(obj) bound concrete classes (e.g., JabRefFrame) instead of Interfaces (UiMessageHandler), causing HK2 resolution failures.
    • Fix: Switched to AbstractBinder to explicitly bind instances to their Interface contracts (bind(instance).to(Interface.class)).
  2. Fix CLI Server Crash (EntriesResource.java)

    • Problem: EntriesResource requires UiMessageHandler. When running in CLI mode (headless), this handler is null. This caused the CLI server to crash on startup during dependency resolution because of the mandatory field injection.
    • Fix: Implemented Lazy Injection using ServiceLocator. The resource now retrieves the handler only when addBibtex is called, allowing the server to start safely in CLI mode (throwing a graceful 500 if invoked without UI).
  1. Implement PDF Upload (EntryResource.java)
    • Feature: Added POST /libraries/{id}/entries/{entryId}/files endpoint.
    • Implementation:
      • Accepts application/pdf InputStream.
      • Uses LinkedFileHandler logic to generate standard filenames (e.g., Author - Title.pdf).
      • Includes robust fallback logic to save files to the .bib directory if no specific "Linked Files" directory is configured in preferences.

Steps to test

 * Run ./gradlew clean :jabsrv:assemble              
 * Run ./gradlew :jabgui:run 
 * Enable HTTP in Jabref Preference
 * Create test file "test.bib" (@article{test_entry_2026, title={Test Entry from Curl}, author={Tester}, year={2026}}) and "test.pdf"  
 * Run curl -v -X POST -H "Content-Type: application/x-bibtex" --data-binary {dir}/test.bib http://localhost:23119/libraries/current/entries to test Import        
 * Run curl -v -X POST -H "Content-Type: application/pdf" --data-binary {dir}/test.pdf http://localhost:23119/libraries/current/entries/Tester2026/files to test PDF Upload
Screenshot 2026-01-23 at 18 02 44 Screenshot 2026-01-23 at 18 03 16

Mandatory checks

@github-actions github-actions bot added the status: changes-required Pull requests that are not yet complete label Jan 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

Copy link
Copy Markdown
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

The issue causing the 500 was different - see #14930

I found out by using the debugger, breakpoints, and following the call hierarchy. The main cause was that the wrong http server constructor was called - without uiMessageHandler.


Please submit Implement PDF Upload (EntryResource.java) as separate PR (based on upstreammain`)

Reason: For each use case a different PR

In case you want to have all updates integrated in your IDE, use GitButler - and maybe magic-merge-commit

CHANGELOG.md Outdated
Comment on lines +18 to +19
- REST-API: Added more commands (`selectentries`, `open`, `focus`).
- REST-API: Added the possibility to trigger the import dialog
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.

Something is wrong with this PR - maybe not a clean base on upstream/main?

Maybe try:

  • Ensure everything is committed
  • gitk --all& (to start gitk to have the commit IDs ready if something goes wrong)
  • git merge upstream/main (to merge the latest upstream changes)
  • git reset upstream/main (to discard all commits and start a fresh commit)
  • git gui (to craft a new commit. Do NOT commit the changes in the submodule. Try to revert these changes using "Commit" -> "Revert Changes")
  • Create a new commit using git gui (maybe other git tooling you use)
  • git push -f (to overwrite the changes also in this PR)

Copy link
Copy Markdown
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

(see above)

Comment on lines +153 to +160
// Fallback: Use the directory where the bib file is located
if (targetDirOpt.isEmpty()) {
targetDirOpt = databaseContext.getDatabasePath().map(java.nio.file.Path::getParent);
}

if (targetDirOpt.isEmpty()) {
throw new BadRequestException("Library must be saved or have a file directory configured to attach files.");
}
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.

No fallback - return bad request if there is no dir.

When did you experience this? Mayge at a new, unsaved library.

if (Files.exists(finalPath)) {
String name = com.google.common.io.Files.getNameWithoutExtension(suggestedName);
String ext = com.google.common.io.Files.getFileExtension(suggestedName);
finalPath = targetDir.resolve(name + "_" + System.currentTimeMillis() + "." + ext);
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.

Can't one write directly to this file?

Comment on lines +179 to +180
String name = com.google.common.io.Files.getNameWithoutExtension(suggestedName);
String ext = com.google.common.io.Files.getFileExtension(suggestedName);
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.

Please useorg.jabref.logic.util.io.FileUtil#getFileExtension(java.nio.file.Path) and org.jabref.logic.util.io.FileUtil#getBaseName(java.lang.String)

Comment on lines +196 to +202
FilesToServe filesToServe = serviceLocator.getService(FilesToServe.class);
SrvStateManager srvStateManager = serviceLocator.getService(SrvStateManager.class);
CliPreferences preferences = serviceLocator.getService(CliPreferences.class);

if (filesToServe == null || srvStateManager == null || preferences == null) {
throw new IOException("Required services not found in ServiceLocator");
}
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.

All these changes are not necessary AFAIK.

Comment on lines -76 to -77
// Required for CLI only
// GUI uses HttpServerManager
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.

Strong hint that this is AI generated and the resulting code not reviewed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is because I have the issue with the http 500 and I ask AI about it. But I am sure that I have reverted everything, pull the latest code for importing and enabling http in Jabref Application. It worked then I implemented the PDF Uploading Endpoints with the same concept of Import. Maybe i have committed no-needed code in Server.java and I don't remember about it. Sorry

@sonthien22501
Copy link
Copy Markdown
Contributor Author

I have checked that the Import function works without error 500
I follow the EntriesResource.java to implement PDF Uploading in EntryResource.java
New PR: #14942

@koppor koppor reopened this Jan 29, 2026
@koppor koppor changed the title Import & Add PDF Upload Endpoint from (PR #14855) Import & Add PDF Upload Endpoint Jan 29, 2026
@jabref-machine
Copy link
Copy Markdown
Collaborator

Note that your PR will not be reviewed/accepted until you have gone through the mandatory checks in the description and marked each of them them exactly in the format of [x] (done), [ ] (not done yet) or [/] (not applicable). Please adhere to our pull request template.

if (Files.exists(finalPath)) {
String name = com.google.common.io.Files.getNameWithoutExtension(suggestedName);
String ext = com.google.common.io.Files.getFileExtension(suggestedName);
finalPath = targetDir.resolve(name + "_" + System.currentTimeMillis() + "." + ext);
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.

Please do not use a timestamp for the filename. This is not user friendly. Just keep the original name.

@koppor
Copy link
Copy Markdown
Member

koppor commented Jan 29, 2026

In the exchange today, we decided to go on with this PR.

This comment needs to be resolved: https://github.com/JabRef/jabref/pull/14907/changes#r2730600414

This comment needs to be resolved: https://github.com/JabRef/jabref/pull/14907/changes#r2743826996

This one needs more thought and can be skipped for now to move forward: https://github.com/JabRef/jabref/pull/14907/changes#r2730594969

@koppor
Copy link
Copy Markdown
Member

koppor commented Jan 29, 2026

I merged upstream/main. Please use git pull to update your branch.

@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.

@sonthien22501 sonthien22501 deleted the pr-14855-latest branch January 30, 2026 12:09
@koppor
Copy link
Copy Markdown
Member

koppor commented Feb 2, 2026

Follow-up: #14963

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

Labels

status: changes-required Pull requests that are not yet complete

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants