mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
REPO-3766 Renditions: Simplified Async Rendition Service
REPO-3688 Renditions: Deprecation of public Java APIs
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -37,7 +37,7 @@
|
||||
|
||||
<dependency.alfresco-repository.version>7.10</dependency.alfresco-repository.version>
|
||||
<dependency.alfresco-core.version>7.4</dependency.alfresco-core.version>
|
||||
<dependency.alfresco-data-model.version>8.10</dependency.alfresco-data-model.version>
|
||||
<dependency.alfresco-data-model.version>8.15</dependency.alfresco-data-model.version>
|
||||
<dependency.alfresco-pdf-renderer.version>1.1</dependency.alfresco-pdf-renderer.version>
|
||||
<dependency.jackson.version>2.9.5</dependency.jackson.version>
|
||||
|
||||
|
@@ -29,10 +29,10 @@ package org.alfresco.rest.api.impl;
|
||||
import org.alfresco.heartbeat.RenditionsDataCollector;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.rendition2.RenditionDefinition2;
|
||||
import org.alfresco.repo.rendition2.RenditionDefinitionRegistry2;
|
||||
import org.alfresco.repo.rendition2.RenditionService2;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.thumbnail.ThumbnailDefinition;
|
||||
import org.alfresco.repo.thumbnail.ThumbnailHelper;
|
||||
import org.alfresco.repo.thumbnail.ThumbnailRegistry;
|
||||
import org.alfresco.repo.thumbnail.script.ScriptThumbnailService;
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
@@ -45,6 +45,7 @@ import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.DisabledServiceException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.StaleEntityException;
|
||||
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||
import org.alfresco.rest.framework.resource.content.CacheDirective;
|
||||
import org.alfresco.rest.framework.resource.content.ContentInfoImpl;
|
||||
@@ -57,17 +58,12 @@ import org.alfresco.rest.framework.resource.parameters.where.Query;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper;
|
||||
import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.rendition.RenditionService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
@@ -98,15 +94,12 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
|
||||
private Nodes nodes;
|
||||
private NodeService nodeService;
|
||||
private ThumbnailService thumbnailService;
|
||||
private ScriptThumbnailService scriptThumbnailService;
|
||||
private RenditionService renditionService;
|
||||
private MimetypeService mimetypeService;
|
||||
private ActionService actionService;
|
||||
private NamespaceService namespaceService;
|
||||
private ServiceRegistry serviceRegistry;
|
||||
private ResourceLoader resourceLoader;
|
||||
private TenantService tenantService;
|
||||
private RenditionService2 renditionService2;
|
||||
private RenditionsDataCollector renditionsDataCollector;
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
@@ -114,11 +107,6 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setThumbnailService(ThumbnailService thumbnailService)
|
||||
{
|
||||
this.thumbnailService = thumbnailService;
|
||||
}
|
||||
|
||||
public void setScriptThumbnailService(ScriptThumbnailService scriptThumbnailService)
|
||||
{
|
||||
this.scriptThumbnailService = scriptThumbnailService;
|
||||
@@ -140,6 +128,11 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public void setRenditionService2(RenditionService2 renditionService2)
|
||||
{
|
||||
this.renditionService2 = renditionService2;
|
||||
}
|
||||
|
||||
public void setRenditionsDataCollector(RenditionsDataCollector renditionsDataCollector)
|
||||
{
|
||||
this.renditionsDataCollector = renditionsDataCollector;
|
||||
@@ -148,26 +141,23 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
public void init()
|
||||
{
|
||||
PropertyCheck.mandatory(this, "nodes", nodes);
|
||||
PropertyCheck.mandatory(this, "thumbnailService", thumbnailService);
|
||||
PropertyCheck.mandatory(this, "scriptThumbnailService", scriptThumbnailService);
|
||||
PropertyCheck.mandatory(this, "serviceRegistry", serviceRegistry);
|
||||
PropertyCheck.mandatory(this, "tenantService", tenantService);
|
||||
PropertyCheck.mandatory(this, "renditionService2", renditionService2);
|
||||
PropertyCheck.mandatory(this, "renditionsDataCollector", renditionsDataCollector);
|
||||
|
||||
this.nodeService = serviceRegistry.getNodeService();
|
||||
this.actionService = serviceRegistry.getActionService();
|
||||
this.renditionService = serviceRegistry.getRenditionService();
|
||||
this.mimetypeService = serviceRegistry.getMimetypeService();
|
||||
this.namespaceService = serviceRegistry.getNamespaceService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Rendition> getRenditions(NodeRef nodeRef, Parameters parameters)
|
||||
{
|
||||
final NodeRef validatedNodeRef = validateNode(nodeRef.getStoreRef(), nodeRef.getId());
|
||||
String contentMimeType = getMimeType(validatedNodeRef);
|
||||
ContentData contentData = getContentData(nodeRef, true);
|
||||
String sourceMimetype = contentData.getMimetype();
|
||||
|
||||
Query query = parameters.getQuery();
|
||||
boolean includeCreated = true;
|
||||
boolean includeNotCreated = true;
|
||||
String status = getStatus(parameters);
|
||||
@@ -180,15 +170,17 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
Map<String, Rendition> apiRenditions = new TreeMap<>();
|
||||
if (includeNotCreated)
|
||||
{
|
||||
// List all available thumbnail definitions
|
||||
List<ThumbnailDefinition> thumbnailDefinitions = thumbnailService.getThumbnailRegistry().getThumbnailDefinitions(contentMimeType, -1);
|
||||
for (ThumbnailDefinition thumbnailDefinition : thumbnailDefinitions)
|
||||
// List all available rendition definitions
|
||||
long size = contentData.getSize();
|
||||
RenditionDefinitionRegistry2 renditionDefinitionRegistry2 = renditionService2.getRenditionDefinitionRegistry2();
|
||||
Set<String> renditionNames = renditionDefinitionRegistry2.getRenditionNamesFrom(sourceMimetype, size);
|
||||
for (String renditionName : renditionNames)
|
||||
{
|
||||
apiRenditions.put(thumbnailDefinition.getName(), toApiRendition(thumbnailDefinition));
|
||||
apiRenditions.put(renditionName, toApiRendition(renditionName));
|
||||
}
|
||||
}
|
||||
|
||||
List<ChildAssociationRef> nodeRefRenditions = renditionService.getRenditions(validatedNodeRef);
|
||||
List<ChildAssociationRef> nodeRefRenditions = renditionService2.getRenditions(validatedNodeRef);
|
||||
if (!nodeRefRenditions.isEmpty())
|
||||
{
|
||||
for (ChildAssociationRef childAssociationRef : nodeRefRenditions)
|
||||
@@ -231,21 +223,23 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
// if there is no rendition, then try to find the available/registered rendition (yet to be created).
|
||||
if (renditionNodeRef == null && includeNotCreated)
|
||||
{
|
||||
ThumbnailDefinition thumbnailDefinition = thumbnailService.getThumbnailRegistry().getThumbnailDefinition(renditionId);
|
||||
if (thumbnailDefinition == null)
|
||||
ContentData contentData = getContentData(validatedNodeRef, true);
|
||||
String sourceMimetype = contentData.getMimetype();
|
||||
long size = contentData.getSize();
|
||||
RenditionDefinitionRegistry2 renditionDefinitionRegistry2 = renditionService2.getRenditionDefinitionRegistry2();
|
||||
RenditionDefinition2 renditionDefinition = renditionDefinitionRegistry2.getRenditionDefinition(renditionId);
|
||||
if (renditionDefinition == null)
|
||||
{
|
||||
throw new NotFoundException(renditionId + " is not registered.");
|
||||
}
|
||||
else
|
||||
{
|
||||
String contentMimeType = getMimeType(validatedNodeRef);
|
||||
// List all available thumbnail definitions for the source node
|
||||
List<ThumbnailDefinition> thumbnailDefinitions = thumbnailService.getThumbnailRegistry().getThumbnailDefinitions(contentMimeType, -1);
|
||||
Set<String> renditionNames = renditionDefinitionRegistry2.getRenditionNamesFrom(sourceMimetype, size);
|
||||
boolean found = false;
|
||||
for (ThumbnailDefinition td : thumbnailDefinitions)
|
||||
for (String renditionName : renditionNames)
|
||||
{
|
||||
// Check the registered renditionId is applicable for the node's mimeType
|
||||
if (renditionId.equals(td.getName()))
|
||||
if (renditionId.equals(renditionName))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
@@ -253,10 +247,10 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
throw new NotFoundException(renditionId + " is not applicable for the node's mimeType " + contentMimeType);
|
||||
throw new NotFoundException(renditionId + " is not applicable for the node's mimeType " + sourceMimetype);
|
||||
}
|
||||
}
|
||||
return toApiRendition(thumbnailDefinition);
|
||||
return toApiRendition(renditionId);
|
||||
}
|
||||
|
||||
if (renditionNodeRef == null)
|
||||
@@ -277,9 +271,9 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
public void createRendition(NodeRef nodeRef, Rendition rendition, boolean executeAsync, Parameters parameters)
|
||||
{
|
||||
// If thumbnail generation has been configured off, then don't bother.
|
||||
if (!thumbnailService.getThumbnailsEnabled())
|
||||
if (!renditionService2.isEnabled())
|
||||
{
|
||||
throw new DisabledServiceException("Thumbnail generation has been disabled.");
|
||||
throw new DisabledServiceException("Rendition generation has been disabled.");
|
||||
}
|
||||
|
||||
final NodeRef sourceNodeRef = validateNode(nodeRef.getStoreRef(), nodeRef.getId());
|
||||
@@ -289,29 +283,22 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
throw new ConstraintViolatedException(rendition.getId() + " rendition already exists.");
|
||||
}
|
||||
|
||||
// Use the thumbnail registry to get the details of the thumbnail
|
||||
ThumbnailRegistry registry = thumbnailService.getThumbnailRegistry();
|
||||
ThumbnailDefinition thumbnailDefinition = registry.getThumbnailDefinition(rendition.getId());
|
||||
if (thumbnailDefinition == null)
|
||||
try
|
||||
{
|
||||
throw new NotFoundException(rendition.getId() + " is not registered.");
|
||||
renditionService2.render(sourceNodeRef, rendition.getId());
|
||||
}
|
||||
|
||||
ContentData contentData = getContentData(sourceNodeRef, true);
|
||||
// Check if anything is currently available to generate thumbnails for the specified mimeType
|
||||
String sourceMimetype = contentData.getMimetype();
|
||||
if (!registry.isThumbnailDefinitionAvailable(contentData.getContentUrl(), sourceMimetype, contentData.getSize(), sourceNodeRef,
|
||||
thumbnailDefinition))
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException("Unable to create thumbnail '" + thumbnailDefinition.getName() + "' for " +
|
||||
sourceMimetype + " as no transformer is currently available.");
|
||||
throw new NotFoundException(rendition.getId() + " is not registered."); // 404
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
throw new IllegalArgumentException((e.getMessage())); // 400
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
throw new StaleEntityException(e.getMessage()); // 409
|
||||
}
|
||||
|
||||
Action action = ThumbnailHelper.createCreateThumbnailAction(thumbnailDefinition, serviceRegistry);
|
||||
renditionsDataCollector.recordRenditionRequest(thumbnailDefinition, sourceMimetype);
|
||||
|
||||
// Create thumbnail - or else queue for async creation
|
||||
actionService.executeAction(action, sourceNodeRef, true, executeAsync);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -423,10 +410,8 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
{
|
||||
throw new InvalidArgumentException("renditionId can't be null or empty.");
|
||||
}
|
||||
// Thumbnails have a cm: prefix.
|
||||
QName renditionQName = QName.resolveToQName(namespaceService, renditionId);
|
||||
|
||||
ChildAssociationRef nodeRefRendition = renditionService.getRenditionByName(nodeRef, renditionQName);
|
||||
ChildAssociationRef nodeRefRendition = renditionService2.getRenditionByName(nodeRef, renditionId);
|
||||
if (nodeRefRendition == null)
|
||||
{
|
||||
return null;
|
||||
@@ -457,12 +442,15 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
return apiRendition;
|
||||
}
|
||||
|
||||
protected Rendition toApiRendition(ThumbnailDefinition thumbnailDefinition)
|
||||
protected Rendition toApiRendition(String renditionName)
|
||||
{
|
||||
ContentInfo contentInfo = new ContentInfo(thumbnailDefinition.getMimetype(),
|
||||
getMimeTypeDisplayName(thumbnailDefinition.getMimetype()), null, null);
|
||||
RenditionDefinitionRegistry2 renditionDefinitionRegistry2 = renditionService2.getRenditionDefinitionRegistry2();
|
||||
RenditionDefinition2 renditionDefinition = renditionDefinitionRegistry2.getRenditionDefinition(renditionName);
|
||||
ContentInfo contentInfo = new ContentInfo(renditionDefinition.getTargetMimetype(),
|
||||
getMimeTypeDisplayName(renditionDefinition.getTargetMimetype()), null, null);
|
||||
|
||||
Rendition apiRendition = new Rendition();
|
||||
apiRendition.setId(thumbnailDefinition.getName());
|
||||
apiRendition.setId(renditionName);
|
||||
apiRendition.setContent(contentInfo);
|
||||
apiRendition.setStatus(RenditionStatus.NOT_CREATED);
|
||||
|
||||
|
@@ -1359,10 +1359,10 @@
|
||||
<!-- -->
|
||||
<bean id="renditions" class="org.alfresco.rest.api.impl.RenditionsImpl" init-method="init">
|
||||
<property name="nodes" ref="nodes" />
|
||||
<property name="thumbnailService" ref="ThumbnailService" />
|
||||
<property name="scriptThumbnailService" ref="thumbnailServiceScript" />
|
||||
<property name="serviceRegistry" ref="ServiceRegistry" />
|
||||
<property name="tenantService" ref="tenantService"/>
|
||||
<property name="renditionService2" ref="RenditionService2"/>
|
||||
<property name="renditionsDataCollector" ref="renditionsDataCollector"/>
|
||||
</bean>
|
||||
|
||||
|
@@ -36,6 +36,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import com.google.common.collect.Ordering;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.content.transform.ContentTransformer;
|
||||
import org.alfresco.repo.rendition2.RenditionService2Impl;
|
||||
import org.alfresco.rest.api.model.Site;
|
||||
import org.alfresco.rest.api.nodes.NodesEntityResource;
|
||||
import org.alfresco.rest.api.tests.RepoService.TestNetwork;
|
||||
@@ -469,9 +470,9 @@ public class RenditionsTest extends AbstractBaseApiTest
|
||||
multipleRenditionRequest.add(new Rendition().setId("imgpreview"));
|
||||
post(getNodeRenditionsUrl(contentNodeId), toJsonAsString(multipleRenditionRequest), 400);
|
||||
|
||||
ThumbnailService thumbnailService = applicationContext.getBean("thumbnailService", ThumbnailService.class);
|
||||
RenditionService2Impl renditionService2 = applicationContext.getBean("renditionService2", RenditionService2Impl.class);
|
||||
// Disable thumbnail generation
|
||||
thumbnailService.setThumbnailsEnabled(false);
|
||||
renditionService2.setThumbnailsEnabled(false);
|
||||
try
|
||||
{
|
||||
// Create multipart request
|
||||
@@ -494,7 +495,7 @@ public class RenditionsTest extends AbstractBaseApiTest
|
||||
}
|
||||
finally
|
||||
{
|
||||
thumbnailService.setThumbnailsEnabled(true);
|
||||
renditionService2.setThumbnailsEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -85,6 +85,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
import static org.alfresco.repo.security.authentication.ResetPasswordServiceImplTest.getWorkflowIdAndKeyFromUrl;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -2059,7 +2060,7 @@ public class TestPeople extends AbstractBaseApiTest
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(requiredDelay);
|
||||
sleep(requiredDelay);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
@@ -2129,7 +2130,7 @@ public class TestPeople extends AbstractBaseApiTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateAvatar() throws PublicApiException, IOException
|
||||
public void updateAvatar() throws PublicApiException, IOException, InterruptedException
|
||||
{
|
||||
final String person1 = account1PersonIt.next();
|
||||
final String person2 = account1PersonIt.next();
|
||||
@@ -2243,7 +2244,8 @@ public class TestPeople extends AbstractBaseApiTest
|
||||
|
||||
|
||||
@Test
|
||||
public void removeAvatar() throws IOException, PublicApiException{
|
||||
public void removeAvatar() throws IOException, PublicApiException, InterruptedException
|
||||
{
|
||||
|
||||
final String person1 = account1PersonIt.next();
|
||||
final String person2 = account1PersonIt.next();
|
||||
|
@@ -1411,17 +1411,17 @@ public class PublicApiClient
|
||||
remove("people", personId, "activities", String.valueOf(activity.getId()), "Failed to remove activity");
|
||||
}
|
||||
|
||||
public HttpResponse getAvatar(String personId, boolean placeholder, int expectedStatus) throws PublicApiException
|
||||
public HttpResponse getAvatar(String personId, boolean placeholder, int expectedStatus) throws PublicApiException, InterruptedException
|
||||
{
|
||||
return getAvatar(personId, null, placeholder, null, expectedStatus);
|
||||
}
|
||||
|
||||
public HttpResponse getAvatar(String personId, String ifModifiedSince, int expectedStatus) throws PublicApiException
|
||||
public HttpResponse getAvatar(String personId, String ifModifiedSince, int expectedStatus) throws PublicApiException, InterruptedException
|
||||
{
|
||||
return getAvatar(personId, null, false, ifModifiedSince, expectedStatus);
|
||||
}
|
||||
|
||||
public HttpResponse getAvatar(String personId, Boolean attachment, boolean placeholder, String ifModifiedSince, int expectedStatus) throws PublicApiException
|
||||
public HttpResponse getAvatar(String personId, Boolean attachment, boolean placeholder, String ifModifiedSince, int expectedStatus) throws PublicApiException, InterruptedException
|
||||
{
|
||||
// Binary response expected
|
||||
Map<String, String> params = new HashMap<>();
|
||||
@@ -1438,12 +1438,33 @@ public class PublicApiClient
|
||||
headers.put("If-Modified-Since", ifModifiedSince);
|
||||
}
|
||||
|
||||
HttpResponse response = getSingle("people", personId, "avatar", null, params, headers, "Failed to get avatar", expectedStatus);
|
||||
// As renditions are now done async, we generally need to wait.
|
||||
HttpResponse response = getSingleWithDelayRetry("people", personId, "avatar",
|
||||
null, params, headers, "Failed to get avatar", 40, 2500, expectedStatus);
|
||||
checkStatus("Unexpected response", expectedStatus, response);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private HttpResponse getSingleWithDelayRetry(String entityCollectionName, String entityId, String relationCollectionName, String relationId, Map<String, String> params,
|
||||
Map<String, String> headers, String errorMessage, int repeat, long pauseInMillisecond, int expectedStatus) throws PublicApiException, InterruptedException
|
||||
{
|
||||
int retryCount = 0;
|
||||
while (retryCount < repeat)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getSingle(entityCollectionName, entityId, relationCollectionName, relationId, params, headers, errorMessage, expectedStatus);
|
||||
}
|
||||
catch (PublicApiException ex)
|
||||
{
|
||||
retryCount++;
|
||||
Thread.sleep(pauseInMillisecond);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpResponse updateAvatar(String personId, File avatar, int expectedStatus) throws PublicApiException
|
||||
{
|
||||
try
|
||||
|
Reference in New Issue
Block a user