initial commit
This commit is contained in:
5
pom.xml
5
pom.xml
@@ -83,11 +83,6 @@
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
<version>5.2.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
15
src/main/java/zw/qantra/tm/exceptions/ApiException.java
Executable file
15
src/main/java/zw/qantra/tm/exceptions/ApiException.java
Executable file
@@ -0,0 +1,15 @@
|
||||
package zw.qantra.tm.exceptions;
|
||||
|
||||
public class ApiException extends RuntimeException {
|
||||
|
||||
private String message;
|
||||
|
||||
public ApiException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
99
src/main/java/zw/qantra/tm/exceptions/GeneralExceptionHandler.java
Executable file
99
src/main/java/zw/qantra/tm/exceptions/GeneralExceptionHandler.java
Executable file
@@ -0,0 +1,99 @@
|
||||
package zw.qantra.tm.exceptions;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
import zw.qantra.tm.rest.ApiResponse;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* * Handle all exceptions and java bean validation errors
|
||||
* for all endpoints' income data that use the @Valid annotation
|
||||
*
|
||||
* @author Ehab Qadah
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class GeneralExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass().getName());
|
||||
|
||||
public static final String ACCESS_DENIED = "Access denied!";
|
||||
public static final String INVALID_REQUEST = "Invalid request";
|
||||
public static final String ERROR_MESSAGE_TEMPLATE = "message: %s %n requested uri: %s";
|
||||
public static final String LIST_JOIN_DELIMITER = ",";
|
||||
public static final String FIELD_ERROR_SEPARATOR = ": ";
|
||||
private static final String ERRORS_FOR_PATH = "errors {} for path {}";
|
||||
private static final String PATH = "path";
|
||||
private static final String ERRORS = "error";
|
||||
private static final String STATUS = "status";
|
||||
private static final String MESSAGE = "message";
|
||||
private static final String TIMESTAMP = "timestamp";
|
||||
private static final String TYPE = "type";
|
||||
private static final String BODY = "body";
|
||||
|
||||
/**
|
||||
* A general handler for all uncaught exceptions
|
||||
*/
|
||||
@ExceptionHandler({Exception.class})
|
||||
public ResponseEntity<Object> handleAllExceptions(Exception exception, WebRequest request) {
|
||||
exception.printStackTrace();
|
||||
ResponseStatus responseStatus =
|
||||
exception.getClass().getAnnotation(ResponseStatus.class);
|
||||
final HttpStatus status =
|
||||
responseStatus!=null ? responseStatus.value():HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
final String localizedMessage = exception.getLocalizedMessage();
|
||||
final String path = request.getDescription(false);
|
||||
String message = (StringUtils.isNotEmpty(localizedMessage) ? localizedMessage:status.getReasonPhrase());
|
||||
|
||||
return getExceptionResponseEntity(exception, status, request, Collections.singletonList(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build detailed information about the exception in the response
|
||||
*/
|
||||
private ResponseEntity<Object> getExceptionResponseEntity(final Exception exception,
|
||||
final HttpStatus status,
|
||||
final WebRequest request,
|
||||
final List<String> errors) {
|
||||
final Map<String, Object> body = new LinkedHashMap<>();
|
||||
final String path = request.getDescription(false);
|
||||
body.put(TIMESTAMP, Instant.now());
|
||||
body.put(STATUS, status.value());
|
||||
body.put(ERRORS, errors);
|
||||
body.put(TYPE, exception.getClass().getSimpleName());
|
||||
body.put(PATH, path);
|
||||
body.put(BODY, request.getAttribute("mobileNumber", RequestAttributes.SCOPE_REQUEST));
|
||||
body.put(MESSAGE, getMessageForStatus(status));
|
||||
final String errorsMessage = CollectionUtils.isNotEmpty(errors) ?
|
||||
errors.stream().filter(StringUtils::isNotEmpty).collect(Collectors.joining(LIST_JOIN_DELIMITER))
|
||||
:status.getReasonPhrase();
|
||||
logger.info(ERRORS_FOR_PATH, errorsMessage, path);
|
||||
return ApiResponse.build(status, getMessageForStatus(status), null, errors, false);
|
||||
}
|
||||
|
||||
private String getMessageForStatus(HttpStatus status) {
|
||||
switch (status) {
|
||||
case UNAUTHORIZED:
|
||||
return ACCESS_DENIED;
|
||||
case BAD_REQUEST:
|
||||
return INVALID_REQUEST;
|
||||
default:
|
||||
return status.getReasonPhrase();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/main/java/zw/qantra/tm/exceptions/RestException.java
Executable file
25
src/main/java/zw/qantra/tm/exceptions/RestException.java
Executable file
@@ -0,0 +1,25 @@
|
||||
package zw.qantra.tm.exceptions;
|
||||
|
||||
public class RestException extends RuntimeException {
|
||||
|
||||
private String message;
|
||||
private Object responsePayload;
|
||||
|
||||
public RestException(Object responsePayload, String message) {
|
||||
this.responsePayload = responsePayload;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Object getResponsePayload() {
|
||||
return responsePayload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
46
src/main/java/zw/qantra/tm/exceptions/RestTemplateResponseErrorHandler.java
Executable file
46
src/main/java/zw/qantra/tm/exceptions/RestTemplateResponseErrorHandler.java
Executable file
@@ -0,0 +1,46 @@
|
||||
package zw.qantra.tm.exceptions;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RestTemplateResponseErrorHandler
|
||||
implements ResponseErrorHandler {
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass().toString());
|
||||
|
||||
@Override
|
||||
public boolean hasError(ClientHttpResponse httpResponse)
|
||||
throws IOException {
|
||||
return (
|
||||
httpResponse.getStatusCode().is5xxServerError()
|
||||
|| httpResponse.getStatusCode().is4xxClientError());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse httpResponse)
|
||||
throws IOException {
|
||||
|
||||
logger.info("Rest error code: " + httpResponse.getStatusCode());
|
||||
|
||||
if (httpResponse.getStatusCode()
|
||||
.is5xxServerError()) {
|
||||
// handle SERVER_ERROR
|
||||
logger.info("Server Error");
|
||||
} else if (httpResponse.getStatusCode().is4xxClientError()) {
|
||||
// handle CLIENT_ERROR
|
||||
logger.info("Client Error");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getBody()));
|
||||
String httpBodyResponse = reader.lines().collect(Collectors.joining(""));
|
||||
|
||||
throw new RestException(httpBodyResponse, "Client Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
80
src/main/java/zw/qantra/tm/rest/ApiResponse.java
Executable file
80
src/main/java/zw/qantra/tm/rest/ApiResponse.java
Executable file
@@ -0,0 +1,80 @@
|
||||
package zw.qantra.tm.rest;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiResponse {
|
||||
|
||||
private String message;
|
||||
private HashMap<Object, Object> response;
|
||||
private Boolean success;
|
||||
private HashMap<Object, Object> body;
|
||||
|
||||
private Map<String, ?> errors = new HashMap<>();
|
||||
|
||||
// private Object body;
|
||||
|
||||
private HttpStatus status = HttpStatus.OK;
|
||||
|
||||
public ApiResponse(String message) {
|
||||
super();
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
public ResponseEntity ApiResponse(Object obj, HttpStatus status) {
|
||||
return new ResponseEntity<Object>(obj, status);
|
||||
}
|
||||
|
||||
public static ResponseEntity ok(Object obj){
|
||||
return ApiResponse.build(HttpStatus.OK, "SUCCESSFUL", obj, null, true);
|
||||
}
|
||||
|
||||
public static ResponseEntity created(Object obj){
|
||||
return ApiResponse.build(HttpStatus.CREATED, "CREATED", obj, null, true);
|
||||
}
|
||||
|
||||
public static ResponseEntity badRequest(Object obj){
|
||||
return ApiResponse.build(HttpStatus.BAD_REQUEST, "BAD REQUEST", null, obj, false);
|
||||
}
|
||||
|
||||
public static ResponseEntity notFound(){
|
||||
return ApiResponse.build(HttpStatus.NOT_FOUND, "NOT FOUND", null, null, false);
|
||||
}
|
||||
|
||||
public static ResponseEntity notContent(){
|
||||
return ApiResponse.build(HttpStatus.NO_CONTENT, "DELETED", null, null, false);
|
||||
}
|
||||
|
||||
public static ResponseEntity badRequest(Map<String, Object> errors){
|
||||
return ApiResponse.build(HttpStatus.BAD_REQUEST, "Problem with request", null, errors, false);
|
||||
}
|
||||
|
||||
public static ResponseEntity build(HttpStatus status, String message, Object body, Object errors, Boolean success){
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("message", message);
|
||||
map.put("body", body);
|
||||
map.put("errors", errors);
|
||||
map.put("success", success);
|
||||
map.put("status", status.value());
|
||||
|
||||
return new ResponseEntity<Object>(map, status);
|
||||
}
|
||||
|
||||
public ResponseEntity build(){
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("message", this.message);
|
||||
map.put("body", this.body);
|
||||
map.put("errors", this.errors);
|
||||
// map.put("status", this.errors);
|
||||
|
||||
return new ResponseEntity<Object>(map, this.status);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user