Last active
January 16, 2026 06:56
-
-
Save valarpirai/7bcf5b1707b6188c6b86123798de8158 to your computer and use it in GitHub Desktop.
Error Handling code snippet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ConfigController with proper error handling | |
| import org.springframework.web.bind.annotation.*; | |
| import org.springframework.http.*; | |
| import org.springframework.jdbc.core.JdbcTemplate; | |
| import org.springframework.dao.*; | |
| import org.springframework.transaction.annotation.Transactional; | |
| import com.fasterxml.jackson.core.JsonProcessingException; | |
| import com.fasterxml.jackson.databind.ObjectMapper; | |
| import javax.validation.Valid; | |
| import javax.validation.constraints.*; | |
| import java.time.Instant; | |
| import java.sql.Timestamp; | |
| @RestController | |
| @RequestMapping("/api/config") | |
| public class ConfigController { | |
| private final JdbcTemplate jdbcTemplate; | |
| private final ObjectMapper objectMapper; | |
| public ConfigController(JdbcTemplate jdbcTemplate, ObjectMapper objectMapper) { | |
| this.jdbcTemplate = jdbcTemplate; | |
| this.objectMapper = objectMapper; | |
| } | |
| @PostMapping("/enable") | |
| public ResponseEntity<ApiResponse> enableConfig(@Valid @RequestBody ConfigRequest request) { | |
| try { | |
| // Validate input | |
| validateRequest(request); | |
| // Save to database with transaction | |
| ConfigurationEntity savedConfig = saveConfiguration(request); | |
| // Return success response | |
| return ResponseEntity.ok(ApiResponse.success( | |
| "Configuration updated successfully", | |
| savedConfig | |
| )); | |
| } catch (ValidationException e) { | |
| // Input validation failed | |
| return ResponseEntity | |
| .status(HttpStatus.BAD_REQUEST) | |
| .body(ApiResponse.error( | |
| "VALIDATION_ERROR", | |
| "Invalid request: " + e.getMessage() | |
| )); | |
| } catch (DuplicateKeyException e) { | |
| // Configuration already exists | |
| return ResponseEntity | |
| .status(HttpStatus.CONFLICT) | |
| .body(ApiResponse.error( | |
| "DUPLICATE_CONFIG", | |
| "Configuration for '" + request.getFeatureName() + "' already exists" | |
| )); | |
| } catch (DataAccessException e) { | |
| // Database error | |
| System.err.println("Database error: " + e.getMessage()); | |
| e.printStackTrace(); | |
| return ResponseEntity | |
| .status(HttpStatus.INTERNAL_SERVER_ERROR) | |
| .body(ApiResponse.error( | |
| "DATABASE_ERROR", | |
| "Failed to save configuration. Please try again later." | |
| )); | |
| } catch (Exception e) { | |
| // Unexpected error | |
| System.err.println("Unexpected error: " + e.getMessage()); | |
| e.printStackTrace(); | |
| return ResponseEntity | |
| .status(HttpStatus.INTERNAL_SERVER_ERROR) | |
| .body(ApiResponse.error( | |
| "INTERNAL_ERROR", | |
| "An unexpected error occurred" | |
| )); | |
| } | |
| } | |
| private void validateRequest(ConfigRequest request) throws ValidationException { | |
| if (request.getFeatureName() == null || request.getFeatureName().trim().isEmpty()) { | |
| throw new ValidationException("Feature name is required"); | |
| } | |
| if (request.getFeatureName().length() > 100) { | |
| throw new ValidationException("Feature name must not exceed 100 characters"); | |
| } | |
| if (request.getUpdatedBy() == null || request.getUpdatedBy().trim().isEmpty()) { | |
| throw new ValidationException("Updated by is required"); | |
| } | |
| // Validate feature name format (alphanumeric, underscores, hyphens) | |
| if (!request.getFeatureName().matches("^[a-zA-Z0-9_-]+$")) { | |
| throw new ValidationException( | |
| "Feature name can only contain letters, numbers, underscores, and hyphens" | |
| ); | |
| } | |
| } | |
| @Transactional | |
| private ConfigurationEntity saveConfiguration(ConfigRequest request) { | |
| String sql = """ | |
| INSERT INTO configurations (feature_name, enabled, updated_by, updated_at) | |
| VALUES (?, ?, ?, ?) | |
| ON DUPLICATE KEY UPDATE | |
| enabled = VALUES(enabled), | |
| updated_by = VALUES(updated_by), | |
| updated_at = VALUES(updated_at) | |
| """; | |
| Timestamp now = Timestamp.from(Instant.now()); | |
| try { | |
| int rowsAffected = jdbcTemplate.update( | |
| sql, | |
| request.getFeatureName(), | |
| request.isEnabled(), | |
| request.getUpdatedBy(), | |
| now | |
| ); | |
| if (rowsAffected == 0) { | |
| throw new DataAccessException("No rows were affected") {}; | |
| } | |
| // Retrieve the saved configuration | |
| return getConfiguration(request.getFeatureName()); | |
| } catch (DataAccessException e) { | |
| // Log and rethrow | |
| System.err.println("Failed to save configuration: " + e.getMessage()); | |
| throw e; | |
| } | |
| } | |
| private ConfigurationEntity getConfiguration(String featureName) { | |
| String sql = "SELECT * FROM configurations WHERE feature_name = ?"; | |
| return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> { | |
| ConfigurationEntity entity = new ConfigurationEntity(); | |
| entity.setId(rs.getLong("id")); | |
| entity.setFeatureName(rs.getString("feature_name")); | |
| entity.setEnabled(rs.getBoolean("enabled")); | |
| entity.setUpdatedBy(rs.getString("updated_by")); | |
| entity.setUpdatedAt(rs.getTimestamp("updated_at")); | |
| return entity; | |
| }, featureName); | |
| } | |
| // Exception handler for JSON parsing errors | |
| @ExceptionHandler(JsonProcessingException.class) | |
| public ResponseEntity<ApiResponse> handleJsonError(JsonProcessingException e) { | |
| return ResponseEntity | |
| .status(HttpStatus.BAD_REQUEST) | |
| .body(ApiResponse.error( | |
| "INVALID_JSON", | |
| "Invalid JSON format: " + e.getOriginalMessage() | |
| )); | |
| } | |
| // Request DTO | |
| static class ConfigRequest { | |
| @NotBlank(message = "Feature name is required") | |
| @Size(max = 100, message = "Feature name must not exceed 100 characters") | |
| private String featureName; | |
| @NotNull(message = "Enabled flag is required") | |
| private Boolean enabled; | |
| @NotBlank(message = "Updated by is required") | |
| private String updatedBy; | |
| // Getters and setters | |
| public String getFeatureName() { return featureName; } | |
| public void setFeatureName(String featureName) { this.featureName = featureName; } | |
| public Boolean isEnabled() { return enabled; } | |
| public void setEnabled(Boolean enabled) { this.enabled = enabled; } | |
| public String getUpdatedBy() { return updatedBy; } | |
| public void setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; } | |
| } | |
| // Database entity | |
| static class ConfigurationEntity { | |
| private Long id; | |
| private String featureName; | |
| private Boolean enabled; | |
| private String updatedBy; | |
| private Timestamp updatedAt; | |
| // Getters and setters | |
| public Long getId() { return id; } | |
| public void setId(Long id) { this.id = id; } | |
| public String getFeatureName() { return featureName; } | |
| public void setFeatureName(String featureName) { this.featureName = featureName; } | |
| public Boolean getEnabled() { return enabled; } | |
| public void setEnabled(Boolean enabled) { this.enabled = enabled; } | |
| public String getUpdatedBy() { return updatedBy; } | |
| public void setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; } | |
| public Timestamp getUpdatedAt() { return updatedAt; } | |
| public void setUpdatedAt(Timestamp updatedAt) { this.updatedAt = updatedAt; } | |
| } | |
| // API Response wrapper | |
| static class ApiResponse { | |
| private boolean success; | |
| private String message; | |
| private String errorCode; | |
| private Object data; | |
| public static ApiResponse success(String message, Object data) { | |
| ApiResponse response = new ApiResponse(); | |
| response.success = true; | |
| response.message = message; | |
| response.data = data; | |
| return response; | |
| } | |
| public static ApiResponse error(String errorCode, String message) { | |
| ApiResponse response = new ApiResponse(); | |
| response.success = false; | |
| response.errorCode = errorCode; | |
| response.message = message; | |
| return response; | |
| } | |
| // Getters | |
| public boolean isSuccess() { return success; } | |
| public String getMessage() { return message; } | |
| public String getErrorCode() { return errorCode; } | |
| public Object getData() { return data; } | |
| } | |
| // Custom validation exception | |
| static class ValidationException extends Exception { | |
| public ValidationException(String message) { | |
| super(message); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment