This is an automated email from the ASF dual-hosted git repository.
grv pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ofbiz-plugins.git The following commit(s) were added to refs/heads/trunk by this push: new 43d4c0b Improved: Error handling for the response and added new error 422 (Unprocessable Entity) to handle validation errors(OFBIZ-11995) 43d4c0b is described below commit 43d4c0bd9899b1a22a453cf06a91c3d934cde3c2 Author: Girish Vasmatkar <[hidden email]> AuthorDate: Mon Sep 21 17:02:24 2020 +0530 Improved: Error handling for the response and added new error 422 (Unprocessable Entity) to handle validation errors(OFBIZ-11995) --- ofbiz-rest-impl/config/ApiUiLabels.xml | 15 ++++ .../ofbiz/ws/rs/process/ServiceRequestHandler.java | 93 +++++++++++++++++++-- .../org/apache/ofbiz/ws/rs/response/Error.java | 96 ++++++++++++++++++++++ .../ws/rs/response/{Error.java => Response.java} | 55 +++++-------- 4 files changed, 221 insertions(+), 38 deletions(-) diff --git a/ofbiz-rest-impl/config/ApiUiLabels.xml b/ofbiz-rest-impl/config/ApiUiLabels.xml index 2071e6e..88795e0 100644 --- a/ofbiz-rest-impl/config/ApiUiLabels.xml +++ b/ofbiz-rest-impl/config/ApiUiLabels.xml @@ -40,4 +40,19 @@ under the License. <value xml:lang="zh">不允许你浏览这个页面。</value> <value xml:lang="zh-TW">不允許您檢視這個頁面.</value> </property> + <property key="GenericServiceValidationErrorMessage"> + <value xml:lang="en">${service} validation failed. The request contained invalid information and could not be processed.</value> + </property> + <property key="GenericServiceExecutionGenericEntityOperationErrorMessage"> + <value xml:lang="en">${service} execution failed. The request contained invalid information and could not be processed.</value> + </property> + <property key="GenericServiceExecutionGenericExceptionErrorMessage"> + <value xml:lang="en">${service} execution failed. The service encountered an error; please try again later.</value> + </property> + <property key="NoSuchEntityDefaultMessage"> + <value xml:lang="en">${service} execution failed. The requested entity does not exist.</value> + </property> + <property key="GenericServiceErrorMessage"> + <value xml:lang="en">${service} returned error. The request contained invalid information and could not be processed.</value> + </property> </resource> diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java index 51ce63b..b51e3fe 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java @@ -19,15 +19,23 @@ package org.apache.ofbiz.ws.rs.process; import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; -import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.NotFoundException; import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.ofbiz.base.util.UtilProperties; import org.apache.ofbiz.base.util.UtilValidate; +import org.apache.ofbiz.entity.GenericEntityException; +import org.apache.ofbiz.entity.GenericEntityNotFoundException; +import org.apache.ofbiz.entity.GenericNoSuchEntityException; import org.apache.ofbiz.entity.GenericValue; import org.apache.ofbiz.service.DispatchContext; import org.apache.ofbiz.service.GenericServiceException; @@ -35,10 +43,15 @@ import org.apache.ofbiz.service.LocalDispatcher; import org.apache.ofbiz.service.ModelParam; import org.apache.ofbiz.service.ModelService; import org.apache.ofbiz.service.ServiceUtil; +import org.apache.ofbiz.service.ServiceValidationException; +import org.apache.ofbiz.ws.rs.core.ResponseStatus; +import org.apache.ofbiz.ws.rs.response.Error; import org.apache.ofbiz.ws.rs.util.RestApiUtil; +import org.codehaus.groovy.runtime.InvokerInvocationException; public final class ServiceRequestHandler extends RestRequestHandler { + private static final String DEFAULT_MSG_UI_LABEL_RESOURCE = "ApiUiLabels"; private String service; public ServiceRequestHandler(String service) { @@ -68,7 +81,7 @@ public final class ServiceRequestHandler extends RestRequestHandler { try { result = dispatcher.runSync(service, serviceContext); } catch (GenericServiceException e) { - throw new InternalServerErrorException(e.getMessage()); + return handleException(e); } Map<String, Object> responseData = new LinkedHashMap<>(); if (ServiceUtil.isSuccess(result)) { @@ -84,9 +97,7 @@ public final class ServiceRequestHandler extends RestRequestHandler { } return RestApiUtil.success((String) result.get(ModelService.SUCCESS_MESSAGE), responseData); } else { - return RestApiUtil.error(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), - Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase(), - (String) result.get(ModelService.ERROR_MESSAGE)); + return errorFromServiceResult(service, result); } } @@ -99,4 +110,76 @@ public final class ServiceRequestHandler extends RestRequestHandler { } return svc; } + + private Response handleException(GenericServiceException gse) { + Response.ResponseBuilder builder = null; + Throwable actualCause = gse.getCause(); + if (actualCause == null) { + actualCause = gse; + } else if (actualCause instanceof InvokerInvocationException) { + actualCause = actualCause.getCause(); + } + + if (actualCause instanceof ServiceValidationException) { + ServiceValidationException validationException = (ServiceValidationException) actualCause; + Error error = new Error().type(actualCause.getClass().getSimpleName()).code(Response.Status.BAD_REQUEST.getStatusCode()) + .description(Response.Status.BAD_REQUEST.getReasonPhrase()) + .message(getErrorMessage(service, "GenericServiceValidationErrorMessage", getHttpRequest().getLocale())) + .errorDesc((validationException.getMessage())).additionalErrors(validationException.getMessageList()); + builder = Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON).entity(error); + } else if (actualCause instanceof GenericNoSuchEntityException + || actualCause instanceof GenericEntityNotFoundException) { + Error error = new Error().type(actualCause.getClass().getSimpleName()).code(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .description(Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase()) + .message(getErrorMessage(service, "NoSuchEntityDefaultMessage", getHttpRequest().getLocale())) + .errorDesc(ExceptionUtils.getRootCauseMessage(gse)); + builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON) + .entity(error); + } else if (actualCause instanceof GenericEntityException) { + Error error = new Error().type(actualCause.getClass().getSimpleName()).code(ResponseStatus.Custom.UNPROCESSABLE_ENTITY.getStatusCode()) + .description(ResponseStatus.Custom.UNPROCESSABLE_ENTITY.getReasonPhrase()) + .message(getErrorMessage(service, "GenericServiceExecutionGenericEntityOperationErrorMessage", getHttpRequest().getLocale())) + .errorDesc(ExceptionUtils.getRootCauseMessage(gse)); + builder = Response.status(ResponseStatus.Custom.UNPROCESSABLE_ENTITY).type(MediaType.APPLICATION_JSON) + .entity(error); + } else { + Error error = new Error().type(actualCause.getClass().getSimpleName()).code(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .description(Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase()) + .message(getErrorMessage(service, "GenericServiceExecutionGenericExceptionErrorMessage", getHttpRequest().getLocale())) + .errorDesc(ExceptionUtils.getRootCauseMessage(gse)); + builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON) + .entity(error); + } + return builder.build(); + } + + private String getErrorMessage(String serviceName, String errorKey, Locale locale) { + String error = UtilProperties.getMessage(DEFAULT_MSG_UI_LABEL_RESOURCE, errorKey, locale); + error = error.replace("${service}", serviceName); + return error; + } + + @SuppressWarnings("unchecked") + private Response errorFromServiceResult(String service, Map<String, Object> result) { + String errorMessage = null; + List<String> additionalErrorMessages = new LinkedList<>(); + if (!UtilValidate.isEmpty(result.get(ModelService.ERROR_MESSAGE))) { + errorMessage = result.get(ModelService.ERROR_MESSAGE).toString(); + } + if (!UtilValidate.isEmpty(result.get(ModelService.ERROR_MESSAGE_LIST))) { + List<String> errorMessageList = (List<String>) result.get(ModelService.ERROR_MESSAGE_LIST); + if (UtilValidate.isEmpty(errorMessage)) { + errorMessage = errorMessageList.get(0); + errorMessageList.remove(0); + } + for (int i = 0; i < errorMessageList.size(); i++) { + additionalErrorMessages.add(errorMessageList.get(i)); + } + } + Error error = new Error().type("ServiceError").code(ResponseStatus.Custom.UNPROCESSABLE_ENTITY.getStatusCode()) + .description(ResponseStatus.Custom.UNPROCESSABLE_ENTITY.getReasonPhrase()) + .message(getErrorMessage(service, "GenericServiceErrorMessage", getHttpRequest().getLocale())) + .errorDesc(errorMessage); + return Response.status(ResponseStatus.Custom.UNPROCESSABLE_ENTITY).type(MediaType.APPLICATION_JSON).entity(error).build(); + } } diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Error.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Error.java index 24c7732..6f093d6 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Error.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Error.java @@ -20,16 +20,28 @@ package org.apache.ofbiz.ws.rs.response; import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRootName; @JsonRootName(value = "error") +@JsonPropertyOrder({ "statusCode", "statusDescription", "errorType", "errorMessage", "errorDescription", + "additionalErrors" }) public class Error { private int statusCode; private String statusDescription; private String errorMessage; + @JsonProperty("errorType") + private String type; + @JsonProperty("errorDescription") + private String errorDesc; private List<String> additionalErrors; + public Error() { + + } + public Error(int statusCode, String statusDescription, String errorMessage) { this.statusCode = statusCode; this.statusDescription = statusDescription; @@ -44,6 +56,69 @@ public class Error { } /** + * @param statusCode + * @return + */ + public Error code(int statusCode) { + this.statusCode = statusCode; + return this; + } + + /** + * @param statusDescription + * @return + */ + public Error description(String statusDescription) { + this.statusDescription = statusDescription; + return this; + } + + /** + * @param errorMessage + * @return + */ + public Error message(String errorMessage) { + this.errorMessage = errorMessage; + return this; + } + + /** + * @param type + * @return + */ + public Error type(String type) { + this.type = type; + return this; + } + + /** + * @param statusCode + * @return + */ + public Error statusCode(int statusCode) { + this.statusCode = statusCode; + return this; + } + + /** + * @param additionalErrors + * @return + */ + public Error additionalErrors(List<String> additionalErrors) { + this.additionalErrors = additionalErrors; + return this; + } + + /** + * @param errorDesc + * @return + */ + public Error errorDesc(String errorDesc) { + this.setErrorDesc(errorDesc); + return this; + } + + /** * @return the statusCode */ public int getStatusCode() { @@ -51,6 +126,13 @@ public class Error { } /** + * @return the type + */ + public String getType() { + return type; + } + + /** * @param statusCode the statusCode to set */ public void setStatusCode(int statusCode) { @@ -99,4 +181,18 @@ public class Error { this.additionalErrors = additionalErrors; } + /** + * @return the errorDesc + */ + public String getErrorDesc() { + return errorDesc; + } + + /** + * @param errorDesc the errorDesc to set + */ + public void setErrorDesc(String errorDesc) { + this.errorDesc = errorDesc; + } + } diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Error.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Response.java similarity index 58% copy from ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Error.java copy to ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Response.java index 24c7732..f513eca 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Error.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/response/Response.java @@ -18,30 +18,19 @@ *******************************************************************************/ package org.apache.ofbiz.ws.rs.response; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonRootName; - -@JsonRootName(value = "error") -public class Error { +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +@JsonPropertyOrder({ "statusCode", "statusDescription", "data", "error" }) +@JsonInclude(Include.NON_NULL) +public class Response { private int statusCode; private String statusDescription; - private String errorMessage; - private List<String> additionalErrors; - - public Error(int statusCode, String statusDescription, String errorMessage) { - this.statusCode = statusCode; - this.statusDescription = statusDescription; - this.errorMessage = errorMessage; - } - - public Error(int statusCode, String statusDescription, String errorMessage, List<String> additionalErrors) { - this.statusCode = statusCode; - this.statusDescription = statusDescription; - this.errorMessage = errorMessage; - this.additionalErrors = additionalErrors; - } + @JsonProperty("payload") + private Success success; + private Error error; /** * @return the statusCode @@ -72,31 +61,31 @@ public class Error { } /** - * @return the errorMessage + * @return the success */ - public String getErrorMessage() { - return errorMessage; + public Success getSuccess() { + return success; } /** - * @param errorMessage the errorMessage to set + * @param success the success to set */ - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; + public void setSuccess(Success success) { + this.success = success; } /** - * @return the additionalErrors + * @return the error */ - public List<String> getAdditionalErrors() { - return additionalErrors; + public Error getError() { + return error; } /** - * @param additionalErrors the additionalErrors to set + * @param error the error to set */ - public void setAdditionalErrors(List<String> additionalErrors) { - this.additionalErrors = additionalErrors; + public void setError(Error error) { + this.error = error; } } |
Free forum by Nabble | Edit this page |