mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
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:
@@ -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.DeletedResource=In this version of the REST API resource {0} has been deleted
|
||||||
framework.exception.RequestEntityTooLarge=Request entity too large
|
framework.exception.RequestEntityTooLarge=Request entity too large
|
||||||
framework.exception.InsufficientStorage=Content storage quota exceeded
|
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.
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
*/
|
*/
|
||||||
public class DefaultExceptionResolver implements ExceptionResolver<Exception>
|
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 ERROR_URL = "https://api-explorer.alfresco.com";
|
||||||
public static final String DEFAULT_MESSAGE_ID = "framework.exception.ApiDefault";
|
public static final String DEFAULT_MESSAGE_ID = "framework.exception.ApiDefault";
|
||||||
|
|
||||||
|
@@ -11,13 +11,14 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class ErrorResponse
|
public class ErrorResponse
|
||||||
{
|
{
|
||||||
final private String errorKey;
|
private final String errorKey;
|
||||||
final private int statusCode;
|
private final int statusCode;
|
||||||
final private String briefSummary;
|
private final String briefSummary;
|
||||||
final private String stackTrace;
|
private final String stackTrace;
|
||||||
final private Map<String,Object> additionalState;
|
private final Map<String,Object> additionalState;
|
||||||
final private String descriptionURL;
|
private final String descriptionURL;
|
||||||
|
private final String logId;
|
||||||
|
|
||||||
public ErrorResponse(String errorKey, int statusCode, String briefSummary,
|
public ErrorResponse(String errorKey, int statusCode, String briefSummary,
|
||||||
StackTraceElement[] stackTrace, Map<String,Object> additionalState)
|
StackTraceElement[] stackTrace, Map<String,Object> additionalState)
|
||||||
{
|
{
|
||||||
@@ -28,16 +29,18 @@ public class ErrorResponse
|
|||||||
this.stackTrace = Arrays.toString(stackTrace);
|
this.stackTrace = Arrays.toString(stackTrace);
|
||||||
this.additionalState = additionalState==null?null:Collections.unmodifiableMap(additionalState);
|
this.additionalState = additionalState==null?null:Collections.unmodifiableMap(additionalState);
|
||||||
this.descriptionURL = null;
|
this.descriptionURL = null;
|
||||||
|
this.logId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErrorResponse(String errorKey, int statusCode, String briefSummary,
|
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();
|
super();
|
||||||
this.errorKey = errorKey;
|
this.errorKey = errorKey;
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
this.briefSummary = briefSummary;
|
this.briefSummary = briefSummary;
|
||||||
this.stackTrace = stackTrace;
|
this.stackTrace = stackMessage;
|
||||||
|
this.logId = logId;
|
||||||
this.additionalState = additionalState==null?null:Collections.unmodifiableMap(additionalState);
|
this.additionalState = additionalState==null?null:Collections.unmodifiableMap(additionalState);
|
||||||
this.descriptionURL = descriptionURL;
|
this.descriptionURL = descriptionURL;
|
||||||
}
|
}
|
||||||
@@ -72,6 +75,10 @@ public class ErrorResponse
|
|||||||
return this.additionalState;
|
return this.additionalState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLogId() {
|
||||||
|
return logId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
@@ -79,6 +86,7 @@ public class ErrorResponse
|
|||||||
builder.append("ErrorResponse [errorKey=").append(this.errorKey).append(", statusCode=")
|
builder.append("ErrorResponse [errorKey=").append(this.errorKey).append(", statusCode=")
|
||||||
.append(this.statusCode).append(", briefSummary=").append(this.briefSummary)
|
.append(this.statusCode).append(", briefSummary=").append(this.briefSummary)
|
||||||
.append(", descriptionURL=").append(this.descriptionURL)
|
.append(", descriptionURL=").append(this.descriptionURL)
|
||||||
|
.append(", logId=").append(this.logId)
|
||||||
.append(", stackTrace=").append(this.stackTrace).append(", additionalState=")
|
.append(", stackTrace=").append(this.stackTrace).append(", additionalState=")
|
||||||
.append(this.additionalState).append("]");
|
.append(this.additionalState).append("]");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
|
@@ -43,6 +43,7 @@ import org.codehaus.jackson.JsonGenerator;
|
|||||||
import org.codehaus.jackson.map.JsonMappingException;
|
import org.codehaus.jackson.map.JsonMappingException;
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
import org.springframework.extensions.webscripts.*;
|
import org.springframework.extensions.webscripts.*;
|
||||||
import org.springframework.extensions.webscripts.Description.RequiredCache;
|
import org.springframework.extensions.webscripts.Description.RequiredCache;
|
||||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletResponse;
|
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 {
|
public void renderErrorResponse(ErrorResponse errorResponse, final WebScriptResponse res) throws IOException {
|
||||||
|
|
||||||
String logKey = " ";
|
String logId = "";
|
||||||
|
|
||||||
if (Status.STATUS_INTERNAL_SERVER_ERROR == errorResponse.getStatusCode() || logger.isDebugEnabled())
|
if (Status.STATUS_INTERNAL_SERVER_ERROR == errorResponse.getStatusCode() || logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logKey = GUID.generate();
|
logId = GUID.generate();
|
||||||
logger.error(logKey+" : "+errorResponse.getStackTrace());
|
logger.error(logId+" : "+errorResponse.getStackTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String stackMessage = I18NUtil.getMessage(DefaultExceptionResolver.STACK_MESSAGE_ID);
|
||||||
|
|
||||||
final ErrorResponse errorToWrite = new ErrorResponse(errorResponse.getErrorKey(),
|
final ErrorResponse errorToWrite = new ErrorResponse(errorResponse.getErrorKey(),
|
||||||
errorResponse.getStatusCode(),
|
errorResponse.getStatusCode(),
|
||||||
errorResponse.getBriefSummary(),
|
errorResponse.getBriefSummary(),
|
||||||
logKey,
|
stackMessage,
|
||||||
|
logId,
|
||||||
errorResponse.getAdditionalState(),
|
errorResponse.getAdditionalState(),
|
||||||
DefaultExceptionResolver.ERROR_URL);
|
DefaultExceptionResolver.ERROR_URL);
|
||||||
|
|
||||||
|
@@ -287,20 +287,22 @@ public class ExecutionTests extends AbstractContextTest
|
|||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
executor.renderErrorResponse(defaultError, mockResponse(out));
|
executor.renderErrorResponse(defaultError, mockResponse(out));
|
||||||
String errorMessage = out.toString();
|
String errorMessage = out.toString();
|
||||||
//System.out.println(errorMessage);
|
// System.out.println(errorMessage);
|
||||||
assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.ApiDefault\""));
|
assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.ApiDefault\""));
|
||||||
assertTrue(errorMessage.contains("\"statusCode\":500"));
|
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+"\""));
|
assertTrue(errorMessage.contains("\"descriptionURL\":\""+DefaultExceptionResolver.ERROR_URL+"\""));
|
||||||
|
|
||||||
ErrorResponse anError = simpleMappingExceptionResolver.resolveException(new ApiException("nothing"));
|
ErrorResponse anError = simpleMappingExceptionResolver.resolveException(new ApiException("nothing"));
|
||||||
out = new ByteArrayOutputStream();
|
out = new ByteArrayOutputStream();
|
||||||
executor.renderErrorResponse(anError, mockResponse(out));
|
executor.renderErrorResponse(anError, mockResponse(out));
|
||||||
errorMessage = out.toString();
|
errorMessage = out.toString();
|
||||||
System.out.println(errorMessage);
|
// System.out.println(errorMessage);
|
||||||
assertTrue(errorMessage.contains("\"errorKey\":\"nothing\""));
|
assertTrue(errorMessage.contains("\"errorKey\":\"nothing\""));
|
||||||
assertTrue(errorMessage.contains("\"statusCode\":500"));
|
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"));
|
anError = simpleMappingExceptionResolver.resolveException(new EntityNotFoundException("2"));
|
||||||
out = new ByteArrayOutputStream();
|
out = new ByteArrayOutputStream();
|
||||||
@@ -309,7 +311,7 @@ public class ExecutionTests extends AbstractContextTest
|
|||||||
System.out.println(errorMessage);
|
System.out.println(errorMessage);
|
||||||
assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.EntityNotFound\""));
|
assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.EntityNotFound\""));
|
||||||
assertTrue(errorMessage.contains("\"statusCode\":404"));
|
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
|
private WebScriptResponse mockResponse() throws IOException
|
||||||
|
Reference in New Issue
Block a user