Content is user-generated and unverified.
// Base API Response wrapper public class ApiResponse<T> { private boolean success; private String message; private T data; private List<String> errors; public ApiResponse() { this.errors = new ArrayList<>(); } public static <T> ApiResponse<T> success(T data) { ApiResponse<T> response = new ApiResponse<>(); response.success = true; response.data = data; response.message = "Operation completed successfully"; return response; } public static <T> ApiResponse<T> success(T data, String message) { ApiResponse<T> response = new ApiResponse<>(); response.success = true; response.data = data; response.message = message; return response; } public static <T> ApiResponse<T> error(String message) { ApiResponse<T> response = new ApiResponse<>(); response.success = false; response.message = message; return response; } public static <T> ApiResponse<T> error(List<String> errors) { ApiResponse<T> response = new ApiResponse<>(); response.success = false; response.errors = errors; response.message = "Validation failed"; return response; } // Getters and setters public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } public List<String> getErrors() { return errors; } public void setErrors(List<String> errors) { this.errors = errors; } } // Custom exceptions public class ValidationException extends Exception { private List<String> errors; public ValidationException(String message) { super(message); this.errors = Arrays.asList(message); } public ValidationException(List<String> errors) { super("Validation failed"); this.errors = errors; } public List<String> getErrors() { return errors; } } public class BusinessLogicException extends Exception { public BusinessLogicException(String message) { super(message); } public BusinessLogicException(String message, Throwable cause) { super(message, cause); } } // Validation interface @FunctionalInterface public interface Validator<T> { List<String> validate(T input); } // Base API Service abstract class public abstract class BaseApiService<REQUEST, RESPONSE> { private static final Logger logger = LoggerFactory.getLogger(BaseApiService.class); // Template method for processing API requests public final ApiResponse<RESPONSE> processRequest(REQUEST request) { String operationName = getOperationName(); long startTime = System.currentTimeMillis(); try { logger.info("Starting operation: {} with request: {}", operationName, logRequest(request)); // Step 1: Validate input validateInput(request); logger.debug("Validation passed for operation: {}", operationName); // Step 2: Execute business logic RESPONSE result = executeBusinessLogic(request); logger.debug("Business logic completed for operation: {}", operationName); // Step 3: Post-process if needed RESPONSE finalResult = postProcess(result, request); long duration = System.currentTimeMillis() - startTime; logger.info("Operation {} completed successfully in {}ms", operationName, duration); return ApiResponse.success(finalResult, "Operation completed successfully"); } catch (ValidationException e) { logger.warn("Validation failed for operation {}: {}", operationName, e.getErrors()); return ApiResponse.error(e.getErrors()); } catch (BusinessLogicException e) { logger.error("Business logic error in operation {}: {}", operationName, e.getMessage(), e); return ApiResponse.error("Business logic error: " + e.getMessage()); } catch (Exception e) { long duration = System.currentTimeMillis() - startTime; logger.error("Unexpected error in operation {} after {}ms: {}", operationName, duration, e.getMessage(), e); return ApiResponse.error("Internal server error occurred"); } } // Abstract methods to be implemented by concrete services protected abstract String getOperationName(); protected abstract RESPONSE executeBusinessLogic(REQUEST request) throws BusinessLogicException; // Default implementations that can be overridden protected void validateInput(REQUEST request) throws ValidationException { List<String> errors = getValidator().validate(request); if (!errors.isEmpty()) { throw new ValidationException(errors); } } protected RESPONSE postProcess(RESPONSE response, REQUEST request) { // Default: no post-processing return response; } protected String logRequest(REQUEST request) { // Override this method to customize request logging (e.g., mask sensitive data) return request != null ? request.toString() : "null"; } // Default validator - override in concrete implementations protected Validator<REQUEST> getValidator() { return (request) -> { List<String> errors = new ArrayList<>(); if (request == null) { errors.add("Request cannot be null"); } return errors; }; } // Utility method for conditional validation protected void addErrorIf(List<String> errors, boolean condition, String errorMessage) { if (condition) { errors.add(errorMessage); } } // Utility method for string validation protected boolean isNullOrEmpty(String value) { return value == null || value.trim().isEmpty(); } // Utility method for collection validation protected boolean isNullOrEmpty(Collection<?> collection) { return collection == null || collection.isEmpty(); } } // Example concrete implementation public class UserRegistrationService extends BaseApiService<UserRegistrationRequest, UserRegistrationResponse> { private static final Logger logger = LoggerFactory.getLogger(UserRegistrationService.class); @Override protected String getOperationName() { return "USER_REGISTRATION"; } @Override protected UserRegistrationResponse executeBusinessLogic(UserRegistrationRequest request) throws BusinessLogicException { try { // Your business logic here logger.debug("Processing user registration for email: {}", request.getEmail()); // Example: Check if user already exists // if (userRepository.existsByEmail(request.getEmail())) { // throw new BusinessLogicException("User with this email already exists"); // } // Example: Create user // User user = userRepository.save(new User(request.getEmail(), request.getName())); return new UserRegistrationResponse("user123", "Registration successful"); } catch (Exception e) { throw new BusinessLogicException("Failed to register user", e); } } @Override protected Validator<UserRegistrationRequest> getValidator() { return (request) -> { List<String> errors = new ArrayList<>(); addErrorIf(errors, request == null, "Request cannot be null"); if (request != null) { addErrorIf(errors, isNullOrEmpty(request.getEmail()), "Email is required"); addErrorIf(errors, isNullOrEmpty(request.getName()), "Name is required"); // Email format validation if (!isNullOrEmpty(request.getEmail()) && !isValidEmail(request.getEmail())) { errors.add("Invalid email format"); } // Name length validation if (!isNullOrEmpty(request.getName()) && request.getName().length() < 2) { errors.add("Name must be at least 2 characters long"); } } return errors; }; } @Override protected String logRequest(UserRegistrationRequest request) { // Mask sensitive information in logs if (request == null) return "null"; return String.format("UserRegistrationRequest{email='%s', name='%s'}", maskEmail(request.getEmail()), request.getName()); } private boolean isValidEmail(String email) { return email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"); } private String maskEmail(String email) { if (isNullOrEmpty(email)) return "null"; int atIndex = email.indexOf("@"); if (atIndex > 0) { return email.substring(0, 1) + "***" + email.substring(atIndex); } return "***"; } } // Example DTOs public class UserRegistrationRequest { private String email; private String name; private String password; // Constructors public UserRegistrationRequest() {} public UserRegistrationRequest(String email, String name, String password) { this.email = email; this.name = name; this.password = password; } // Getters and setters public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } public class UserRegistrationResponse { private String userId; private String message; public UserRegistrationResponse() {} public UserRegistrationResponse(String userId, String message) { this.userId = userId; this.message = message; } // Getters and setters public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } // Example REST Controller usage @RestController @RequestMapping("/api/users") public class UserController { private final UserRegistrationService userRegistrationService; public UserController(UserRegistrationService userRegistrationService) { this.userRegistrationService = userRegistrationService; } @PostMapping("/register") public ResponseEntity<ApiResponse<UserRegistrationResponse>> registerUser( @RequestBody UserRegistrationRequest request) { ApiResponse<UserRegistrationResponse> response = userRegistrationService.processRequest(request); HttpStatus status = response.isSuccess() ? HttpStatus.OK : HttpStatus.BAD_REQUEST; return ResponseEntity.status(status).body(response); } }
Content is user-generated and unverified.
    Java 8 API Service Skeleton | Claude