Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2)

123025 gjames: RA-757: Handle integrity exceptions


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@126522 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jamal Kaabi-Mofrad
2016-05-10 11:19:41 +00:00
parent 8e27cb0de1
commit 1e4f80cb61
8 changed files with 126 additions and 21 deletions

View File

@@ -145,6 +145,7 @@
<entry key="org.alfresco.rest.framework.core.exceptions.RequestEntityTooLargeException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_REQUEST_ENTITY_TOO_LARGE}" /> <entry key="org.alfresco.rest.framework.core.exceptions.RequestEntityTooLargeException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_REQUEST_ENTITY_TOO_LARGE}" />
<entry key="org.alfresco.rest.framework.core.exceptions.DisabledServiceException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_IMPLEMENTED}" /> <entry key="org.alfresco.rest.framework.core.exceptions.DisabledServiceException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_IMPLEMENTED}" />
<entry key="org.alfresco.rest.framework.core.exceptions.InsufficientStorageException" value="507" /> <entry key="org.alfresco.rest.framework.core.exceptions.InsufficientStorageException" value="507" />
<entry key="org.alfresco.repo.node.integrity.IntegrityException" value="422" />
</map> </map>
</property> </property>
</bean> </bean>

View File

@@ -25,6 +25,7 @@ import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.node.integrity.IntegrityException; import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.repo.tenant.TenantUtil; import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
@@ -146,17 +147,9 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
} }
} }
catch (IntegrityException intException) catch (AlfrescoRuntimeException | ApiException | WebScriptException xception )
{ {
renderErrorResponse(resolveException(intException), res); renderErrorResponse(resolveException(xception), res);
}
catch (ApiException apiException)
{
renderErrorResponse(resolveException(apiException), res);
}
catch (WebScriptException webException)
{
renderErrorResponse(resolveException(webException), res);
} }
catch (RuntimeException runtimeException) catch (RuntimeException runtimeException)
{ {

View File

@@ -161,7 +161,7 @@ public abstract class ApiWebScript extends AbstractWebScript
} }
} }
private Api determineApi(Map<String, String> templateVars) public Api determineApi(Map<String, String> templateVars)
{ {
String apiScope = templateVars.get("apiScope"); String apiScope = templateVars.get("apiScope");
String apiVersion = templateVars.get("apiVersion"); String apiVersion = templateVars.get("apiVersion");

View File

@@ -0,0 +1,33 @@
package org.alfresco.rest.framework.tests.api.mocks;
import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.WebApiParameters;
import org.alfresco.rest.framework.core.ResourceParameter;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.springframework.extensions.webscripts.Status;
@EntityResource(name= BadEntityResource.ENTITY_KEY,title="bad resource that does bad things")
public class BadEntityResource implements EntityResourceAction.Read<Sheep>,EntityResourceAction.ReadById<Sheep>
{
public static final String ENTITY_KEY = "bad";
@Override
public Sheep readById(String id, Parameters parameters)
{
throw new IntegrityException("bad integrity", null);
}
@Override
@WebApiDescription(title = "Gets all the Sheep", successStatus = Status.STATUS_ACCEPTED)
public CollectionWithPagingInfo<Sheep> readAll(Parameters params)
{
throw new RuntimeException("read all");
}
}

View File

@@ -11,7 +11,8 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({ InspectorTests.class, JsonJacksonTests.class, ParamsExtractorTests.class, @SuiteClasses({ InspectorTests.class, JsonJacksonTests.class, ParamsExtractorTests.class,
ResourceLocatorTests.class, ResourceWebScriptHelperTests.class, SerializeTests.class, ResourceLocatorTests.class, ResourceWebScriptHelperTests.class, SerializeTests.class,
WhereTests.class, ExecutionTests.class, WithResponseTest.class }) WhereTests.class, ExecutionTests.class, WithResponseTest.class,
ExceptionResolverTests.class })
public class AllRestFrameworkTest public class AllRestFrameworkTest
{ {

View File

@@ -5,11 +5,13 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import org.alfresco.repo.forms.FormNotFoundException; import org.alfresco.repo.forms.FormNotFoundException;
import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.rest.framework.core.exceptions.ApiException; import org.alfresco.rest.framework.core.exceptions.ApiException;
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
import org.alfresco.rest.framework.core.exceptions.DeletedResourceException; import org.alfresco.rest.framework.core.exceptions.DeletedResourceException;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.ErrorResponse; import org.alfresco.rest.framework.core.exceptions.ErrorResponse;
import org.alfresco.rest.framework.core.exceptions.InsufficientStorageException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException; import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
@@ -77,6 +79,12 @@ public class ExceptionResolverTests
//Try a random exception //Try a random exception
response = simpleMappingExceptionResolver.resolveException(new FormNotFoundException(null)); response = simpleMappingExceptionResolver.resolveException(new FormNotFoundException(null));
assertNull(response); assertNull(response);
response = simpleMappingExceptionResolver.resolveException(new InsufficientStorageException(null));
assertEquals(507, response.getStatusCode());
response = simpleMappingExceptionResolver.resolveException(new IntegrityException(null));
assertEquals(422, response.getStatusCode());
} }
} }

