diff --git a/pom.xml b/pom.xml
index b47f85d2e0..baf771f023 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,7 +37,7 @@
7.10
7.4
- 8.10
+ 8.15
1.1
2.9.5
diff --git a/src/main/java/org/alfresco/rest/api/impl/RenditionsImpl.java b/src/main/java/org/alfresco/rest/api/impl/RenditionsImpl.java
index ac4036121c..c92df940dc 100644
--- a/src/main/java/org/alfresco/rest/api/impl/RenditionsImpl.java
+++ b/src/main/java/org/alfresco/rest/api/impl/RenditionsImpl.java
@@ -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 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 apiRenditions = new TreeMap<>();
if (includeNotCreated)
{
- // List all available thumbnail definitions
- List thumbnailDefinitions = thumbnailService.getThumbnailRegistry().getThumbnailDefinitions(contentMimeType, -1);
- for (ThumbnailDefinition thumbnailDefinition : thumbnailDefinitions)
+ // List all available rendition definitions
+ long size = contentData.getSize();
+ RenditionDefinitionRegistry2 renditionDefinitionRegistry2 = renditionService2.getRenditionDefinitionRegistry2();
+ Set renditionNames = renditionDefinitionRegistry2.getRenditionNamesFrom(sourceMimetype, size);
+ for (String renditionName : renditionNames)
{
- apiRenditions.put(thumbnailDefinition.getName(), toApiRendition(thumbnailDefinition));
+ apiRenditions.put(renditionName, toApiRendition(renditionName));
}
}
- List nodeRefRenditions = renditionService.getRenditions(validatedNodeRef);
+ List 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 thumbnailDefinitions = thumbnailService.getThumbnailRegistry().getThumbnailDefinitions(contentMimeType, -1);
+ Set 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);
diff --git a/src/main/resources/alfresco/public-rest-context.xml b/src/main/resources/alfresco/public-rest-context.xml
index cff19bf0b8..73295d7f32 100644
--- a/src/main/resources/alfresco/public-rest-context.xml
+++ b/src/main/resources/alfresco/public-rest-context.xml
@@ -1359,10 +1359,10 @@
-
+
diff --git a/src/test/java/org/alfresco/rest/api/tests/RenditionsTest.java b/src/test/java/org/alfresco/rest/api/tests/RenditionsTest.java
index feca5ee960..fb43dc6cf7 100644
--- a/src/test/java/org/alfresco/rest/api/tests/RenditionsTest.java
+++ b/src/test/java/org/alfresco/rest/api/tests/RenditionsTest.java
@@ -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);
}
}
diff --git a/src/test/java/org/alfresco/rest/api/tests/TestPeople.java b/src/test/java/org/alfresco/rest/api/tests/TestPeople.java
index bd54305fd0..acda284400 100644
--- a/src/test/java/org/alfresco/rest/api/tests/TestPeople.java
+++ b/src/test/java/org/alfresco/rest/api/tests/TestPeople.java
@@ -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();
diff --git a/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java b/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java
index ce4fe2d593..aeb5315610 100644
--- a/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java
+++ b/src/test/java/org/alfresco/rest/api/tests/client/PublicApiClient.java
@@ -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 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 params,
+ Map 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