Conversation
jabsrv identified every library by its .bib path, so directory libraries - which have no .bib path, only a root directory - were invisible to the whole HTTP API: absent from the library listing and the existence-check query, and un-addressable for reading or adding entries. ServerUtils now derives a library's id from getDatabasePath() or, for a directory library, its root directory (the same identity the GUI session store uses), so listing, the batch query, entry reads, and appends all resolve it. The GUI append matcher gains the same fallback, so an append targets the open directory-library tab by its root; the entries then flow through the normal write-back into sidecars and the mirror. Standalone-server mode still serves only .bib files (adds require the GUI regardless). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Resync layer 9 (tip) of the stack (no conflicts; jabsrv ServerUtils changes still compile and ServerUtilsTest passes against upstream). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vr3E1Gg5DRU4LQDDVnhPys
The id derives from the library's location on disk in one place; endpoints that need BibTeX bytes read a directory library's mirror file, and the select command matches directory libraries too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vr3E1Gg5DRU4LQDDVnhPys
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vr3E1Gg5DRU4LQDDVnhPys
23 tasks
Fixes the CI format check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Upstream added a 0071 ADR after this stack claimed the number, so the MADR duplicate-ID check failed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Sep 7, 2026
# Conflicts: # jabsrv/src/main/java/org/jabref/http/server/command/SelectEntriesCommand.java # jabsrv/src/main/java/org/jabref/http/server/services/ServerUtils.java
Main's new library id ignored directory libraries, so in-app entry links could not find them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CajtxjcCEjS87f4hoTBTJD
31 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issues and pull requests
Phase 8 of the "directory as library" plan (
PLAN.md), stacked on #744 (base branchdirectory-convert). No issue is closed by this PR.PR Description
🤖 JabRef's REST API identified every open library by its
.bibpath, so directory libraries — which have only a root folder — were invisible: absent from the library list and the existence-check query, and unreachable for reading or adding entries. They are now identified by their root, the same identity the GUI already uses, so listing, queries, reads, and appends all resolve a directory library; added entries flow through into its sidecars and mirror. This covers GUI mode.jabref-contrib-policy:4.2:reviewed:okAnalogies
Like honey the label finally lists, the directory library was always in the pantry but unnamed on the jar; now the index reads it out. Like a chocolate assortment where one praline had no map coordinate, every piece can now be pointed to and picked. And like the moon answering to a name in the almanac, the library was always orbiting — it just needed an entry in the tables to be found and hailed.
Steps to test
GET http://localhost:23119/libraries— the directory library now appears in the list (id =<folder-name>-<hash>).POST http://localhost:23119/libraries:querywith{"queries": ["doi = \"…\""]}— matches in the directory library are returned (the browser-extension / JabMap existence check).POST http://localhost:23119/libraries/<that-id>/entrieswith a BibTeX body — the entry lands in the directory library, and a Markdown sidecar plus the.bibmirror update on disk.(No user-visible UI change, so no screenshot — the behaviour is exercised by
ServerUtilsTestand the steps above.)Live verification (running JabRef + HTTP server)
Enabled the HTTP server, opened a folder as library (
demo-library), and drove the real API:GET /libraries→ the directory library now appears:"demo-library-275b20a6"(a.bib-only listing before this PR).POST /libraries:query{"queries":["title = \"ZygOS: Achieving Low Tail Latency\""]}→{"libraryId":"demo-library-275b20a6","entryId":"zygos"}(existence check hits the directory library); a non-matching query returns[].GET /libraries/demo-library-275b20a6/entries/sidecar2026→ entry preview resolves.POST /libraries/demo-library-275b20a6/entrieswith a BibTeX body →204; the entry lands in the directory library, and write-back creates the Markdown sidecarRest2026 - Added Over the REST API.md(filename pattern applied) and updates the.bibmirror. A follow-uplibraries:querythen finds the freshly addedRest2026— the full loop closes.Known cosmetic follow-up (not fixed here): the interactive import dialog's "Library to import into" selector shows untitled for a directory library (it derives the name from the
.bibpath); the import still targets the correct directory-library context.AI usage
Claude Code (model claude-opus-4-8).
AI CHECKLIST.md walkthrough
== null/!= nullchecks.Objects.requireNonNull(...).@NullMarked— no new production classes (methods added to existingServerUtils).Optionalconsumed withmap/or/flatMap/orElse(false)— noisPresent()+get()(in fact this PR removes agetDatabasePath().get()block).StringUtil.isBlank(...)— no blank checks added.catch (Exception e).throw new RuntimeException(...).BibEntry— none built.Optional.or, streams).new Thread()— none.///) with Markdown syntax.HtmlEscaperson the 404 id message is preserved.jabsrvcovered byServerUtilsTest(listing, path resolution, context resolution, unknown id).assertEquals/assertSame, plain JUnit, no@DisplayName, no caught exceptions,@TempDir../gradlew :jabsrv:testgreen locally (full suite, no regressions);:jabsrv:compileJava+:jabgui:compileJavagreen../gradlew checkstyleMain checkstyleTestgreen for touched modules../gradlew modernizergreen../gradlew :rewriteRunapplied (no diff)../gradlew traceRequirementsgreen (req~directory-library.rest-api~1covered impl + utest).npx markdownlint-cli2green on the changed Markdown.Checklist
CHANGELOG.mddescribing the change from the user's point of view (if the change is visible to the user)🤖 Generated with Claude Code