Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/main/java/com/app/dto/StandardResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.app.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class StandardResponse<T> {
private String responseCode; // The response code (e.g., "E1005")
private String responseDescription; // The response description (e.g., "Invalid method argument.")
private T response; // Generic type to hold any object (e.g., data or error details)
private boolean isOkay; // Indicates success (true) or failure (false)
}
26 changes: 26 additions & 0 deletions src/main/java/com/app/exception/CustomRuntimeException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.app.exception;

import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public class CustomRuntimeException extends RuntimeException {

private final String responseCode; // Unique error code
private final HttpStatus httpStatus; // HTTP status associated with the exception
private final Object[] args;

/**
* Constructor for CustomRuntimeException.
*
* @param responseCode The unique error code.
* @param httpStatus The HTTP status associated with the exception.
* @param args Arguments for dynamic message formatting.
*/
public CustomRuntimeException(String responseCode, HttpStatus httpStatus, Object... args) {
super(responseCode); // Use responseCode as the default message for the exception
this.responseCode = responseCode;
this.httpStatus = httpStatus;
this.args = args;
}
}
73 changes: 73 additions & 0 deletions src/main/java/com/app/exception/RestExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.app.exception;

import com.app.dto.StandardResponse;
import com.app.utils.MessageConstant;
import com.app.utils.ResponseUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
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.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.stream.Collectors;

