From ffd1abbdb30196c3604c8bcd60997a960a0818ef Mon Sep 17 00:00:00 2001 From: PandaMan Date: Tue, 3 Feb 2026 02:48:09 -0700 Subject: [PATCH] Fix ClassCastException in extractBookmarks endpoint (#5578) (#5604) ## Description Fixes #5578 This PR fixes a `ClassCastException` that occurs when calling `/api/v1/general/extract-bookmarks`. The method was returning `List>` directly, but Spring MVC was wrapping it in a `ResponseEntity`, causing a type mismatch. ## Changes - Changed return type from `List>` to `ResponseEntity>>` - Wrapped return values with `ResponseEntity.ok(...)` to match Spring MVC pattern - Removed `@ResponseBody` annotation as it is not needed with `ResponseEntity` ## Verification This fix follows the same pattern used in other similar endpoints: - `VerifyPDFController.verifyPDF()` returns `ResponseEntity>` - `ValidateSignatureController.validateSignature()` returns `ResponseEntity>` ## Testing The endpoint should now return a proper JSON response with the list of bookmarks instead of throwing a 500 error. --------- Co-authored-by: GitTensor Miner Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> --- .../api/EditTableOfContentsController.java | 8 +++---- .../EditTableOfContentsControllerTest.java | 24 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java index 094a19a4b..38ddc8715 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/EditTableOfContentsController.java @@ -46,18 +46,18 @@ public class EditTableOfContentsController { @Operation( summary = "Extract PDF Bookmarks", description = "Extracts bookmarks/table of contents from a PDF document as JSON.") - @ResponseBody - public List> extractBookmarks(@RequestParam("file") MultipartFile file) + public ResponseEntity>> extractBookmarks(@RequestParam("file") MultipartFile file) throws Exception { try (PDDocument document = pdfDocumentFactory.load(file)) { PDDocumentOutline outline = document.getDocumentCatalog().getDocumentOutline(); if (outline == null) { log.info("No outline/bookmarks found in PDF"); - return new ArrayList<>(); + return ResponseEntity.ok(new ArrayList<>()); } - return extractBookmarkItems(document, outline); + List> bookmarks = extractBookmarkItems(document, outline); + return ResponseEntity.ok(bookmarks); } } diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/EditTableOfContentsControllerTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/EditTableOfContentsControllerTest.java index 6317a16a3..0a0e8c4dc 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/EditTableOfContentsControllerTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/EditTableOfContentsControllerTest.java @@ -85,10 +85,12 @@ class EditTableOfContentsControllerTest { when(mockOutlineItem.getNextSibling()).thenReturn(null); // When - List> result = editTableOfContentsController.extractBookmarks(mockFile); + ResponseEntity>> response = editTableOfContentsController.extractBookmarks(mockFile); // Then - assertNotNull(result); + assertNotNull(response); + assertNotNull(response.getBody()); + List> result = response.getBody(); assertEquals(1, result.size()); Map bookmark = result.get(0); @@ -107,10 +109,12 @@ class EditTableOfContentsControllerTest { when(mockCatalog.getDocumentOutline()).thenReturn(null); // When - List> result = editTableOfContentsController.extractBookmarks(mockFile); + ResponseEntity>> response = editTableOfContentsController.extractBookmarks(mockFile); // Then - assertNotNull(result); + assertNotNull(response); + assertNotNull(response.getBody()); + List> result = response.getBody(); assertTrue(result.isEmpty()); verify(mockDocument).close(); } @@ -141,10 +145,12 @@ class EditTableOfContentsControllerTest { when(childItem.getNextSibling()).thenReturn(null); // When - List> result = editTableOfContentsController.extractBookmarks(mockFile); + ResponseEntity>> response = editTableOfContentsController.extractBookmarks(mockFile); // Then - assertNotNull(result); + assertNotNull(response); + assertNotNull(response.getBody()); + List> result = response.getBody(); assertEquals(1, result.size()); Map parentBookmark = result.get(0); @@ -177,10 +183,12 @@ class EditTableOfContentsControllerTest { when(mockOutlineItem.getNextSibling()).thenReturn(null); // When - List> result = editTableOfContentsController.extractBookmarks(mockFile); + ResponseEntity>> response = editTableOfContentsController.extractBookmarks(mockFile); // Then - assertNotNull(result); + assertNotNull(response); + assertNotNull(response.getBody()); + List> result = response.getBody(); assertEquals(1, result.size()); Map bookmark = result.get(0);