[ofbiz-plugins] branch trunk updated: Implemented: Exception Mapper for GenericServiceException. > Improved: Cleaned up code for exception handling and moved the code to ErrorUtil. Still some improvements needed. (OFBIZ-11328)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[ofbiz-plugins] branch trunk updated: Implemented: Exception Mapper for GenericServiceException. > Improved: Cleaned up code for exception handling and moved the code to ErrorUtil. Still some improvements needed. (OFBIZ-11328)

grv-2
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;
+    }
+}