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 e30634f Implemented: Exception Mapper for GenericServiceException. > Improved: Cleaned up code for exception handling and moved the code to ErrorUtil. Still some improvements needed. (OFBIZ-11328) e30634f is described below commit e30634fba1b776219b9cc5674b15bf4d1b44fa53 Author: Girish Vasmatkar <[hidden email]> AuthorDate: Thu Oct 1 22:36:35 2020 +0530 Implemented: Exception Mapper for GenericServiceException. > Improved: Cleaned up code for exception handling and moved the code to ErrorUtil. Still some improvements needed. (OFBIZ-11328) --- .../apache/ofbiz/ws/rs/ServiceRequestFilter.java | 3 + .../ofbiz/ws/rs/ServiceRequestProcessor.java | 4 +- .../ofbiz/ws/rs/process/RestRequestHandler.java | 12 +++ .../ofbiz/ws/rs/process/ServiceRequestHandler.java | 99 ++---------------- .../rs/spi/impl/GenericServiceExceptionMapper.java | 116 +++++++++++++++++++++ .../org/apache/ofbiz/ws/rs/util/ErrorUtil.java | 75 +++++++++++++ 6 files changed, 218 insertions(+), 91 deletions(-) diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestFilter.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestFilter.java index 91f5f87..db6d1eb 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestFilter.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestFilter.java @@ -91,6 +91,9 @@ public class ServiceRequestFilter implements ContainerRequestFilter { if (!mdService.getAction().equalsIgnoreCase(method)) { throw new MethodNotAllowedException("HTTP " + method + " is not allowed on service '" + service + "'"); } + // If everything looks good, set the 'requestForService' property in the + // context. Indicates which service this request is for. + requestContext.setProperty("requestForService", service); } } diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestProcessor.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestProcessor.java index 9b737db..c851c03 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestProcessor.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestProcessor.java @@ -34,6 +34,7 @@ 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.ws.rs.util.ErrorUtil; import org.apache.ofbiz.ws.rs.util.RestApiUtil; public class ServiceRequestProcessor { @@ -78,8 +79,7 @@ public class ServiceRequestProcessor { } 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 ErrorUtil.buildErrorFromServiceResult(serviceName, result, request.getLocale()); } } } diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java index 0309cdf..fca1f28 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.Map; import javax.inject.Inject; +import javax.inject.Provider; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.HttpMethod; @@ -39,6 +40,7 @@ import org.glassfish.jersey.message.internal.MediaTypes; import org.glassfish.jersey.process.Inflector; import org.glassfish.jersey.server.ContainerRequest; import org.glassfish.jersey.server.ExtendedUriInfo; +import org.glassfish.jersey.spi.ExceptionMappers; public abstract class RestRequestHandler implements Inflector<ContainerRequestContext, Response> { @@ -60,6 +62,9 @@ public abstract class RestRequestHandler implements Inflector<ContainerRequestCo @Inject private HttpServletRequest httpRequest; + @Inject + private Provider<ExceptionMappers> mappers; + /** * @return the httpHeaders */ @@ -253,4 +258,11 @@ public abstract class RestRequestHandler implements Inflector<ContainerRequestCo arguments.putAll(extractQueryParameters(requestContext)); return execute(requestContext, arguments); } + + /** + * @return the mappers + */ + public Provider<ExceptionMappers> getMappers() { + return mappers; + } } 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 1ebfaa8..d274b46 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,24 +19,16 @@ 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.NotFoundException; import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; -import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.ofbiz.base.util.Debug; -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; @@ -44,16 +36,12 @@ 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.ErrorUtil; import org.apache.ofbiz.ws.rs.util.RestApiUtil; -import org.codehaus.groovy.runtime.InvokerInvocationException; public final class ServiceRequestHandler extends RestRequestHandler { private static final String MODULE = ServiceRequestHandler.class.getName(); - private static final String DEFAULT_MSG_UI_LABEL_RESOURCE = "ApiUiLabels"; private String service; public ServiceRequestHandler(String service) { @@ -65,13 +53,16 @@ public final class ServiceRequestHandler extends RestRequestHandler { * @return */ @Override - protected Response execute(ContainerRequestContext data, Map<String, Object> arguments) { + protected Response execute(ContainerRequestContext ctx, Map<String, Object> arguments) { + ctx.setProperty("requestForService", service); LocalDispatcher dispatcher = (LocalDispatcher) getServletContext().getAttribute("dispatcher"); Map<String, Object> serviceContext = null; try { serviceContext = dispatcher.getDispatchContext().makeValidContext(service, ModelService.IN_PARAM, arguments); } catch (GenericServiceException e) { Debug.logError(e, MODULE); + final ExceptionMapper<GenericServiceException> mapper = getMappers().get().findMapping(e); + return mapper.toResponse(e); } ModelService svc = getModelService(dispatcher.getDispatchContext()); GenericValue userLogin = (GenericValue) getHttpRequest().getAttribute("userLogin"); @@ -80,7 +71,9 @@ public final class ServiceRequestHandler extends RestRequestHandler { try { result = dispatcher.runSync(service, serviceContext); } catch (GenericServiceException e) { - return handleException(e); + Debug.logError(e, MODULE); + final ExceptionMapper<GenericServiceException> mapper = getMappers().get().findMapping(e); + return mapper.toResponse(e); } Map<String, Object> responseData = new LinkedHashMap<>(); if (ServiceUtil.isSuccess(result)) { @@ -96,7 +89,7 @@ public final class ServiceRequestHandler extends RestRequestHandler { } return RestApiUtil.success((String) result.get(ModelService.SUCCESS_MESSAGE), responseData); } else { - return errorFromServiceResult(service, result); + return ErrorUtil.buildErrorFromServiceResult(service, result, getHttpRequest().getLocale()); } } @@ -109,76 +102,4 @@ 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/spi/impl/GenericServiceExceptionMapper.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/spi/impl/GenericServiceExceptionMapper.java new file mode 100644 index 0000000..3fda264 --- /dev/null +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/spi/impl/GenericServiceExceptionMapper.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.apache.ofbiz.ws.rs.spi.impl; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; + +import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.ofbiz.base.util.Debug; +import org.apache.ofbiz.entity.GenericEntityException; +import org.apache.ofbiz.entity.GenericEntityNotFoundException; +import org.apache.ofbiz.entity.GenericNoSuchEntityException; +import org.apache.ofbiz.service.GenericServiceException; +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.spi.AbstractExceptionMapper; +import org.apache.ofbiz.ws.rs.util.ErrorUtil; +import org.codehaus.groovy.runtime.InvokerInvocationException; + +/** + * + * Exception Mapper for GenericServiceException. Catches GenericServiceException and handles it and prepares appropriate response. + * + */ +@Provider +public class GenericServiceExceptionMapper extends AbstractExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<GenericServiceException> { + + /** + * Module Name Used for debugging + */ + private static final String MODULE = GenericServiceExceptionMapper.class.getName(); + + @Context + private HttpServletRequest request; + + @Context + private ContainerRequestContext crc; + + /** + * To response response. + * + * @param throwable the throwable + * @return the response + */ + @Override + public Response toResponse(GenericServiceException gse) { + Debug.logError(gse.getMessage(), MODULE); + Response.ResponseBuilder builder = null; + Throwable actualCause = gse.getCause(); + if (actualCause == null) { + actualCause = gse; + } else if (actualCause instanceof InvokerInvocationException) { + actualCause = actualCause.getCause(); + } + String service = (String) crc.getProperty("requestForService"); + 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(ErrorUtil.getErrorMessage(service, "GenericServiceValidationErrorMessage", request.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(ErrorUtil.getErrorMessage(service, "NoSuchEntityDefaultMessage", request.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(ErrorUtil.getErrorMessage(service, "GenericServiceExecutionGenericEntityOperationErrorMessage", + request.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(ErrorUtil.getErrorMessage(service, "GenericServiceExecutionGenericExceptionErrorMessage", + request.getLocale())) + .errorDesc(ExceptionUtils.getRootCauseMessage(gse)); + builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON) + .entity(error); + } + return builder.build(); + } +} diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/ErrorUtil.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/ErrorUtil.java new file mode 100644 index 0000000..1842175 --- /dev/null +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/ErrorUtil.java @@ -0,0 +1,75 @@ +/** + * + */ +package org.apache.ofbiz.ws.rs.util; + +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.ofbiz.base.util.UtilProperties; +import org.apache.ofbiz.base.util.UtilValidate; +import org.apache.ofbiz.service.ModelService; +import org.apache.ofbiz.ws.rs.core.ResponseStatus; +import org.apache.ofbiz.ws.rs.response.Error; + +public final class ErrorUtil { + + private ErrorUtil() { + + } + + private static final String DEFAULT_MSG_UI_LABEL_RESOURCE = "ApiUiLabels"; + + @SuppressWarnings("unchecked") + public static Response buildErrorFromServiceResult(String service, Map<String, Object> result, Locale locale) { + 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", locale)).errorDesc(errorMessage); + return Response.status(ResponseStatus.Custom.UNPROCESSABLE_ENTITY).type(MediaType.APPLICATION_JSON) + .entity(error).build(); + } + + public static 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; + } +} |
Free forum by Nabble | Edit this page |