@RestControllerAdvice
@RequiredArgsConstructor
@Log4j2
public class RestExceptionHandler {

private final ResponseUtil responseUtil;

/**
* Handles validation errors for method arguments.
*
* @param ex The MethodArgumentNotValidException to handle.
* @return A ResponseEntity with a structured error response.
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<StandardResponse<Object>> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
return buildErrorResponse(MessageConstant.E1005, HttpStatus.BAD_REQUEST, ex.getBindingResult().getFieldErrors().stream()
.collect(Collectors.toMap(FieldError::getField, responseUtil::getMessage)));
}

/**
* Handles custom ServiceException.
*
* @param ex The ServiceException to handle.
* @return A ResponseEntity with an error response.
*/
@ExceptionHandler(CustomRuntimeException.class)
public ResponseEntity<StandardResponse<Object>> handleServiceException(CustomRuntimeException ex) {
log.error("Service exception: ", ex);
return buildErrorResponse(ex.getResponseCode(), ex.getHttpStatus(), ex.getArgs());
}

/**
* Handles generic RuntimeExceptions.
*
* @param ex The RuntimeException to handle.
* @return A ResponseEntity with an error response.
*/
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<StandardResponse<Object>> handleRuntimeException(RuntimeException ex) {
log.error("Runtime exception: ", ex);
return buildErrorResponse(MessageConstant.E1000, HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
}


/**
* Utility method to build a standardized error response.
*
* @param responseCode The response code for the error.
* @param details The error details to include in the response.
* @param httpStatus The HTTP status for the response.
* @return A ResponseEntity containing the StandardResponse.
*/
private ResponseEntity<StandardResponse<Object>> buildErrorResponse(String responseCode, HttpStatus httpStatus, Object... details) {
StandardResponse<Object> response = responseUtil.createErrorResponse(responseCode, details);
return ResponseEntity.status(httpStatus).body(response);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/app/utils/MessageConstant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.app.utils;

public class MessageConstant {
private MessageConstant() {
}
//Success
public static final String S0001 = "s0001";
// Error Message Constant
public static final String E1000 = "e1000";
public static final String E1001 = "e1001";
public static final String E1002 = "e1002";
public static final String E1003 = "e1003";
public static final String E1004 = "e1004";
public static final String E1005 = "e1005";
public static final String E1006 = "e1006";
public static final String E1007 = "e1007";


}
59 changes: 59 additions & 0 deletions src/main/java/com/app/utils/ResponseUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.app.utils;

import com.app.dto.StandardResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
@RequiredArgsConstructor
public class ResponseUtil {

private final MessageSource messageSource;


/**
* Creates a success response.
*
* @param responseCode The response code for success.
* @param responseObject The object to include in the response.
* @return A StandardResponse object.
*/
public <T> StandardResponse<T> createSuccessResponse(String responseCode, T responseObject, Object... args) {
return new StandardResponse<>(StringUtils.uncapitalizeAsProperty(responseCode), getMessage("success.description." + responseCode, args), responseObject, true);
}

/**
* Creates an error response.
*
* @param responseCode The response code for the error.
* @param errorDetails Optional error details to include in the response.
* @return A StandardResponse object.
*/
public <T> StandardResponse<T> createErrorResponse(String responseCode, T errorDetails, Object... args) {
return new StandardResponse<>(StringUtils.uncapitalizeAsProperty(responseCode), getMessage("error.description." + responseCode, args), errorDetails, false);
}

/**
* Retrieves a message from the MessageSource based on the current locale.
*
* @param key The message key.
* @return The localized message.
*/
public String getMessage(String key, Object... args) {
return messageSource.getMessage(key, args, LocaleContextHolder.getLocale());
}

/**
* Retrieves a message from the MessageSource based on the current locale.
*
* @return The localized message.
*/
public String getMessage(MessageSourceResolvable resolvable) {
return messageSource.getMessage(resolvable, LocaleContextHolder.getLocale());
}

}
8 changes: 8 additions & 0 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@ app:
logs:
path: C:/${spring.application.name}/logs

####################### START READ PROPERTIES FILE #######################
spring:
messages:
basename: error_messages,success_messages # Or provide full paths if needed
cache-duration: 3600
encoding: UTF-8
web:
locale: en
42 changes: 42 additions & 0 deletions src/main/resources/error_messages.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Error Code Properties
error.code.e1000=E1000
error.description.e1000=Something went wrong! {0}

error.code.e1001=E1001
error.description.e1001=Authorization header cannot be blank or invalid.

error.code.e1002=E1002
error.description.e1002=Unable to extract email ID from the token. Please generate a new token.

error.code.e1003=E1003
error.description.e1003=Invalid token. Please generate a new token.

error.code.e1004=E1004
error.description.e1004=Authentication token is required.

error.code.e1005=E1005
error.description.e1005=Invalid method argument.

error.code.e1006=E1006
error.description.e1006=No matching enum found.

error.code.e1007=E1007
error.description.e1007=Duplicate entry detected.



# fullName validations
fullName.not.blank=Full name cannot be blank
fullName.size=Full name must not exceed 100 characters
# email validations
email.not.blank=Email cannot be blank
email.invalid=Please provide a valid email address
# password validations
password.not.blank=Password cannot be blank
password.pattern=Password must be at least 8 characters, include an alphanumeric character, and one special character
# authProvider validations
authProvider.notnull=Auth provider is required
authProvider.invalid=Auth provider must be one of the values: 4, 5, 6
# roleId validations
roleId.notnull=Role ID is required
roleId.invalid=Role ID must be either 2 or 3
15 changes: 15 additions & 0 deletions src/main/resources/error_messages_hi.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# fullName validations
fullName.no.tblank=???? ??? ???? ???? ?? ????
fullName.size=???? ??? 100 ??????? ?? ???? ???? ???? ?????
# email validations
email.not.blank=???? ???? ???? ?? ????
email.invalid=????? ?? ????? ???? ??? ?????? ????
# password validations
password.not.blank=??????? ???? ???? ?? ????
password.pattern=??????? ?? ?? ?? 8 ??????? ?? ???? ?????, ?? ??????????????? ?? ?? ????? ????? ????? ???? ?????
# authProvider validations
authProvider.notnull=?? ????????? ?????? ??
authProvider.invalid=?? ????????? ?? ??? 3, 4, 5 ??? ?? ?? ???? ?????
# roleId validations
roleId.notnull=?????? ???? ?????? ??
roleId.invalid=?????? ???? 2 ?? 3 ??? ?? ?? ???? ?????
2 changes: 2 additions & 0 deletions src/main/resources/success_messages.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
success.description.s0001=Request processed successfully.
success.description.s0002=Token generated successfully.
15 changes: 15 additions & 0 deletions src/main/resources/success_messages_hi.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# fullName validations
fullName.no.tblank=???? ??? ???? ???? ?? ????
fullName.size=???? ??? 100 ??????? ?? ???? ???? ???? ?????
# email validations
email.not.blank=???? ???? ???? ?? ????
email.invalid=????? ?? ????? ???? ??? ?????? ????
# password validations
password.not.blank=??????? ???? ???? ?? ????
password.pattern=??????? ?? ?? ?? 8 ??????? ?? ???? ?????, ?? ??????????????? ?? ?? ????? ????? ????? ???? ?????
# authProvider validations
authProvider.notnull=?? ????????? ?????? ??
authProvider.invalid=?? ????????? ?? ??? 3, 4, 5 ??? ?? ?? ???? ?????
# roleId validations
roleId.notnull=?????? ???? ?????? ??
roleId.invalid=?????? ???? 2 ?? 3 ??? ?? ?? ???? ?????