09-22-2022 03:51 AM
Hi i need to add a new (and custom) thumbnail "original" to the list supported from alfresco 7.2.1 Community.
I have created a local transformer for convert files to "original" ( you can think thata as a alternative pdf thumbnail),
for the sourcemimetype = "text/plain" and the target mimetype "application/original".
Here i define my thumbnaildefinition for the auto registry:
@Component public class ThumbnailDefinitionOriginal extends org.alfresco.repo.thumbnail.ThumbnailDefinition implements InitializingBean{ private static final transient org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ThumbnailDefinitionOriginal.class); @Autowired private ThumbnailRegistry thumbnailRegistry; public void setThumbnailRegistry(ThumbnailRegistry thumbnailRegistry) { this.thumbnailRegistry = thumbnailRegistry; } @Override public void afterPropertiesSet() { super.setName(this.name); super.setMimetype(this.mimetype); super.setTransformationOptions(this.transformationOptions); super.setRunAs(this.runAs); super.setFailureHandlingOptions(this.failureHandlingOptions); super.setThumbnailRegistry(this.thumbnailRegistry); Map<String, Serializable> parameters = new HashMap<String, Serializable>(); // All TransformationOptions-based renditions are considered to be "thumbnails". // Therefore they should be created with a node type of cm:thumbnail parameters.put(RenditionService.PARAM_RENDITION_NODETYPE, ContentModel.TYPE_THUMBNAIL); // parameters common to all transformations putParameterIfNotNull(AbstractRenderingEngine.PARAM_SOURCE_CONTENT_PROPERTY, transformationOptions.getSourceContentProperty(), parameters); putParameterIfNotNull(AbstractRenderingEngine.PARAM_TARGET_CONTENT_PROPERTY, transformationOptions.getTargetContentProperty(), parameters); putParameterIfNotNull(RenditionService.PARAM_DESTINATION_NODE, transformationOptions.getTargetNodeRef(), parameters); // putParameterIfNotNull(ImageRenderingEngine.PARAM_ASSOC_NAME, assocDetails.getAssociationName(), parameters); // putParameterIfNotNull(ImageRenderingEngine.PARAM_ASSOC_TYPE, assocDetails.getAssociationType(), parameters); putParameterIfNotNull(AbstractTransformationRenderingEngine.PARAM_TIMEOUT_MS, transformationOptions.getTimeoutMs(), parameters); putParameterIfNotNull(AbstractTransformationRenderingEngine.PARAM_READ_LIMIT_TIME_MS, transformationOptions.getReadLimitTimeMs(), parameters); putParameterIfNotNull(AbstractTransformationRenderingEngine.PARAM_MAX_SOURCE_SIZE_K_BYTES, transformationOptions.getMaxSourceSizeKBytes(), parameters); putParameterIfNotNull(AbstractTransformationRenderingEngine.PARAM_READ_LIMIT_K_BYTES, transformationOptions.getReadLimitKBytes(), parameters); putParameterIfNotNull(AbstractTransformationRenderingEngine.PARAM_MAX_PAGES, transformationOptions.getMaxPages(), parameters); putParameterIfNotNull(AbstractTransformationRenderingEngine.PARAM_PAGE_LIMIT, transformationOptions.getPageLimit(), parameters); putParameterIfNotNull(AbstractTransformationRenderingEngine.PARAM_USE, transformationOptions.getUse(), parameters); if (transformationOptions.getSourceOptionsList() != null) { for (TransformationSourceOptions sourceOptions : transformationOptions.getSourceOptionsList()) { sourceOptions.getSerializer().serialize(sourceOptions, parameters); } } // Auto self registry this.thumbnailRegistry.addThumbnailDefinition(this); } private void putParameterIfNotNull(String paramName, Serializable paramValue, Map<String, Serializable> params) { if (paramValue != null) { params.put(paramName, paramValue); } } @Autowired private ThumbnailService thumbnailService; public void setThumbnailService(ThumbnailService thumbnailService) { this.thumbnailService = thumbnailService; } // ====================== // CUSTOM // ====================== private String name = "original"; public void setName(String name) { this.name = name; } private String mimetype = "application/original"; public void setMimetype(String mimetype) { this.mimetype = mimetype; } private TransformationOptions transformationOptions = new RuntimeExecutableContentTransformerOptions(); public void setTransformationOptions(TransformationOptions transformationOptions) { this.transformationOptions = transformationOptions; } private String runAs = AuthenticationUtil.getSystemUserName(); public void setRunAs(String runAs) { this.runAs = runAs; } /** * The placeholder is a graphic that the thumbnail service can return as the thumbnail if the thumbnail for a given * node has not been generated. In my example I just copied one of the out-of-the-box placeholders and renamed it * but you could use anything you want there. */ private String placeHolderResourcePath = "alfresco/module/xxx/thumbnail/thumbnail_placeholder_scImageThumbnail.png"; public void setPlaceHolderResourcePath(String placeHolderResourcePath) { this.placeHolderResourcePath = placeHolderResourcePath; } private String mimeAwarePlaceHolderResourcePath = "alfresco/module/xxx/thumbnail/thumbnail_placeholder_scImageThumbnail.png"; public void setMimeAwarePlaceHolderResourcePath(String mimeAwarePlaceHolderResourcePath) { this.mimeAwarePlaceHolderResourcePath = mimeAwarePlaceHolderResourcePath; } @Autowired @Qualifier("standardFailureOptions") private FailureHandlingOptions failureHandlingOptions; public void setFailureHandlingOptions(FailureHandlingOptions failureHandlingOptions) { this.failureHandlingOptions = failureHandlingOptions; } }
Now i set up a lillte behaviour for launch the rendition2Service when updating a content:
/** * Rendition Behaviour using RenditionService v2, as Share is still using RenditionService V1 * Performs ORIGINAL renditions on created and modified Markdown content nodes using Rendition Service V2. * Share Web App is still using Rendition Service V1, so in order to get the rendition done with this * new transformer this additional operation is required. * @href https://github.com/aborroy/alf-tengine-markdown * @author aborroy * */ @Component public class OriginalRenditionBehaviour implements NodeServicePolicies.OnCreateNodePolicy, ContentServicePolicies.OnContentUpdatePolicy, NodeServicePolicies.OnCreateChildAssociationPolicy, InitializingBean { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(OriginalRenditionBehaviour.class); private boolean enable = true; @Autowired @Qualifier("configurazioniBeanCompleto") private ConfigurazioniBean configurazioniBean; public void setConfigurazioniBean(ConfigurazioniBean configurazioniBean) { this.configurazioniBean = configurazioniBean; } @Autowired private PolicyComponent policyComponent; public void setPolicyComponent(PolicyComponent policyComponent) { this.policyComponent = policyComponent; } @Autowired @Qualifier("NodeService") private NodeService nodeService; public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } /** * Use the new Rendition Service V2 in order to use "localTransform.original" transformer */ @Autowired @Qualifier("RenditionService2") private RenditionService2 renditionService2; public void setRenditionService2(RenditionService2 renditionService2) { this.renditionService2 = renditionService2; } @Autowired @Qualifier("RenditionService") private RenditionService renditionService; public void setRenditionService(RenditionService renditionService) { this.renditionService = renditionService; } @Override public void afterPropertiesSet() { init(); } public void init() { logger.debug("START BEHAVIOUR '" + this.getClass().getSimpleName()+"' '"+new Object(){}.getClass().getEnclosingMethod().getName()+"'"); policyComponent.bindClassBehaviour( NodeServicePolicies.OnCreateNodePolicy.QNAME, ContentModel.TYPE_CONTENT, new JavaBehaviour(this, "onCreateNode", NotificationFrequency.TRANSACTION_COMMIT)); policyComponent.bindClassBehaviour( ContentServicePolicies.OnContentUpdatePolicy.QNAME, ContentModel.TYPE_CONTENT, new JavaBehaviour(this, "onContentUpdate", NotificationFrequency.TRANSACTION_COMMIT)); policyComponent.bindAssociationBehaviour( NodeServicePolicies.OnCreateChildAssociationPolicy.QNAME, ContentModel.TYPE_CONTENT, //ContentModel.ASSOC_THUMBNAILS, RenditionModel.ASSOC_RENDITION, new JavaBehaviour(this, "onCreateChildAssociation", NotificationFrequency.TRANSACTION_COMMIT)); logger.debug("END BEHAVIOUR '" + this.getClass().getSimpleName()+"' '"+new Object(){}.getClass().getEnclosingMethod().getName()+"'"); }else { logger.warn("Can't invoke the '"+new Object(){}.getClass().getEnclosingMethod().getName()+"' because the property 'enable' is false"); } } @Override public void onContentUpdate(NodeRef nodeRef, boolean newContent) { for(String targetMimetype : TARGET_MIMETYPES) { requestRendition(nodeRef,targetMimetype); } } @Override public void onCreateNode(ChildAssociationRef childAssocRef) { for(String targetMimetype : TARGET_MIMETYPES) { requestRendition(childAssocRef.getChildRef(),targetMimetype); } } @Override public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNewNode) { // for(String targetMimetype : TARGET_MIMETYPES) { // requestRendition(childAssocRef.getChildRef(),targetMimetype); // } } public static final List<String> SOURCE_MIMETYPES= Arrays.asList(new String[] { "text/plain" }); public static final List<String> TARGET_MIMETYPES = Arrays.asList(new String[] { "application/original" }); public boolean isTransformable(String sourceMimetype, String targetMimetype) { if(sourceMimetype==null || targetMimetype == null) { return false; } if(this.enable && SOURCE_MIMETYPES.contains(sourceMimetype.toLowerCase()) && TARGET_MIMETYPES.contains(targetMimetype.toLowerCase()) && !sourceMimetype.equalsIgnoreCase(targetMimetype)){ //logger.debug("sourceMimetype=" + sourceMimetype+", targetMimetype=" + targetMimetype+", check="+SOURCE_MIMETYPES.contains(sourceMimetype)+", nodeRef="+options.getSourceNodeRef()); return true; }else { return false; } } /** * Performs a specific Rendition on sourceNodeRef if mime type is transformable * @param sourceNodeRef The node to be renditioned */ private void requestRendition(NodeRef sourceNodeRef, String targetMimetype) { try { //logger.debug("START TRANSFORMER LOCAL '" + this.getClass().getSimpleName() + "'" + " with stargetMimetype '"+targetMimetype+"'" + " on node '"+sourceNodeRef+"|"+nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME)+"'"); AuthenticationUtil.pushAuthentication(); Boolean FINALE = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>() { @Override public Boolean doWork() throws Exception { return TenantUtil.runAsTenant(new TenantUtil.TenantRunAsWork<Boolean>() { public Boolean doWork() throws Exception { if (nodeService.exists(sourceNodeRef)) { ContentData contentData = (ContentData) nodeService.getProperty(sourceNodeRef, ContentModel.PROP_CONTENT); if(contentData == null) { return false; } String mimeType = contentData.getMimetype(); if (isTransformable(mimeType, targetMimetype)) { String thumbnailName = ThumbnailServiceUtilities.retrieveThumbnailNameFromMimetype(targetMimetype); if(StringUtils.isBlank(thumbnailName)) { return false; } logger.debug("START TRANSFORMER LOCAL '" + this.getClass().getSimpleName() + "'" + " with stargetMimetype '"+targetMimetype+"'" + " on node '"+sourceNodeRef+"|"+nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME)+"'"); long size = contentData.getSize(); RenditionDefinitionRegistry2 renditionDefinitionRegistry2 = renditionService2.getRenditionDefinitionRegistry2(); Set<String> availableRenditions = renditionDefinitionRegistry2.getRenditionNamesFrom(mimeType, size); if(availableRenditions==null || availableRenditions.isEmpty()) { logger.warn("No rendition2 is enabled for sourceMimetype="+mimeType+" and targetMimetype="+targetMimetype+""); return false; } logger.debug("Found these renditions/thumbnails "+Arrays.toString(availableRenditions.toArray())+" for sourceMimetype="+mimeType+" and targetMimetype="+targetMimetype+""); try { if (!availableRenditions.contains(thumbnailName)) { logger.warn("Unable to create rendition '"+thumbnailName+"' for " + mimeType + " as no transformer is currently available."); return false; } logger.debug("Run local transformer on node '"+sourceNodeRef+"' "); renditionService2.render(sourceNodeRef, thumbnailName); //renditionService.render(sourceNodeRef, "pdf"); logger.debug("END TRANSFORMER LOCAL '" + this.getClass().getSimpleName() + "'" + " with stargetMimetype '"+targetMimetype+"'" + " on node '"+sourceNodeRef+"|"+nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME)+"'"); return true; } catch (Exception ex) { // Don't throw the exception as we don't want the the upload to fail, just log it logger.warn("Asynchronous request to create a rendition upon upload failed: " + ex.getMessage(), ex); return false; } } return false; } return false; } }, TenantUtil.getCurrentDomain()); } } , AuthenticationUtil.getSystemUserName()); //logger.debug("END TRANSFORMER LOCAL '" + this.getClass().getSimpleName() + "'" + " with stargetMimetype '"+targetMimetype+"'" + " on node '"+sourceNodeRef+"|"+nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME)+"'"); }finally { AuthenticationUtil.popAuthentication(); } } }
but here the result of the line of code:
Set<String> availableRenditions = renditionDefinitionRegistry2.getRenditionNamesFrom(mimeType, size);
it's seem not have the rendition "original" on the list, here the result catch on debug:
renditionService2.getRenditionDefinitionRegistry2().getRenditionNamesFrom(mimeType, contentData.getSize()) (java.util.HashSet<E>) [imgpreview, doclib, pdf, medium, avatar, avatar32]
Anyone can tell me what i missing ?
Explore our Alfresco products with the links below. Use labels to filter content by product module.