refactor base smartproc

This commit is contained in:
dirgantarasiahaan
2023-05-23 11:26:15 +07:00
parent 329d515577
commit beff4babe0
85 changed files with 1642 additions and 839 deletions

View File

@ -0,0 +1,49 @@
package com.iconplus.smartproc.exception;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.http.HttpStatus;
import java.util.Map;
@Setter
@Getter
@ToString
public class BaseException extends RuntimeException {
protected HttpStatus httpStatus;
protected String errorCode;
protected String errorDesc;
protected String errorMessage;
protected String rootCause;
protected Map<String, String> errorMessageMap;
public BaseException(HttpStatus httpStatus, String errorCode, String rootCause, String errorDesc, String errorMessage) {
super(rootCause);
this.httpStatus = httpStatus;
this.errorCode = errorCode;
this.errorDesc = errorDesc;
this.errorMessage = errorMessage;
}
public BaseException(HttpStatus httpStatus, String errorCode, String rootCause) {
super(rootCause);
this.httpStatus = httpStatus;
this.errorCode = errorCode;
}
public BaseException(String errorCode, String rootCause) {
super(rootCause);
this.errorCode = errorCode;
}
public BaseException(HttpStatus httpStatus, String errorCode, String rootCause, Map<String, String> errorMessageMap){
super(rootCause);
this.httpStatus = httpStatus;
this.errorCode = errorCode;
this.errorMessageMap = errorMessageMap;
}
}

View File

@ -0,0 +1,47 @@
package com.iconplus.smartproc.exception;
import org.springframework.http.HttpStatus;
import java.util.Map;
public class BusinessException extends BaseException {
public BusinessException(String errorCode, String errorDesc, String errorMessage) {
super(HttpStatus.CONFLICT, errorCode, "", errorDesc, errorMessage);
}
public BusinessException(HttpStatus httpStatus, String errorCode, String errorDesc, String errorMessage) {
super(httpStatus, errorCode, "", errorDesc, errorMessage);
}
public BusinessException(String errorCode) {
super(HttpStatus.CONFLICT, errorCode, "");
}
public BusinessException(HttpStatus httpStatus, String errorCode) {
super(httpStatus, errorCode, "");
}
public BusinessException(String errorCode, Map<String, String> maps) {
super(HttpStatus.CONFLICT, errorCode, "", maps);
}
public BusinessException(HttpStatus httpStatus, String errorCode, Map<String, String> maps) {
super(httpStatus, errorCode, "", maps);
}
public BusinessException(String errorCode, String rootCause) {
super(HttpStatus.CONFLICT, errorCode, rootCause);
}
public BusinessException(HttpStatus httpStatus, String errorCode, String rootCause) {
super(httpStatus, errorCode, rootCause);
}
public BusinessException(String errorCode, String rootCause, Map<String, String> maps) {
super(HttpStatus.CONFLICT, errorCode, rootCause, maps);
}
public BusinessException(HttpStatus httpStatus, String errorCode, String rootCause, Map<String, String> maps) {
super(httpStatus, errorCode, rootCause, maps);
}
}

View File

@ -0,0 +1,115 @@
package com.iconplus.smartproc.exception;
import lombok.extern.log4j.Log4j2;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import java.io.StringWriter;
import java.util.Map;
import static org.apache.velocity.runtime.RuntimeConstants.RESOURCE_LOADER;
@Configuration
@Log4j2
public class ErrorHelper {
public static final String RAW_TEMPLATE = "rawTemplate";
private final VelocityEngine engine;
public ErrorHelper() {
engine = new VelocityEngine();
this.addVelocityProperties();
engine.init();
}
public ResponseEntity<ErrorResponse> throwErrorException(String errorCode, HttpStatus httpStatus) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(errorCode);
errorResponse.setTitle("Kesalahan terjadi");
errorResponse.setMessage("Kesalahan terjadi");
return new ResponseEntity<>(errorResponse, new HttpHeaders(), httpStatus);
}
public ResponseEntity<ErrorResponse> throwErrorExceptionWithHardcodedMsg(String errorCode, HttpStatus httpStatus,
String errorDesc, String errorMsg) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(errorCode);
errorResponse.setTitle(errorDesc);
errorResponse.setMessage(errorMsg);
return new ResponseEntity<>(errorResponse, new HttpHeaders(), httpStatus);
}
public ResponseEntity<ErrorResponse> throwErrorExceptionWithMetadata(String errorCode, HttpStatus httpStatus,
Map<String, String> metadata) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(errorCode);
errorResponse.setTitle("Kesalahan terjadi");
errorResponse.setMessage(transform("Kesalahan terjadi", metadata));
return new ResponseEntity<>(errorResponse, new HttpHeaders(), httpStatus);
}
public ResponseEntity<ErrorResponse> throwErrorExceptionWithMessageAndMetadataWithoutLocalization(HttpStatus httpStatus, String errorCode, String errorTitle, String errorMessage,
Map<String, String> metadata) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(errorCode);
errorResponse.setTitle(errorTitle);
errorResponse.setMessage(transform(errorMessage, metadata));
return new ResponseEntity<>(errorResponse, new HttpHeaders(), httpStatus);
}
private String transform(String rawNotificationTemplate, Map<String, String> parameters) {
VelocityContext context = this.getVelocityContext(rawNotificationTemplate, parameters);
Template template = engine.getTemplate(RAW_TEMPLATE);
StringWriter templateWriter = new StringWriter(rawNotificationTemplate.length());
template.merge(context, templateWriter);
return templateWriter.toString();
}
private VelocityContext getVelocityContext(String rawNotificationTemplate, Map<String, String> parameters) {
StringResourceRepository resourceRepository = (StringResourceRepository) engine
.getApplicationAttribute(StringResourceLoader.REPOSITORY_NAME_DEFAULT);
resourceRepository.putStringResource(RAW_TEMPLATE, rawNotificationTemplate);
return new VelocityContext(parameters);
}
private void addVelocityProperties() {
Velocity.addProperty("string.resource.loader.description", "Velocity StringResource loader");
engine.addProperty(RESOURCE_LOADER, "string");
engine.addProperty("string.resource.loader.repository.static", "false");
engine.addProperty("string.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.StringResourceLoader");
engine.addProperty("string.resource.loader.repository.class",
"org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl");
engine.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogChute");
}
public ResponseEntity<ErrorResponse> throwErrorExceptionWithMessage(HttpStatus httpStatus, String errorCode, String errorTitle, String errorMessage) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(errorCode);
errorResponse.setTitle(errorTitle);
errorResponse.setMessage(errorMessage);
return new ResponseEntity<>(errorResponse, new HttpHeaders(), httpStatus);
}
}

View File

@ -0,0 +1,16 @@
package com.iconplus.smartproc.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ErrorResponse implements Serializable {
private String code;
private String title;
private String message;
}

View File