View File

@@ -5,14 +5,17 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.alfresco.rest.framework.Api; import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.core.ResourceLocator; import org.alfresco.rest.framework.core.ResourceLocator;
import org.alfresco.rest.framework.core.ResourceLookupDictionary; import org.alfresco.rest.framework.core.ResourceLookupDictionary;
import org.alfresco.rest.framework.core.ResourceWithMetadata; import org.alfresco.rest.framework.core.ResourceWithMetadata;
import org.alfresco.rest.framework.core.exceptions.SimpleMappingExceptionResolver;
import org.alfresco.rest.framework.jacksonextensions.ExecutionResult; import org.alfresco.rest.framework.jacksonextensions.ExecutionResult;
import org.alfresco.rest.framework.resource.actions.ActionExecutor; import org.alfresco.rest.framework.resource.actions.ActionExecutor;
import org.alfresco.rest.framework.resource.content.ContentInfo; import org.alfresco.rest.framework.resource.content.ContentInfo;
@@ -27,9 +30,12 @@ import org.alfresco.rest.framework.webscripts.AbstractResourceWebScript;
import org.alfresco.rest.framework.webscripts.ApiWebScript; import org.alfresco.rest.framework.webscripts.ApiWebScript;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.extensions.webscripts.Cache; import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Match;
import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse; import org.springframework.extensions.webscripts.WebScriptResponse;
@@ -37,9 +43,12 @@ import org.springframework.http.HttpMethod;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@@ -50,6 +59,9 @@ public class ExecutionTests extends AbstractContextTest
{ {
static final Api api3 = Api.valueOf("alfrescomock", "private", "3"); static final Api api3 = Api.valueOf("alfrescomock", "private", "3");
@Autowired
SimpleMappingExceptionResolver simpleMappingExceptionResolver;
@Test @Test
public void testInvokeGet() throws IOException public void testInvokeGet() throws IOException
{ {
@@ -218,4 +230,55 @@ public class ExecutionTests extends AbstractContextTest
result = executor.execute(calf, Params.valueOf("4", "56", mock(WebScriptRequest.class)), mock(WebScriptResponse.class), false); result = executor.execute(calf, Params.valueOf("4", "56", mock(WebScriptRequest.class)), mock(WebScriptResponse.class), false);
assertNull(result); assertNull(result);
} }
@Test
public void testInvokeAbstract() throws IOException
{
AbstractResourceWebScript executor = (AbstractResourceWebScript) applicationContext.getBean("executorOfGets");
executor.setLocator(locator);
executor.setResolver(simpleMappingExceptionResolver);
executor.setJsonHelper(jsonHelper);
Map<String, String> templateVars = new HashMap();
templateVars.put("apiScope", "private");
templateVars.put("apiVersion", "1");
templateVars.put("apiName", "alfrescomock");
templateVars.put(ResourceLocator.COLLECTION_RESOURCE, "sheep");
executor.execute(executor.determineApi(templateVars), mockRequest(templateVars,new HashMap<String, List<String>>(1)), mock(WebScriptResponse.class));
WebScriptResponse response = mockResponse();
templateVars.put(ResourceLocator.COLLECTION_RESOURCE, "bad");
executor.execute(api, mockRequest(templateVars,new HashMap<String, List<String>>(1)), response);
//throws a runtime exception so INTERNAL_SERVER_ERROR
verify(response, times(1)).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response = mockResponse();
templateVars.put(ResourceLocator.ENTITY_ID, "badId");
executor.execute(api, mockRequest(templateVars,new HashMap<String, List<String>>(1)), response);
//throws a IntegrityException so 422
verify(response, times(1)).setStatus(422);
}
private WebScriptResponse mockResponse() throws IOException
{
WebScriptResponse res = mock(WebScriptResponse.class);
when(res.getOutputStream()).thenReturn(new ByteArrayOutputStream());
return res;
}
private WebScriptRequest mockRequest(Map<String, String> templateVars, final Map<String, List<String>> params)
{
final String[] paramNames = params.keySet().toArray(new String[]{});
WebScriptRequest request = mock(WebScriptRequest.class);
when(request.getServiceMatch()).thenReturn(new Match(null, templateVars,null));
when(request.getParameterNames()).thenReturn(paramNames);
when(request.getParameterValues(anyString())).thenAnswer(new Answer<String[]>() {
@Override
public String[] answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
return params.get((String) args[0]).toArray(new String[]{});
}
});
return request;
}
} }

