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.