diff --git a/data/demo.mv.db b/data/demo.mv.db index fc0aa3faa25be93c4aff51e81753594e79c11751..58a471a1a46f01613223ede85826889a448b65b6 100644 Binary files a/data/demo.mv.db and b/data/demo.mv.db differ diff --git a/src/main/java/com/dre0059/articleprocessor/GrobidClient.java b/src/main/java/com/dre0059/articleprocessor/GrobidClient.java index 7b58e41e4fb2e40d432509c7d20b60eb0c677cfc..5910d36de9ca348ebf06cab621213686dbe15a44 100644 --- a/src/main/java/com/dre0059/articleprocessor/GrobidClient.java +++ b/src/main/java/com/dre0059/articleprocessor/GrobidClient.java @@ -7,9 +7,11 @@ import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.core.io.FileSystemResource; +import org.springframework.web.reactive.function.client.WebClientRequestException; import reactor.core.publisher.Mono; import java.io.File; +import java.net.ConnectException; @Service @@ -25,18 +27,30 @@ public class GrobidClient { // get METADATA of the file public String processHeader(File pdfFile){ // Mono - vráti jeden string, vĂ˝sledok je JSON - return webClient.post() - .uri("/api/processHeaderDocument") - .contentType(MediaType.MULTIPART_FORM_DATA) - .body(BodyInserters.fromMultipartData("input", new FileSystemResource(pdfFile))) - .attribute("consolidateHeader", 1) // MoĹľnosĹĄ na zjednotenie hlaviÄŤky - .attribute("includeRawAffiliations", 1) // PrĂpadne pridaĹĄ ÄŹalšie parametre, ak Grobid podporuje takĂ©to rozšĂrenie - .attribute("includeRawCopyrights", 1) // PrĂpadne pridaĹĄ ÄŹalšie parametre, ak Grobid podporuje takĂ©to rozšĂrenie - //.attribute("includeReferences", 1) // MoĹľnosĹĄ pridaĹĄ aj referencie priamo do hlaviÄŤky - .retrieve() - .bodyToMono(String.class) - .block(); // returns String instead of Mono<String> - } + try { + + return webClient.post() + .uri("/api/processHeaderDocument") + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData("input", new FileSystemResource(pdfFile))) + .attribute("consolidateHeader", 1) // MoĹľnosĹĄ na zjednotenie hlaviÄŤky + .attribute("includeRawAffiliations", 1) // PrĂpadne pridaĹĄ ÄŹalšie parametre, ak Grobid podporuje takĂ©to rozšĂrenie + .attribute("includeRawCopyrights", 1) // PrĂpadne pridaĹĄ ÄŹalšie parametre, ak Grobid podporuje takĂ©to rozšĂrenie + //.attribute("includeReferences", 1) // MoĹľnosĹĄ pridaĹĄ aj referencie priamo do hlaviÄŤky + .retrieve() + .onStatus(status -> status.isError(), clientResponse -> + clientResponse.bodyToMono(String.class) + .defaultIfEmpty("Unknown error from GROBID server - failed to process HEADER") + .flatMap(errorBody -> Mono.error(new RuntimeException("GROBID server error: " + errorBody))) + ) + .bodyToMono(String.class) + .block(); // returns String instead of Mono<String> + } catch (WebClientRequestException e) { + throw new RuntimeException("Failed to connect to GROBID server: " + e.getMessage(), e); + } catch (Exception e) { + throw new RuntimeException("Error communicating with GROBID server: " + e.getMessage(), e); + } + } public String processFullMetadata(File pdfFile) { return webClient.post() @@ -51,13 +65,24 @@ public class GrobidClient { // spracuje REFERENCIE z PDF public String processReferences(File pdfFile){ - return webClient.post() - .uri("/api/processReferences") - .contentType(MediaType.MULTIPART_FORM_DATA) - .body(BodyInserters.fromMultipartData("input", new FileSystemResource(pdfFile))) - .retrieve() - .bodyToMono(String.class) - .block(); + try { + return webClient.post() + .uri("/api/processReferences") + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData("input", new FileSystemResource(pdfFile))) + .retrieve() + .onStatus(status -> status.isError(), clientResponse -> + clientResponse.bodyToMono(String.class) + .defaultIfEmpty("Unknown error from GROBID server - failed to process REFERENCES") + .flatMap(errorBody -> Mono.error(new RuntimeException("GROBID server error: " + errorBody))) + ) + .bodyToMono(String.class) + .block(); + } catch (WebClientRequestException e) { + throw new RuntimeException("Failed to connect to GROBID server: " + e.getMessage(), e); + } catch (Exception e) { + throw new RuntimeException("Error communicating with GROBID server: " + e.getMessage(), e); + } } } \ No newline at end of file diff --git a/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java b/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java index c3fd1d863ecd9d52b02797d22c9b171c97ae9588..8d463d729a1e739546dd0ae2fbca8dc3c55cb983 100644 --- a/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java +++ b/src/main/java/com/dre0059/articleprocessor/controller/FileUploadController.java @@ -2,20 +2,17 @@ package com.dre0059.articleprocessor.controller; import com.dre0059.articleprocessor.GrobidClient; import com.dre0059.articleprocessor.model.Dokument; -import com.dre0059.articleprocessor.model.Tag; -import com.dre0059.articleprocessor.repository.TagRepository; import com.dre0059.articleprocessor.service.CategoryService; import com.dre0059.articleprocessor.service.HeaderService; import com.dre0059.articleprocessor.service.ReferenceService; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -72,7 +69,16 @@ public class FileUploadController { } //System.out.println("File written to temporary location. "); - String header = grobidClient.processHeader(tmpFile); + String header; + try { + header = grobidClient.processHeader(tmpFile); + } catch (RuntimeException e) { + if (e.getMessage().contains("Failed to connect to GROBID server")) { + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) + .body(Map.of("error", "Cannot connect to GROBID server")); + } + return ResponseEntity.internalServerError().body(Map.of("error", "GROBID processing error")); + } //System.out.println("GROBID Header processed: " + header); String references = grobidClient.processReferences(tmpFile); @@ -81,10 +87,17 @@ public class FileUploadController { Dokument savedDocument = headerService.processHeader(header, categoryId, tags, tmpFile); //System.out.println("Header saved to database."); + // dokument already exists + if(savedDocument == null) { + if (tmpFile.exists()) tmpFile.delete(); + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(Map.of("error", "Document already exists in the database")); + } + referenceService.extractReferences(references); //System.out.println("References extracted.."); - tmpFile.delete(); + if (tmpFile.exists()) tmpFile.delete(); Map<String, Object> response = new HashMap<>(); response.put("id", savedDocument.getId()); diff --git a/src/main/resources/templates/upload.html b/src/main/resources/templates/upload.html index 4170ed7fb8a47ef34e990da932887278bcb58e0b..42973c2f259dad8b41c3f8cb327f3375418ba56a 100644 --- a/src/main/resources/templates/upload.html +++ b/src/main/resources/templates/upload.html @@ -148,7 +148,7 @@ cache: true }, createTag: function (params) { - let term = $.trim(params.term.toLowerCase()); // đź‘ vytváraj lowercase tagy + let term = $.trim(params.term.toLowerCase()); // lowercase tagy if (term === '') { return null; @@ -192,7 +192,7 @@ const formData = new FormData(); formData.append("file", fileInput); formData.append("categoryId", category); - formData.append("tags",tags); // DĂ´leĹľitĂ©! + formData.append("tags", tags); // DĂ´leĹľitĂ©! $.ajax({ url: "/api/upload", @@ -210,13 +210,24 @@ alert("Upload completed, but no ID returned."); } }, - error: function() { + error: function(xhr, status, error) { // <-- tu sĂş teraz 3 argumenty! clearInterval(dotInterval); $('#processing-message').hide(); - alert("Error processing PDF."); + + let errorMessage = "Error while processing PDF."; + + // Tu bezpeÄŤne kontrolujeme odpoveÄŹ + if (xhr.responseJSON && xhr.responseJSON.error) { + errorMessage = xhr.responseJSON.error; + } else if (xhr.responseText) { + errorMessage = xhr.responseText; + } + + alert(errorMessage); // zobrazĂ chybu } }); }); + </script>