From aedc00ebca342df82611532b8cebb8da025740ac Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Fri, 30 Aug 2024 15:44:25 -0400 Subject: [PATCH 1/7] This is the fix for the bug in its entirety. #10819 --- src/main/webapp/dataset.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/dataset.xhtml b/src/main/webapp/dataset.xhtml index 4cece74b67a..0118e6decb2 100644 --- a/src/main/webapp/dataset.xhtml +++ b/src/main/webapp/dataset.xhtml @@ -86,7 +86,7 @@ - + From f3177bebb8eaf9f1dbcf49a3b0640baff5ed8ce9 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Fri, 30 Aug 2024 16:59:04 -0400 Subject: [PATCH 2/7] Making dataset thumbnail auto-selection optional (but enabled by default) #10819 --- .../edu/harvard/iq/dataverse/Dataset.java | 5 + .../dataverse/DatasetVersionServiceBean.java | 140 +++++++++--------- .../iq/dataverse/settings/FeatureFlags.java | 10 ++ 3 files changed, 86 insertions(+), 69 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataset.java b/src/main/java/edu/harvard/iq/dataverse/Dataset.java index eaf406d01bf..98766dca447 100644 --- a/src/main/java/edu/harvard/iq/dataverse/Dataset.java +++ b/src/main/java/edu/harvard/iq/dataverse/Dataset.java @@ -6,6 +6,7 @@ import edu.harvard.iq.dataverse.license.License; import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitations; import edu.harvard.iq.dataverse.makedatacount.DatasetMetrics; +import edu.harvard.iq.dataverse.settings.FeatureFlags; import java.nio.file.Path; import java.nio.file.Paths; import java.sql.Timestamp; @@ -206,6 +207,10 @@ public Dataset(boolean isHarvested) { StorageUse storageUse = new StorageUse(this); this.setStorageUse(storageUse); } + + if (FeatureFlags.DISABLE_DATASET_THUMBNAIL_AUTOSELECT.enabled()) { + this.setUseGenericThumbnail(true); + } } /** diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetVersionServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DatasetVersionServiceBean.java index 8ddc9545763..762319884b9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetVersionServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetVersionServiceBean.java @@ -9,6 +9,7 @@ import static edu.harvard.iq.dataverse.batch.jobs.importer.filesystem.FileRecordJobListener.SEP; import edu.harvard.iq.dataverse.batch.util.LoggingUtil; import edu.harvard.iq.dataverse.search.SolrSearchResult; +import edu.harvard.iq.dataverse.settings.FeatureFlags; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import edu.harvard.iq.dataverse.util.MarkupChecker; @@ -807,36 +808,11 @@ public Long getThumbnailByVersionId(Long versionId) { return null; } - Long thumbnailFileId; - - // First, let's see if there are thumbnails that have already been - // generated: - try { - thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id " - + "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o " - + "WHERE dv.id = " + versionId + " " - + "AND df.id = o.id " - + "AND fm.datasetversion_id = dv.id " - + "AND fm.datafile_id = df.id " - + "AND df.restricted = false " - + "AND df.embargo_id is null " - + "AND df.retention_id is null " - + "AND o.previewImageAvailable = true " - + "ORDER BY df.id LIMIT 1;").getSingleResult(); - } catch (Exception ex) { - thumbnailFileId = null; - } - - if (thumbnailFileId != null) { - logger.fine("DatasetVersionService,getThumbnailByVersionid(): found already generated thumbnail for version " + versionId + ": " + thumbnailFileId); - assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId); - return thumbnailFileId; - } - - if (!systemConfig.isThumbnailGenerationDisabledForImages()) { - // OK, let's try and generate an image thumbnail! - long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitImage(); + if (!FeatureFlags.DISABLE_DATASET_THUMBNAIL_AUTOSELECT.enabled()) { + Long thumbnailFileId; + // First, let's see if there are thumbnails that have already been + // generated: try { thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id " + "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o " @@ -844,63 +820,89 @@ public Long getThumbnailByVersionId(Long versionId) { + "AND df.id = o.id " + "AND fm.datasetversion_id = dv.id " + "AND fm.datafile_id = df.id " - + "AND o.previewimagefail = false " + "AND df.restricted = false " + "AND df.embargo_id is null " + "AND df.retention_id is null " - + "AND df.contenttype LIKE 'image/%' " - + "AND NOT df.contenttype = 'image/fits' " - + "AND df.filesize < " + imageThumbnailSizeLimit + " " - + "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult(); + + "AND o.previewImageAvailable = true " + + "ORDER BY df.id LIMIT 1;").getSingleResult(); } catch (Exception ex) { thumbnailFileId = null; } if (thumbnailFileId != null) { - logger.fine("obtained file id: " + thumbnailFileId); - DataFile thumbnailFile = datafileService.find(thumbnailFileId); - if (thumbnailFile != null) { - if (datafileService.isThumbnailAvailable(thumbnailFile)) { - assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId); - return thumbnailFileId; + logger.fine("DatasetVersionService,getThumbnailByVersionid(): found already generated thumbnail for version " + versionId + ": " + thumbnailFileId); + assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId); + return thumbnailFileId; + } + + if (!systemConfig.isThumbnailGenerationDisabledForImages()) { + // OK, let's try and generate an image thumbnail! + long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitImage(); + + try { + thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id " + + "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o " + + "WHERE dv.id = " + versionId + " " + + "AND df.id = o.id " + + "AND fm.datasetversion_id = dv.id " + + "AND fm.datafile_id = df.id " + + "AND o.previewimagefail = false " + + "AND df.restricted = false " + + "AND df.embargo_id is null " + + "AND df.retention_id is null " + + "AND df.contenttype LIKE 'image/%' " + + "AND NOT df.contenttype = 'image/fits' " + + "AND df.filesize < " + imageThumbnailSizeLimit + " " + + "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult(); + } catch (Exception ex) { + thumbnailFileId = null; + } + + if (thumbnailFileId != null) { + logger.fine("obtained file id: " + thumbnailFileId); + DataFile thumbnailFile = datafileService.find(thumbnailFileId); + if (thumbnailFile != null) { + if (datafileService.isThumbnailAvailable(thumbnailFile)) { + assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId); + return thumbnailFileId; + } } } } - } - // And if that didn't work, try the same thing for PDFs: - if (!systemConfig.isThumbnailGenerationDisabledForPDF()) { - // OK, let's try and generate an image thumbnail! - long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitPDF(); - try { - thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id " - + "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o " - + "WHERE dv.id = " + versionId + " " - + "AND df.id = o.id " - + "AND fm.datasetversion_id = dv.id " - + "AND fm.datafile_id = df.id " - + "AND o.previewimagefail = false " - + "AND df.restricted = false " - + "AND df.embargo_id is null " - + "AND df.retention_id is null " - + "AND df.contenttype = 'application/pdf' " - + "AND df.filesize < " + imageThumbnailSizeLimit + " " - + "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult(); - } catch (Exception ex) { - thumbnailFileId = null; - } + // And if that didn't work, try the same thing for PDFs: + if (!systemConfig.isThumbnailGenerationDisabledForPDF()) { + // OK, let's try and generate an image thumbnail! + long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitPDF(); + try { + thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id " + + "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o " + + "WHERE dv.id = " + versionId + " " + + "AND df.id = o.id " + + "AND fm.datasetversion_id = dv.id " + + "AND fm.datafile_id = df.id " + + "AND o.previewimagefail = false " + + "AND df.restricted = false " + + "AND df.embargo_id is null " + + "AND df.retention_id is null " + + "AND df.contenttype = 'application/pdf' " + + "AND df.filesize < " + imageThumbnailSizeLimit + " " + + "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult(); + } catch (Exception ex) { + thumbnailFileId = null; + } - if (thumbnailFileId != null) { - DataFile thumbnailFile = datafileService.find(thumbnailFileId); - if (thumbnailFile != null) { - if (datafileService.isThumbnailAvailable(thumbnailFile)) { - assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId); - return thumbnailFileId; + if (thumbnailFileId != null) { + DataFile thumbnailFile = datafileService.find(thumbnailFileId); + if (thumbnailFile != null) { + if (datafileService.isThumbnailAvailable(thumbnailFile)) { + assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId); + return thumbnailFileId; + } } } } } - return null; } diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/FeatureFlags.java b/src/main/java/edu/harvard/iq/dataverse/settings/FeatureFlags.java index 021977ff8c6..2bfda69247a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/FeatureFlags.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/FeatureFlags.java @@ -91,6 +91,16 @@ public enum FeatureFlags { * @since Dataverse 6.3 */ DISABLE_RETURN_TO_AUTHOR_REASON("disable-return-to-author-reason"), + /** + * This flag disables the feature that automatically selects one of the + * DataFile thumbnails in the dataset/version as the dedicated thumbnail + * for the dataset. + * + * @apiNote Raise flag by setting + * "dataverse.feature.enable-dataset-thumbnail-autoselect" + * @since Dataverse 6.4 + */ + DISABLE_DATASET_THUMBNAIL_AUTOSELECT("disable-dataset-thumbnail-autoselect"), ; final String flag; From bfcbb5dae9e8ebf64c2f9c7b2bb746aba3600646 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Tue, 3 Sep 2024 08:35:01 -0400 Subject: [PATCH 3/7] release note for the PR. #10819 --- doc/release-notes/10819-publish-thumbnail-bug.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 doc/release-notes/10819-publish-thumbnail-bug.md diff --git a/doc/release-notes/10819-publish-thumbnail-bug.md b/doc/release-notes/10819-publish-thumbnail-bug.md new file mode 100644 index 00000000000..f6b9a8d6a0c --- /dev/null +++ b/doc/release-notes/10819-publish-thumbnail-bug.md @@ -0,0 +1,4 @@ +The initial release of the Dataverse v6.3 introduced a bug where publishing would break the dataset thumbnail, which in turn broke the rendering of the parent Collection ("dataverse") page. This problem was fixed in the PR 10820. + +Additionally, the same PR made it possible to turn off the feature that automatically selects of one of the image datafiles to serve as the thumbnail of the parent dataset. An admin can turn it off by raising the feature flag `-Ddataverse.feature.disable-dataset-thumbnail-autoselect=true`. When the feature is disabled, a user can still manually pick a thumbnail image, or upload a dedicated thumbnail image. + From f3c002586c57bf34ee5eb198677cdece33b989c2 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Tue, 3 Sep 2024 13:39:02 -0400 Subject: [PATCH 4/7] added a size == 0 check to DatasetUtil.getThumbnail (copied from #10687) #10819 --- .../edu/harvard/iq/dataverse/dataset/DatasetUtil.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java b/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java index 4c84384b271..cacd409b365 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java @@ -113,13 +113,19 @@ public static List getThumbnailCandidates(Dataset dataset, boo * * @param dataset * @param datasetVersion - * @return + * @param size of the requested thumbnail + * @return DatasetThumbnail object, or null if not available */ public static DatasetThumbnail getThumbnail(Dataset dataset, DatasetVersion datasetVersion, int size) { if (dataset == null) { return null; } + if (size == 0) { + // Size 0 will fail (and set the failure flag) and should never be sent + logger.warning("getThumbnail called with size 0"); + return null; + } StorageIO dataAccess = null; try{ From ae733faa720dc9125cb5c0a1d438144b6438577a Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Tue, 3 Sep 2024 13:48:39 -0400 Subject: [PATCH 5/7] Added instructions on how to fix the files and datasets affected by the bug to the release note. #10819 --- doc/release-notes/10819-publish-thumbnail-bug.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release-notes/10819-publish-thumbnail-bug.md b/doc/release-notes/10819-publish-thumbnail-bug.md index f6b9a8d6a0c..e325eb059cd 100644 --- a/doc/release-notes/10819-publish-thumbnail-bug.md +++ b/doc/release-notes/10819-publish-thumbnail-bug.md @@ -1,4 +1,6 @@ The initial release of the Dataverse v6.3 introduced a bug where publishing would break the dataset thumbnail, which in turn broke the rendering of the parent Collection ("dataverse") page. This problem was fixed in the PR 10820. +This bug fix will prevent this from happening in the future, but does not fix any existing broken links. To restore any broken thumbnails caused by this bug, you can call the http://localhost:8080/api/admin/clearThumbnailFailureFlag API, which will clear the flag on all files (regardless of whether caused by this bug or some other problem with the file) or the http://localhost:8080/api/admin/clearThumbnailFailureFlag/id to clear the flag for individual files. Calling the former, batch API is recommended. + Additionally, the same PR made it possible to turn off the feature that automatically selects of one of the image datafiles to serve as the thumbnail of the parent dataset. An admin can turn it off by raising the feature flag `-Ddataverse.feature.disable-dataset-thumbnail-autoselect=true`. When the feature is disabled, a user can still manually pick a thumbnail image, or upload a dedicated thumbnail image. From 55f43e0d30d7759cdcbd664f87b336f945be3566 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Tue, 3 Sep 2024 13:54:12 -0400 Subject: [PATCH 6/7] 2 extra words added to the release note #10819 --- doc/release-notes/10819-publish-thumbnail-bug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/10819-publish-thumbnail-bug.md b/doc/release-notes/10819-publish-thumbnail-bug.md index e325eb059cd..46c9875a6ef 100644 --- a/doc/release-notes/10819-publish-thumbnail-bug.md +++ b/doc/release-notes/10819-publish-thumbnail-bug.md @@ -1,6 +1,6 @@ The initial release of the Dataverse v6.3 introduced a bug where publishing would break the dataset thumbnail, which in turn broke the rendering of the parent Collection ("dataverse") page. This problem was fixed in the PR 10820. -This bug fix will prevent this from happening in the future, but does not fix any existing broken links. To restore any broken thumbnails caused by this bug, you can call the http://localhost:8080/api/admin/clearThumbnailFailureFlag API, which will clear the flag on all files (regardless of whether caused by this bug or some other problem with the file) or the http://localhost:8080/api/admin/clearThumbnailFailureFlag/id to clear the flag for individual files. Calling the former, batch API is recommended. +This bug fix will prevent this from happening in the future, but does not fix any existing broken links. To restore any broken thumbnails caused by this bug, you can call the http://localhost:8080/api/admin/clearThumbnailFailureFlag API, which will attempt to clear the flag on all files (regardless of whether caused by this bug or some other problem with the file) or the http://localhost:8080/api/admin/clearThumbnailFailureFlag/id to clear the flag for individual files. Calling the former, batch API is recommended. Additionally, the same PR made it possible to turn off the feature that automatically selects of one of the image datafiles to serve as the thumbnail of the parent dataset. An admin can turn it off by raising the feature flag `-Ddataverse.feature.disable-dataset-thumbnail-autoselect=true`. When the feature is disabled, a user can still manually pick a thumbnail image, or upload a dedicated thumbnail image. From 19489b0246db6161a99fd0d9708a98f45993dfbe Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Tue, 3 Sep 2024 14:43:01 -0400 Subject: [PATCH 7/7] droped TIF from the error message in the thumbnail widgets, since it's not supported. (#10819) --- src/main/java/propertyFiles/Bundle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 4fc7ce88a7f..b53f0e84400 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -1064,7 +1064,7 @@ dataverse.theme.logo.imageFooter=Footer Image dataverse.theme.logo.image.title=The logo or image file you wish to display in the header of this dataverse. dataverse.theme.logo.image.footer=The logo or image file you wish to display in the footer of this dataverse. dataverse.theme.logo.image.uploadNewFile=Upload New File -dataverse.theme.logo.image.invalidMsg=The image could not be uploaded. Please try again with a JPG, TIF, or PNG file. +dataverse.theme.logo.image.invalidMsg=The image could not be uploaded. Please try again with a JPG or PNG file. dataverse.theme.logo.image.uploadImgFile=Upload Image File dataverse.theme.logo.format.title=The shape for the logo or image file you upload for this dataverse. dataverse.theme.logo.alignment.title=Where the logo or image should display in the header or footer. @@ -2166,7 +2166,7 @@ dataset.thumbnailsAndWidget.thumbnailImage.selectAvailable.title=Select a thumbn dataset.thumbnailsAndWidget.thumbnailImage.uploadNew=Upload New File dataset.thumbnailsAndWidget.thumbnailImage.uploadNew.title=Upload an image file as your dataset thumbnail, which will be stored separately from the data files that belong to your dataset. dataset.thumbnailsAndWidget.thumbnailImage.upload=Upload Image -dataset.thumbnailsAndWidget.thumbnailImage.upload.invalidMsg=The image could not be uploaded. Please try again with a JPG, TIF, or PNG file. +dataset.thumbnailsAndWidget.thumbnailImage.upload.invalidMsg=The image could not be uploaded. Please try again with a JPG or PNG file. dataset.thumbnailsAndWidget.thumbnailImage.alt=Thumbnail image selected for dataset dataset.thumbnailsAndWidget.success=Dataset thumbnail updated. dataset.thumbnailsAndWidget.removeThumbnail=Remove Thumbnail