@ -0,0 +1,102 @@
package com.iconplus.smartproc.exception;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.client.HttpServerErrorException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeoutException;
@Log4j2
@ControllerAdvice
public class GlobalExceptionHandler {
private ErrorHelper errorHelper;
public GlobalExceptionHandler(ErrorHelper errorHelper) {
this.errorHelper = errorHelper;
}
private Boolean isError = false;
private static final String DEFAULT_ERROR_CODE = "80000";
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> renderDefaultResponse(Exception ex) {
log.error("Exception occurred: ", ex);
return errorHelper.throwErrorException(DEFAULT_ERROR_CODE, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> renderBusinessErrorResponse(BusinessException exception) {
log.error("BusinessException occurred: ", exception);
if (Objects.nonNull(exception.getErrorMessageMap())) {
return getErrorResponseResponseEntity(exception.getErrorDesc(), exception.getErrorMessage(), exception.getErrorCode(), exception.getHttpStatus(), exception.getErrorMessageMap());
}
return getErrorResponseResponseEntity(exception.getErrorDesc(), exception.getErrorMessage(), exception.getErrorCode(), exception.getHttpStatus(), null);
}
@ExceptionHandler(TechnicalException.class)
public ResponseEntity<ErrorResponse> renderTechnicalErrorResponse(TechnicalException exception) {
log.error("TechnicalException occurred: ", exception);
return getErrorResponseResponseEntity(exception.getErrorDesc(), exception.getErrorMessage(), exception.getErrorCode(), exception.getHttpStatus(), null);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> renderMethodArgumentErrorResponse(MethodArgumentNotValidException exception) {
log.error("MethodArgumentNotValidException occurred: ", exception);
List<String> errors = new ArrayList<String>();
for (FieldError error : exception.getBindingResult().getFieldErrors()) {
errors.add(error.getField().concat(":").concat(error.getDefaultMessage()));
}
return errorHelper.throwErrorExceptionWithMessage(HttpStatus.BAD_REQUEST, "80400", "Request Validation Error", errors.toString());
}
@ExceptionHandler(HttpServerErrorException.class)
public ResponseEntity<ErrorResponse> renderHttpServerErrorResponse(HttpServerErrorException exception) {
log.error("HttpServerErrorException occurred: ", exception);
return errorHelper.throwErrorException(DEFAULT_ERROR_CODE, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(TimeoutException.class)
public ResponseEntity<ErrorResponse> renderTimeoutResponse(TimeoutException exception) {
log.error("TimeoutException occurred: ", exception);
return errorHelper.throwErrorException("80001", HttpStatus.INTERNAL_SERVER_ERROR);
}
private ResponseEntity<ErrorResponse> getErrorResponseResponseEntity(String errorDesc, String errorMessage,
String errorCode, HttpStatus httpStatus,
Map<String, String> metadata) {
if (StringUtils.isNotBlank(errorDesc) && StringUtils.isNotBlank(errorMessage)) {
return errorHelper.throwErrorExceptionWithMessageAndMetadataWithoutLocalization(httpStatus, errorCode, errorDesc, errorMessage, metadata);
} else {
if (Objects.nonNull(metadata)) {
return errorHelper.throwErrorExceptionWithMetadata(errorCode, httpStatus, metadata);
}
return errorHelper.throwErrorException(errorCode, httpStatus);
}
}
public Boolean isError() {
return isError;
}
}

View File

@ -0,0 +1,69 @@
package com.iconplus.smartproc.exception;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@Log4j2
@Component
public class ResponseExceptionResolver extends AbstractHandlerExceptionResolver {
private static final String DEFAULT_ERROR_CODE = "80000";
public ResponseExceptionResolver() {}
@SneakyThrows
@Override
protected ModelAndView doResolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex
) {
return handleException(request, response, ex);
}
private ModelAndView handleException(
HttpServletRequest request,
HttpServletResponse response,
Exception exception
) {
if (ObjectUtils.isNotEmpty(response) && HttpStatus.UNAUTHORIZED.value() == response.getStatus()
&& ObjectUtils.isNotEmpty(exception) && exception instanceof BusinessException
) {
BusinessException businessException = (BusinessException) exception;
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(businessException.getErrorCode());
errorResponse.setTitle(businessException.getErrorDesc());
errorResponse.setMessage(businessException.getErrorMessage());
log.info("Error Response Exception : {}", errorResponse);
return new ModelAndView(new MappingJackson2JsonView(), this.getErrorResponse(errorResponse));
}
response.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(DEFAULT_ERROR_CODE);
errorResponse.setTitle("Kesalahan terjadi");
errorResponse.setMessage("Kesalahan terjadi");
return new ModelAndView(new MappingJackson2JsonView(), this.getErrorResponse(errorResponse));
}
private Map<String, String> getErrorResponse(ErrorResponse errorResponse) {
return new ObjectMapper().convertValue(errorResponse, new TypeReference<Map<String, String>>() {
});
}
}

View File

@ -0,0 +1,40 @@
package com.iconplus.smartproc.exception;
import org.springframework.http.HttpStatus;
import java.util.Map;
public class TechnicalException extends BaseException {
public TechnicalException(String errorCode, String errorDesc, String errorMessage) {
super(HttpStatus.INTERNAL_SERVER_ERROR, errorCode, "", errorDesc, errorMessage);
}
public TechnicalException(HttpStatus httpStatus, String errorCode, String errorDesc, String errorMessage){
super(httpStatus, errorCode, "", errorDesc, errorMessage);
}
public TechnicalException(String errorCode){
super(HttpStatus.INTERNAL_SERVER_ERROR, errorCode, "");
}
public TechnicalException(HttpStatus httpStatus, String errorCode){
super(httpStatus, errorCode, "");
}
public TechnicalException(String errorCode, String rootCause){
super(HttpStatus.INTERNAL_SERVER_ERROR, errorCode, rootCause);
}
public TechnicalException(HttpStatus httpStatus, String errorCode, String rootCause) {
super(httpStatus, errorCode, rootCause);
}
public TechnicalException(String errorCode, String rootCause, Map<String, String> maps) {
super(HttpStatus.CONFLICT, errorCode, rootCause, maps);
}
public TechnicalException(HttpStatus httpStatus, String errorCode, String rootCause, Map<String, String> maps) {
super(httpStatus, errorCode, rootCause, maps);
}
}