From 311dde41349495a0441a52e43ffbdad1cc5fda66 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Apr 2026 15:09:32 +0000 Subject: [PATCH] Instantiate DatasetDisambiguator in DatasetParser and guard null case The fix in #13 made DatasetDisambiguator.disambiguate() gracefully short-circuit via serverStatus when entity-fishing is unavailable, but that guard never ran: DatasetParser.disambiguator was always null, because the private constructor only takes `configuration` while the three collaborator assignments were field-to-field self-assignments (no such parameters exist on the ctor), and every caller of getInstance(...) passes `null, null, null`. A request with disambiguate=true therefore NPE'd at DatasetParser:276 before the internal short-circuit could help. - DatasetParser constructor now obtains the existing @Singleton via DatasetDisambiguator.getInstance(configuration.getDatastetConfiguration()), so #13's serverStatus guard does its job when entity-fishing is not configured. - Add a warn-once AtomicBoolean guard at the disambiguate() call site mirroring the existing gluttonWarningLogged pattern, so any future null disambiguator path also degrades to a single WARN instead of crashing the request. Result: one WARN at startup ("entity-fishing host not configured, dataset disambiguation will be skipped"), no stacktrace, requests return 200. https://claude.ai/code/session_014ZyP9j7nprZKKtJMtbWmvA --- .../grobid/core/engines/DatasetParser.java | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/grobid/core/engines/DatasetParser.java b/src/main/java/org/grobid/core/engines/DatasetParser.java index 4d75fef..1b9d192 100644 --- a/src/main/java/org/grobid/core/engines/DatasetParser.java +++ b/src/main/java/org/grobid/core/engines/DatasetParser.java @@ -79,6 +79,10 @@ public class DatasetParser extends AbstractParser { private static final java.util.concurrent.atomic.AtomicBoolean gluttonWarningLogged = new java.util.concurrent.atomic.AtomicBoolean(false); + // guard to warn only once about the disambiguator not being available + private static final java.util.concurrent.atomic.AtomicBoolean disambiguatorWarningLogged = + new java.util.concurrent.atomic.AtomicBoolean(false); + private EngineParsers parsers; private DatastetServiceConfiguration datastetConfiguration; private DataTypeClassifier dataTypeClassifier; @@ -91,6 +95,12 @@ private static void warnGluttonNotConfiguredOnce() { } } + private static void warnDisambiguatorNotAvailableOnce() { + if (disambiguatorWarningLogged.compareAndSet(false, true)) { + LOGGER.warn("Dataset disambiguator is not available, dataset disambiguation will be skipped"); + } + } + public static DatasetParser getInstance( DatastetServiceConfiguration configuration, DataTypeClassifier dataTypeClassifier, @@ -122,7 +132,7 @@ private DatasetParser(DatastetServiceConfiguration configuration) { DatastetLexicon.getInstance(); this.parsers = new EngineParsers(); this.datastetConfiguration = configuration; - this.disambiguator = disambiguator; + this.disambiguator = DatasetDisambiguator.getInstance(configuration.getDatastetConfiguration()); this.datasetContextClassifier = datasetContextClassifier; } @@ -273,22 +283,26 @@ public List> processing(List datasetDocum // disambiguation if (disambiguate) { - localDatasets = disambiguator.disambiguate(localDatasets, tokens); - - // apply existing filtering - indexToBeFiltered = new ArrayList<>(); - k = 0; - for (Dataset entity : localDatasets) { - if (entity.isFiltered()) { - indexToBeFiltered.add(Integer.valueOf(k)); + if (disambiguator != null) { + localDatasets = disambiguator.disambiguate(localDatasets, tokens); + + // apply existing filtering + indexToBeFiltered = new ArrayList<>(); + k = 0; + for (Dataset entity : localDatasets) { + if (entity.isFiltered()) { + indexToBeFiltered.add(Integer.valueOf(k)); + } + k++; } - k++; - } - if (indexToBeFiltered.size() > 0) { - for (int j = indexToBeFiltered.size() - 1; j >= 0; j--) { - localDatasets.remove(indexToBeFiltered.get(j).intValue()); + if (indexToBeFiltered.size() > 0) { + for (int j = indexToBeFiltered.size() - 1; j >= 0; j--) { + localDatasets.remove(indexToBeFiltered.get(j).intValue()); + } } + } else { + warnDisambiguatorNotAvailableOnce(); } }