Skip to content

Commit 92d3839

Browse files
authored
A Fix for the Dataset Thumbnail Bug on Publish, 10819 (#10820)
* This is the fix for the bug in its entirety. #10819 * Making dataset thumbnail auto-selection optional (but enabled by default) #10819 * release note for the PR. #10819 * added a size == 0 check to DatasetUtil.getThumbnail (copied from #10687) #10819 * Added instructions on how to fix the files and datasets affected by the bug to the release note. #10819 * 2 extra words added to the release note #10819 * droped TIF from the error message in the thumbnail widgets, since it's not supported. (#10819)
1 parent 025b55d commit 92d3839

File tree

7 files changed

+102
-73
lines changed

7 files changed

+102
-73
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
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.
2+
3+
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.
4+
5+
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 `<jvm-options>-Ddataverse.feature.disable-dataset-thumbnail-autoselect=true</jvm-options>`. When the feature is disabled, a user can still manually pick a thumbnail image, or upload a dedicated thumbnail image.
6+

src/main/java/edu/harvard/iq/dataverse/Dataset.java

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import edu.harvard.iq.dataverse.license.License;
77
import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitations;
88
import edu.harvard.iq.dataverse.makedatacount.DatasetMetrics;
9+
import edu.harvard.iq.dataverse.settings.FeatureFlags;
910
import java.nio.file.Path;
1011
import java.nio.file.Paths;
1112
import java.sql.Timestamp;
@@ -206,6 +207,10 @@ public Dataset(boolean isHarvested) {
206207
StorageUse storageUse = new StorageUse(this);
207208
this.setStorageUse(storageUse);
208209
}
210+
211+
if (FeatureFlags.DISABLE_DATASET_THUMBNAIL_AUTOSELECT.enabled()) {
212+
this.setUseGenericThumbnail(true);
213+
}
209214
}
210215

