From d31dff7f4cd6270d959957664c9e3ac8ee82fd95 Mon Sep 17 00:00:00 2001 From: Akos Kukucska Date: Tue, 16 Jun 2026 17:15:58 +0200 Subject: [PATCH 1/5] Mention PROV-JSON explicitly --- doc/sphinx-guides/source/user/dataset-management.rst | 2 +- src/main/java/propertyFiles/Bundle.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/sphinx-guides/source/user/dataset-management.rst b/doc/sphinx-guides/source/user/dataset-management.rst index 17eff033882..a50caa69545 100755 --- a/doc/sphinx-guides/source/user/dataset-management.rst +++ b/doc/sphinx-guides/source/user/dataset-management.rst @@ -627,7 +627,7 @@ A **Provenance File** is the preferred way of submitting provenance information Once you upload a provenance file, the Dataverse installation will need some additional information in order to accurately connect it to your data file. Once provenance file upload finishes, an input box labeled "Connect entity" will appear under the file. Provenance files contain a list of "entities", which include your data file as well as any objects associated with it (e.g. a chart, a spellchecker, etc.). You will need to tell the Dataverse installation which entity within the provenance file represents your data file. You may type the name of the entity into the box, or click the arrow next to the box and select the entity from a list of all entities in the provenance file. -For more information on entities and the contents of provenance files, see `the W3C PROV Model Primer `_. +For more information on entities and the contents of provenance files, see `the W3C PROV Model Primer `_. The uploaded file must be in JSON format as described in `the PROV-JSON specification `_. Once you've uploaded your Provenance File and connected the proper entity, you can hit the Preview button to view the raw JSON of the Provenance File. This can help you confirm that you've uploaded the right file. Be sure to double-check it, because the Provenance File will made *permanent* once it's finalized. At that point you will not be able to *replace*, *remove*, or otherwise *edit* the Provenance File. This ensures that the Provenance File maintains a stable, immutable record of the data file's history. This finalization of the Provenance File happens at different points depending on the status of your data file. If this is a brand new data file that has never been published before, then its associated Provenance File will be made permanent once you publish the dataset. If this data file *has* been published in a previous version of your dataset, then its associated Provenance File will be made permanent as soon as you upload the Provenance File and click "Save Changes" on the warning popup. diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 0825816048d..474b51281d0 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2538,9 +2538,9 @@ file.editProvenanceDialog.tip=Provenance is a record of the origin of your data file.editProvenanceDialog.uploadSuccess=Upload complete file.editProvenanceDialog.uploadError=An error occurred during upload and parsing of your provenance file. file.editProvenanceDialog.noEntitiesError=The uploaded provenance file does not contain any entities that can be related to your Data File. -file.editProvenanceDialog.invalidSchemaError=The uploaded provenance file does not comply with the W3C Provenance standard. +file.editProvenanceDialog.invalidSchemaError=The uploaded provenance file does not comply with the PROV-JSON specification. file.editProvenanceDialog.bundleFile=Provenance File -file.editProvenanceDialog.bundleFile.instructions=File must be JSON format and follow the W3C standard. +file.editProvenanceDialog.bundleFile.instructions=File must be in JSON format and follow the PROV-JSON specification. file.editProvenanceDialog.bundleFile.alreadyPublished=This Provenance File has been published and cannot be replaced or removed. file.editProvenanceDialog.bundleEntity=Data File Entity file.editProvenanceDialog.bundleEntity.placeholder=Connect entity... From 916c464cf1f09884d2b7ff6874a360d448ef54c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Kukucska?= Date: Tue, 16 Jun 2026 23:47:55 +0200 Subject: [PATCH 2/5] Display no changes have been made message after uploading non-compliant json --- .../harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java index a8b28d2d79d..82cca984cd4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java @@ -98,6 +98,7 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { if(!provUtil.isProvValid(provJsonState)) { //if uploaded prov-json does not comply with schema Logger.getLogger(ProvPopupFragmentBean.class.getName()) .log(Level.INFO, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); + provJsonState = null; removeJsonAndRelatedData(); JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); } From 6a64bf970bae084432b22bf968803aad97c28337 Mon Sep 17 00:00:00 2001 From: Akos Kukucska Date: Wed, 17 Jun 2026 13:40:41 +0200 Subject: [PATCH 3/5] Display detailed error message when user uploads json not conforming to the schema --- src/main/java/edu/harvard/iq/dataverse/api/Prov.java | 5 +++-- .../iq/dataverse/provenance/ProvInvestigator.java | 9 +++++---- .../iq/dataverse/provenance/ProvPopupFragmentBean.java | 10 ++++------ .../iq/dataverse/provenance/ProvInvestigatorTest.java | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Prov.java b/src/main/java/edu/harvard/iq/dataverse/api/Prov.java index 7f81ca20988..77221fd6500 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Prov.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Prov.java @@ -59,8 +59,9 @@ public Response addProvJson(@Context ContainerRequestContext crc, String body, @ return error(FORBIDDEN, BundleUtil.getStringFromBundle("api.prov.error.jsonUpdateNotAllowed")); } - if(!provUtil.isProvValid(body)) { - return error(BAD_REQUEST, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); + var schemaErrorMessages = provUtil.isProvValid(body); + if(!schemaErrorMessages.isEmpty()) { + return error(BAD_REQUEST, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError") + schemaErrorMessages.get()); } /*Add when we actually integrate provCpl*/ diff --git a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java index c2eecb90d9e..09da1bb2dbe 100644 --- a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java +++ b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java @@ -11,6 +11,7 @@ import java.util.Set; import java.util.logging.Logger; import jakarta.json.JsonObject; +import java.util.Optional; import org.everit.json.schema.Schema; import org.everit.json.schema.ValidationException; import org.everit.json.schema.loader.SchemaLoader; @@ -114,18 +115,18 @@ public String getPrettyJsonString(JsonObject jsonObject) { return gson.toJson(je); } - public boolean isProvValid(String jsonInput) { + public Optional isProvValid(String jsonInput) { try { schema.validate(new JSONObject(jsonInput)); // throws a ValidationException if this object is invalid } catch (ValidationException vx) { logger.info("Prov schema error : " + vx); //without classLoader is blows up in actual deployment - return false; + return Optional.of(vx.getAllMessages().toString()); } catch (Exception ex) { logger.info("Prov file error : " + ex); - return false; + return Optional.of(ex.getMessage()); } - return true; + return Optional.empty(); } //Pulled from https://www.w3.org/Submission/2013/SUBM-prov-json-20130424/schema diff --git a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java index 82cca984cd4..082b24117be 100644 --- a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java @@ -95,15 +95,13 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { provJsonState = IOUtils.toString(jsonUploadedTempFile.getInputStream()); - if(!provUtil.isProvValid(provJsonState)) { //if uploaded prov-json does not comply with schema + provUtil.isProvValid(provJsonState).ifPresentOrElse(message -> { //if uploaded prov-json does not comply with schema Logger.getLogger(ProvPopupFragmentBean.class.getName()) .log(Level.INFO, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); provJsonState = null; removeJsonAndRelatedData(); - JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); - } - - else { + JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError"), message); + }, () -> { try { generateProvJsonParsedEntities(); @@ -117,7 +115,7 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { removeJsonAndRelatedData(); JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.noEntitiesError")); } - } + }); } diff --git a/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java b/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java index f59f686a94c..f42b3487983 100644 --- a/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java @@ -68,7 +68,7 @@ public void testProvValidator() { " }\n" + "}"; - assertTrue(provUtilBean.isProvValid(validJsonString)); + assertTrue(provUtilBean.isProvValid(validJsonString).isEmpty()); //This string has the "entity" section misnamed to "entitddd" String invalidJsonString = "{\n" + @@ -102,7 +102,7 @@ public void testProvValidator() { " }\n" + "}"; - assertFalse(provUtilBean.isProvValid(invalidJsonString)); + assertFalse(provUtilBean.isProvValid(invalidJsonString).isEmpty()); } From c0ed7950cd45276db2be147f7fa05b88d56876be Mon Sep 17 00:00:00 2001 From: Akos Kukucska Date: Wed, 17 Jun 2026 16:46:21 +0200 Subject: [PATCH 4/5] Prettier error message --- .../harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java index 082b24117be..b26bc952464 100644 --- a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java @@ -100,7 +100,7 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { .log(Level.INFO, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); provJsonState = null; removeJsonAndRelatedData(); - JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError"), message); + JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError"), "Reason: " + message); }, () -> { try { generateProvJsonParsedEntities(); From 37440da09e1c30be3818117c774b8fe5c640fac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Kukucska?= Date: Tue, 23 Jun 2026 11:14:02 +0200 Subject: [PATCH 5/5] Add release note --- doc/release-notes/12468-prov-fixes.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 doc/release-notes/12468-prov-fixes.md diff --git a/doc/release-notes/12468-prov-fixes.md b/doc/release-notes/12468-prov-fixes.md new file mode 100644 index 00000000000..3235ecb7203 --- /dev/null +++ b/doc/release-notes/12468-prov-fixes.md @@ -0,0 +1,6 @@ +This release resolves two older issues about provenance files and improves the related documentation. + +When uploading a wrong provenance JSON, the user was still able to click on the preview button which caused an exception. +From now on, this button will not be available. Also, the error message about the wrong JSON now includes information about what the error actually is. + +The user guide and the GUI now explicitly state that Dataverse only accepts the PROV-JSON format.