View File

@@ -34,15 +34,21 @@
</bean> </bean>
<bean id="simpleMappingExceptionResolver" class="org.alfresco.rest.framework.core.exceptions.SimpleMappingExceptionResolver"> <bean id="simpleMappingExceptionResolver" class="org.alfresco.rest.framework.core.exceptions.SimpleMappingExceptionResolver">
<property name="exceptionMappings"> <property name="exceptionMappings">
<map> <map>
<entry key="org.alfresco.rest.framework.core.exceptions.ApiException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_INTERNAL_SERVER_ERROR}" /> <entry key="org.alfresco.rest.framework.core.exceptions.ApiException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_INTERNAL_SERVER_ERROR}" />
<entry key="org.alfresco.rest.framework.core.exceptions.InvalidArgumentException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_BAD_REQUEST}" /> <entry key="org.alfresco.rest.framework.core.exceptions.InvalidArgumentException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_BAD_REQUEST}" />
<entry key="org.alfresco.rest.framework.core.exceptions.NotFoundException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_FOUND}" /> <entry key="org.alfresco.rest.framework.core.exceptions.NotFoundException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_FOUND}" />
<entry key="org.alfresco.rest.framework.core.exceptions.PermissionDeniedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_FORBIDDEN}" /> <entry key="org.alfresco.rest.framework.core.exceptions.EntityNotFoundException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_FOUND}" />
<entry key="org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_METHOD_NOT_ALLOWED}" /> <entry key="org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_FOUND}" />
<entry key="org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_CONFLICT}" /> <entry key="org.alfresco.rest.framework.core.exceptions.PermissionDeniedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_FORBIDDEN}" />
<entry key="org.alfresco.rest.framework.core.exceptions.StaleEntityException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_CONFLICT}" /> <entry key="org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_METHOD_NOT_ALLOWED}" />
</map> <entry key="org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_CONFLICT}" />
<entry key="org.alfresco.rest.framework.core.exceptions.StaleEntityException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_CONFLICT}" />
<entry key="org.alfresco.rest.framework.core.exceptions.RequestEntityTooLargeException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_REQUEST_ENTITY_TOO_LARGE}" />
<entry key="org.alfresco.rest.framework.core.exceptions.DisabledServiceException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_IMPLEMENTED}" />
<entry key="org.alfresco.rest.framework.core.exceptions.InsufficientStorageException" value="507" />
<entry key="org.alfresco.repo.node.integrity.IntegrityException" value="422" />
</map>
</property> </property>
</bean> </bean>
<context:component-scan base-package="org.alfresco.rest.framework.tests.api"/> <context:component-scan base-package="org.alfresco.rest.framework.tests.api"/>