211216
/**

src/main/java/edu/harvard/iq/dataverse/DatasetVersionServiceBean.java

+71-69
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static edu.harvard.iq.dataverse.batch.jobs.importer.filesystem.FileRecordJobListener.SEP;
1010
import edu.harvard.iq.dataverse.batch.util.LoggingUtil;
1111
import edu.harvard.iq.dataverse.search.SolrSearchResult;
12+
import edu.harvard.iq.dataverse.settings.FeatureFlags;
1213
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
1314
import edu.harvard.iq.dataverse.util.BundleUtil;
1415
import edu.harvard.iq.dataverse.util.MarkupChecker;
@@ -807,100 +808,101 @@ public Long getThumbnailByVersionId(Long versionId) {
807808
return null;
808809
}
809810

810-
Long thumbnailFileId;
811-
812-
// First, let's see if there are thumbnails that have already been
813-
// generated:
814-
try {
815-
thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id "
816-
+ "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o "
817-
+ "WHERE dv.id = " + versionId + " "
818-
+ "AND df.id = o.id "
819-
+ "AND fm.datasetversion_id = dv.id "
820-
+ "AND fm.datafile_id = df.id "
821-
+ "AND df.restricted = false "
822-
+ "AND df.embargo_id is null "
823-
+ "AND df.retention_id is null "
824-
+ "AND o.previewImageAvailable = true "
825-
+ "ORDER BY df.id LIMIT 1;").getSingleResult();
826-
} catch (Exception ex) {
827-
thumbnailFileId = null;
828-
}
829-
830-
if (thumbnailFileId != null) {
831-
logger.fine("DatasetVersionService,getThumbnailByVersionid(): found already generated thumbnail for version " + versionId + ": " + thumbnailFileId);
832-
assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId);
833-
return thumbnailFileId;
834-
}
835-
836-
if (!systemConfig.isThumbnailGenerationDisabledForImages()) {
837-
// OK, let's try and generate an image thumbnail!
838-
long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitImage();
811+
if (!FeatureFlags.DISABLE_DATASET_THUMBNAIL_AUTOSELECT.enabled()) {
812+
Long thumbnailFileId;
839813

814+
// First, let's see if there are thumbnails that have already been
815+
// generated:
840816
try {
841817
thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id "
842818
+ "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o "
843819
+ "WHERE dv.id = " + versionId + " "
844820
+ "AND df.id = o.id "
845821
+ "AND fm.datasetversion_id = dv.id "
846822
+ "AND fm.datafile_id = df.id "
847-
+ "AND o.previewimagefail = false "
848823
+ "AND df.restricted = false "
849824
+ "AND df.embargo_id is null "
850825
+ "AND df.retention_id is null "
851-
+ "AND df.contenttype LIKE 'image/%' "
852-
+ "AND NOT df.contenttype = 'image/fits' "
853-
+ "AND df.filesize < " + imageThumbnailSizeLimit + " "
854-
+ "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult();
826+
+ "AND o.previewImageAvailable = true "
827+
+ "ORDER BY df.id LIMIT 1;").getSingleResult();
855828
} catch (Exception ex) {
856829
thumbnailFileId = null;
857830
}
858831

859832
if (thumbnailFileId != null) {
860-
logger.fine("obtained file id: " + thumbnailFileId);
861-
DataFile thumbnailFile = datafileService.find(thumbnailFileId);
862-
if (thumbnailFile != null) {
863-
if (datafileService.isThumbnailAvailable(thumbnailFile)) {
864-
assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId);
865-
return thumbnailFileId;
833+
logger.fine("DatasetVersionService,getThumbnailByVersionid(): found already generated thumbnail for version " + versionId + ": " + thumbnailFileId);
834+
assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId);
835+
return thumbnailFileId;
836+
}
837+
838+
if (!systemConfig.isThumbnailGenerationDisabledForImages()) {
839+
// OK, let's try and generate an image thumbnail!
840+
long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitImage();
841+
842+
try {
843+
thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id "
844+
+ "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o "
845+
+ "WHERE dv.id = " + versionId + " "
846+
+ "AND df.id = o.id "
847+
+ "AND fm.datasetversion_id = dv.id "
848+
+ "AND fm.datafile_id = df.id "
849+
+ "AND o.previewimagefail = false "
850+
+ "AND df.restricted = false "
851+
+ "AND df.embargo_id is null "
852+
+ "AND df.retention_id is null "
853+
+ "AND df.contenttype LIKE 'image/%' "
854+
+ "AND NOT df.contenttype = 'image/fits' "
855+
+ "AND df.filesize < " + imageThumbnailSizeLimit + " "
856+
+ "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult();
857+
} catch (Exception ex) {
858+
thumbnailFileId = null;
859+
}
860+
861+
if (thumbnailFileId != null) {
862+
logger.fine("obtained file id: " + thumbnailFileId);
863+
DataFile thumbnailFile = datafileService.find(thumbnailFileId);
864+
if (thumbnailFile != null) {
865+
if (datafileService.isThumbnailAvailable(thumbnailFile)) {
866+
assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId);
867+
return thumbnailFileId;
868+
}
866869
}
867870
}
868871
}
869-
}
870872

871-
// And if that didn't work, try the same thing for PDFs:
872-
if (!systemConfig.isThumbnailGenerationDisabledForPDF()) {
873-
// OK, let's try and generate an image thumbnail!
874-
long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitPDF();
875-
try {
876-
thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id "
877-
+ "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o "
878-
+ "WHERE dv.id = " + versionId + " "
879-
+ "AND df.id = o.id "
880-
+ "AND fm.datasetversion_id = dv.id "
881-
+ "AND fm.datafile_id = df.id "
882-
+ "AND o.previewimagefail = false "
883-
+ "AND df.restricted = false "
884-
+ "AND df.embargo_id is null "
885-
+ "AND df.retention_id is null "
886-
+ "AND df.contenttype = 'application/pdf' "
887-
+ "AND df.filesize < " + imageThumbnailSizeLimit + " "
888-
+ "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult();
889-
} catch (Exception ex) {
890-
thumbnailFileId = null;
891-
}
873+
// And if that didn't work, try the same thing for PDFs:
874+
if (!systemConfig.isThumbnailGenerationDisabledForPDF()) {
875+
// OK, let's try and generate an image thumbnail!
876+
long imageThumbnailSizeLimit = systemConfig.getThumbnailSizeLimitPDF();
877+
try {
878+
thumbnailFileId = (Long) em.createNativeQuery("SELECT df.id "
879+
+ "FROM datafile df, filemetadata fm, datasetversion dv, dvobject o "
880+
+ "WHERE dv.id = " + versionId + " "
881+
+ "AND df.id = o.id "
882+
+ "AND fm.datasetversion_id = dv.id "
883+
+ "AND fm.datafile_id = df.id "
884+
+ "AND o.previewimagefail = false "
885+
+ "AND df.restricted = false "
886+
+ "AND df.embargo_id is null "
887+
+ "AND df.retention_id is null "
888+
+ "AND df.contenttype = 'application/pdf' "
889+
+ "AND df.filesize < " + imageThumbnailSizeLimit + " "
890+
+ "ORDER BY df.filesize ASC LIMIT 1;").getSingleResult();
891+
} catch (Exception ex) {
892+
thumbnailFileId = null;
893+
}
892894

893-
if (thumbnailFileId != null) {
894-
DataFile thumbnailFile = datafileService.find(thumbnailFileId);
895-
if (thumbnailFile != null) {
896-
if (datafileService.isThumbnailAvailable(thumbnailFile)) {
897-
assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId);
898-
return thumbnailFileId;
895+
if (thumbnailFileId != null) {
896+
DataFile thumbnailFile = datafileService.find(thumbnailFileId);
897+
if (thumbnailFile != null) {
898+
if (datafileService.isThumbnailAvailable(thumbnailFile)) {
899+
assignDatasetThumbnailByNativeQuery(versionId, thumbnailFileId);
900+
return thumbnailFileId;
901+
}
899902
}
900903
}
901904
}
902905
}
903-
904906
return null;
905907
}
906908

src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,19 @@ public static List<DatasetThumbnail> getThumbnailCandidates(Dataset dataset, boo
113113
*
114114
* @param dataset
115115
* @param datasetVersion
116-
* @return
116+
* @param size of the requested thumbnail
117+
* @return DatasetThumbnail object, or null if not available
117118
*/
118119
public static DatasetThumbnail getThumbnail(Dataset dataset, DatasetVersion datasetVersion, int size) {
119120
if (dataset == null) {
120121
return null;
121122
}
122123

124+
if (size == 0) {
125+
// Size 0 will fail (and set the failure flag) and should never be sent
126+
logger.warning("getThumbnail called with size 0");
127+
return null;
128+
}
123129
StorageIO<Dataset> dataAccess = null;
124130

125131
try{

src/main/java/edu/harvard/iq/dataverse/settings/FeatureFlags.java

+10
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ public enum FeatureFlags {
9191
* @since Dataverse 6.3
9292
*/
9393
DISABLE_RETURN_TO_AUTHOR_REASON("disable-return-to-author-reason"),
94+
/**
95+
* This flag disables the feature that automatically selects one of the
96+
* DataFile thumbnails in the dataset/version as the dedicated thumbnail
97+
* for the dataset.
98+
*
99+
* @apiNote Raise flag by setting
100+
* "dataverse.feature.enable-dataset-thumbnail-autoselect"
101+
* @since Dataverse 6.4
102+
*/
103+
DISABLE_DATASET_THUMBNAIL_AUTOSELECT("disable-dataset-thumbnail-autoselect"),
94104
;
95105

96106
final String flag;

src/main/java/propertyFiles/Bundle.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,7 @@ dataverse.theme.logo.imageFooter=Footer Image
10641064
dataverse.theme.logo.image.title=The logo or image file you wish to display in the header of this dataverse.
10651065
dataverse.theme.logo.image.footer=The logo or image file you wish to display in the footer of this dataverse.
10661066
dataverse.theme.logo.image.uploadNewFile=Upload New File
1067-
dataverse.theme.logo.image.invalidMsg=The image could not be uploaded. Please try again with a JPG, TIF, or PNG file.
1067+
dataverse.theme.logo.image.invalidMsg=The image could not be uploaded. Please try again with a JPG or PNG file.
10681068
dataverse.theme.logo.image.uploadImgFile=Upload Image File
10691069
dataverse.theme.logo.format.title=The shape for the logo or image file you upload for this dataverse.
10701070
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
21662166
dataset.thumbnailsAndWidget.thumbnailImage.uploadNew=Upload New File
21672167
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.
21682168
dataset.thumbnailsAndWidget.thumbnailImage.upload=Upload Image
2169-
dataset.thumbnailsAndWidget.thumbnailImage.upload.invalidMsg=The image could not be uploaded. Please try again with a JPG, TIF, or PNG file.
2169+
dataset.thumbnailsAndWidget.thumbnailImage.upload.invalidMsg=The image could not be uploaded. Please try again with a JPG or PNG file.
21702170
dataset.thumbnailsAndWidget.thumbnailImage.alt=Thumbnail image selected for dataset
21712171
dataset.thumbnailsAndWidget.success=Dataset thumbnail updated.
21722172
dataset.thumbnailsAndWidget.removeThumbnail=Remove Thumbnail

src/main/webapp/dataset.xhtml

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
<meta property="og:title" content="#{DatasetPage.title}" />
8787
<meta property="og:type" content="article" />
8888
<meta property="og:url" content="#{DatasetPage.dataverseSiteUrl}/dataset.xhtml?persistentId=#{dataset.globalId}" />
89-
<meta property="og:image" content="#{DatasetPage.dataset.getDatasetThumbnail(ImageThumbConverter.DEFAULT_PREVIEW_SIZE) == null ? DatasetPage.dataverseSiteUrl.concat(resource['images/dataverse-icon-1200.png']): DatasetPage.dataverseSiteUrl.concat('/api/datasets/:persistentId/thumbnail?persistentId=').concat(DatasetPage.dataset.getGlobalId().asString())}" />
89+
<meta property="og:image" content="#{empty DatasetPage.thumbnailString ? DatasetPage.dataverseSiteUrl.concat(resource['images/dataverse-icon-1200.png']): DatasetPage.dataverseSiteUrl.concat('/api/datasets/:persistentId/thumbnail?persistentId=').concat(DatasetPage.dataset.getGlobalId().asString())}" />
9090
<meta property="og:site_name" content="#{DatasetPage.publisher}" />
9191
<meta property="og:description" content="#{(DatasetPage.description.length()>150 ? DatasetPage.description.substring(0,147).concat('...') : DatasetPage.description)}" />
9292
<ui:repeat var="author" value="#{DatasetPage.datasetAuthors}">

0 commit comments

Comments
 (0)