Merged API-STRIKES-BACK (5.2.0) to HEAD (5.2)

125761 gjames: RA-652: new stack trace message and logId property


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@127564 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jamal Kaabi-Mofrad
2016-06-02 21:38:35 +00:00
parent b76f006c7f
commit f9eb72c7ef
5 changed files with 34 additions and 18 deletions

View File

@@ -13,4 +13,5 @@ framework.exception.UnsupportedResourceOperation=The operation is unsupported
framework.exception.DeletedResource=In this version of the REST API resource {0} has been deleted
framework.exception.RequestEntityTooLarge=Request entity too large
framework.exception.InsufficientStorage=Content storage quota exceeded
framework.no.stacktrace=For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.

View File

@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
*/
public class DefaultExceptionResolver implements ExceptionResolver<Exception>
{
public static final String STACK_MESSAGE_ID = "framework.no.stacktrace";
public static final String ERROR_URL = "https://api-explorer.alfresco.com";
public static final String DEFAULT_MESSAGE_ID = "framework.exception.ApiDefault";

View File

@@ -11,12 +11,13 @@ import java.util.Map;
*/
public class ErrorResponse
{
final private String errorKey;
final private int statusCode;
final private String briefSummary;
final private String stackTrace;
final private Map<String,Object> additionalState;
final private String descriptionURL;
private final String errorKey;
private final int statusCode;
private final String briefSummary;
private final String stackTrace;
private final Map<String,Object> additionalState;
private final String descriptionURL;
private final String logId;
public ErrorResponse(String errorKey, int statusCode, String briefSummary,
StackTraceElement[] stackTrace, Map<String,Object> additionalState)
@@ -28,16 +29,18 @@ public class ErrorResponse
this.stackTrace = Arrays.toString(stackTrace);
this.additionalState = additionalState==null?null:Collections.unmodifiableMap(additionalState);
this.descriptionURL = null;
this.logId = null;
}
public ErrorResponse(String errorKey, int statusCode, String briefSummary,
String stackTrace, Map<String,Object> additionalState, String descriptionURL)
String stackMessage, String logId, Map<String,Object> additionalState, String descriptionURL)
{
super();
this.errorKey = errorKey;
this.statusCode = statusCode;
this.briefSummary = briefSummary;
this.stackTrace = stackTrace;
this.stackTrace = stackMessage;
this.logId = logId;
this.additionalState = additionalState==null?null:Collections.unmodifiableMap(additionalState);
this.descriptionURL = descriptionURL;
}
@@ -72,6 +75,10 @@ public class ErrorResponse
return this.additionalState;
}
public String getLogId() {
return logId;
}
@Override
public String toString()
{
@@ -79,6 +86,7 @@ public class ErrorResponse
builder.append("ErrorResponse [errorKey=").append(this.errorKey).append(", statusCode=")
.append(this.statusCode).append(", briefSummary=").append(this.briefSummary)
.append(", descriptionURL=").append(this.descriptionURL)
.append(", logId=").append(this.logId)
.append(", stackTrace=").append(this.stackTrace).append(", additionalState=")
.append(this.additionalState).append("]");
return builder.toString();

View File

@@ -43,6 +43,7 @@ import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.json.simple.JSONObject;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.webscripts.*;
import org.springframework.extensions.webscripts.Description.RequiredCache;
import org.springframework.extensions.webscripts.servlet.WebScriptServletResponse;
@@ -202,18 +203,21 @@ public abstract class ApiWebScript extends AbstractWebScript
*/
public void renderErrorResponse(ErrorResponse errorResponse, final WebScriptResponse res) throws IOException {
String logKey = " ";
String logId = "";
if (Status.STATUS_INTERNAL_SERVER_ERROR == errorResponse.getStatusCode() || logger.isDebugEnabled())
{
logKey = GUID.generate();
logger.error(logKey+" : "+errorResponse.getStackTrace());
logId = GUID.generate();
logger.error(logId+" : "+errorResponse.getStackTrace());
}
String stackMessage = I18NUtil.getMessage(DefaultExceptionResolver.STACK_MESSAGE_ID);
final ErrorResponse errorToWrite = new ErrorResponse(errorResponse.getErrorKey(),
errorResponse.getStatusCode(),
errorResponse.getBriefSummary(),
logKey,
stackMessage,
logId,
errorResponse.getAdditionalState(),
DefaultExceptionResolver.ERROR_URL);

View File

@@ -287,20 +287,22 @@ public class ExecutionTests extends AbstractContextTest
ByteArrayOutputStream out = new ByteArrayOutputStream();
executor.renderErrorResponse(defaultError, mockResponse(out));
String errorMessage = out.toString();
//System.out.println(errorMessage);
// System.out.println(errorMessage);
assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.ApiDefault\""));
assertTrue(errorMessage.contains("\"statusCode\":500"));
assertTrue(errorMessage.contains("\"stackTrace\":\""));
assertTrue(errorMessage.contains("\"logId\":\""));
assertTrue(errorMessage.contains("\"stackTrace\":\"For security reasons the stack trace is no longer displayed"));
assertTrue(errorMessage.contains("\"descriptionURL\":\""+DefaultExceptionResolver.ERROR_URL+"\""));
ErrorResponse anError = simpleMappingExceptionResolver.resolveException(new ApiException("nothing"));
out = new ByteArrayOutputStream();
executor.renderErrorResponse(anError, mockResponse(out));
errorMessage = out.toString();
System.out.println(errorMessage);
// System.out.println(errorMessage);
assertTrue(errorMessage.contains("\"errorKey\":\"nothing\""));
assertTrue(errorMessage.contains("\"statusCode\":500"));
assertTrue(errorMessage.contains("\"stackTrace\":\""));
assertTrue(errorMessage.contains("\"stackTrace\":\"For security reasons the stack trace is no longer displayed"));
assertTrue(errorMessage.contains("\"logId\":\""));
anError = simpleMappingExceptionResolver.resolveException(new EntityNotFoundException("2"));
out = new ByteArrayOutputStream();
@@ -309,7 +311,7 @@ public class ExecutionTests extends AbstractContextTest
System.out.println(errorMessage);
assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.EntityNotFound\""));
assertTrue(errorMessage.contains("\"statusCode\":404"));
assertTrue("Only 500 errors should have a stracktrace", errorMessage.contains("\"stackTrace\":\" \""));
assertFalse("Only 500 errors should have a logId", errorMessage.contains("\"logId\":\" \""));
}
private WebScriptResponse mockResponse() throws IOException