Allra error handling
Skill ComeOnOliver/skillshub/skills/aiskillstore/marketplace/allra-fintech/allra-error-handling
π§ The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.
npx -y skills add ComeOnOliver/skillshub --skill allra-error-handlingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Allra λ°±μλ μλ¬ νΈλ€λ§ λ° μμΈ μ²λ¦¬ νμ€. Use when handling errors, creating custom exceptions, or implementing error responses.
SKILL.md
10.1 KB, as published. Nobody here has run it
Allra Backend μλ¬ νΈλ€λ§ νμ€
Allra λ°±μλ νμ μλ¬ νΈλ€λ§, μμΈ μ²λ¦¬, λ‘κΉ νμ€μ μ μν©λλ€.
μμΈ ν΄λμ€ μ€κ³
1. λΉμ¦λμ€ μμΈ κ³μΈ΅ ꡬ쑰
// μ΅μμ λΉμ¦λμ€ μμΈ
public abstract class BusinessException extends RuntimeException {
private final ErrorCode errorCode;
protected BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
protected BusinessException(ErrorCode errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public ErrorCode getErrorCode() {
return errorCode;
}
public int getStatus() {
return errorCode.getStatus();
}
}
// ErrorCode Enum (μμ)
public enum ErrorCode {
// 400 Bad Request
INVALID_INPUT_VALUE(400, "E001", "μλͺ»λ μ
λ ₯κ°μ
λλ€"),
// 401 Unauthorized
UNAUTHORIZED(401, "E101", "μΈμ¦μ΄ νμν©λλ€"),
INVALID_TOKEN(401, "E102", "μ ν¨νμ§ μμ ν ν°μ
λλ€"),
// 403 Forbidden
FORBIDDEN(403, "E201", "κΆνμ΄ μμ΅λλ€"),
// 404 Not Found
ENTITY_NOT_FOUND(404, "E301", "μμ²ν 리μμ€λ₯Ό μ°Ύμ μ μμ΅λλ€"),
USER_NOT_FOUND(404, "E302", "μ¬μ©μλ₯Ό μ°Ύμ μ μμ΅λλ€"),
// 409 Conflict
DUPLICATE_RESOURCE(409, "E401", "μ΄λ―Έ μ‘΄μ¬νλ 리μμ€μ
λλ€"),
// 500 Internal Server Error
INTERNAL_SERVER_ERROR(500, "E999", "μλ² λ΄λΆ μ€λ₯κ° λ°μνμ΅λλ€");
private final int status;
private final String code;
private final String message;
ErrorCode(int status, String code, String message) {
this.status = status;
this.code = code;
this.message = message;
}
// getters...
}
μ°Έκ³ : ErrorCode 체κ³(E001, E101 λ±)μ λ©μμ§ μΈμ΄(νκ΅μ΄/μμ΄)λ νλ‘μ νΈλ³λ‘ λ€λ₯Ό μ μμ΅λλ€.
2. λλ©μΈλ³ μμΈ ν΄λμ€
// μν°ν°λ₯Ό μ°Ύμ μ μμ λ
public class EntityNotFoundException extends BusinessException {
public EntityNotFoundException(String entityName, Long id) {
super(ErrorCode.ENTITY_NOT_FOUND,
String.format("%s(id=%d)μ μ°Ύμ μ μμ΅λλ€", entityName, id));
}
}
// μ¬μ©μ κ΄λ ¨ μμΈ
public class UserNotFoundException extends BusinessException {
public UserNotFoundException(Long userId) {
super(ErrorCode.USER_NOT_FOUND,
String.format("μ¬μ©μ(id=%d)λ₯Ό μ°Ύμ μ μμ΅λλ€", userId));
}
}
// μ€λ³΅ 리μμ€ μμΈ
public class DuplicateResourceException extends BusinessException {
public DuplicateResourceException(String resourceName, String field, String value) {
super(ErrorCode.DUPLICATE_RESOURCE,
String.format("%sμ %s=%sκ° μ΄λ―Έ μ‘΄μ¬ν©λλ€", resourceName, field, value));
}
}
// μΈμ¦/μΈκ° μμΈ
public class UnauthorizedException extends BusinessException {
public UnauthorizedException() {
super(ErrorCode.UNAUTHORIZED);
}
}
public class ForbiddenException extends BusinessException {
public ForbiddenException(String message) {
super(ErrorCode.FORBIDDEN, message);
}
}
Global Exception Handler
@RestControllerAdvice ꡬν
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
// λΉμ¦λμ€ μμΈ μ²λ¦¬
@ExceptionHandler(BusinessException.class)
protected ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
log.warn("BusinessException: code={}, message={}",
e.getErrorCode().getCode(), e.getMessage());
ErrorResponse response = ErrorResponse.of(e.getErrorCode(), e.getMessage());
return ResponseEntity
.status(e.getStatus())
.body(response);
}
// Bean Validation μμΈ μ²λ¦¬
@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(
MethodArgumentNotValidException e) {
log.warn("MethodArgumentNotValidException: {}", e.getMessage());
List<ErrorResponse.FieldError> fieldErrors = e.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> new ErrorResponse.FieldError(
error.getField(),
error.getRejectedValue() != null ? error.getRejectedValue().toString() : null,
error.getDefaultMessage()
))
.toList();
ErrorResponse response = ErrorResponse.of(ErrorCode.INVALID_INPUT_VALUE, fieldErrors);
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(response);
}
// μμνμ§ λͺ»ν μμΈ μ²λ¦¬
@ExceptionHandler(Exception.class)
protected ResponseEntity<ErrorResponse> handleException(Exception e) {
log.error("Unexpected exception occurred", e);
ErrorResponse response = ErrorResponse.of(
ErrorCode.INTERNAL_SERVER_ERROR,
"μλ² μ€λ₯κ° λ°μνμ΅λλ€"
);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(response);
}
}
μλ¬ μλ΅ νμ (Allra νμ€)
ErrorResponse DTO
public record ErrorResponse(
String code,
String message,
List<FieldError> errors,
LocalDateTime timestamp
) {
public static ErrorResponse of(ErrorCode errorCode) {
return new ErrorResponse(
errorCode.getCode(),
errorCode.getMessage(),
Collections.emptyList(),
LocalDateTime.now()
);
}
public static ErrorResponse of(ErrorCode errorCode, String message) {
return new ErrorResponse(
errorCode.getCode(),
message,
Collections.emptyList(),
LocalDateTime.now()
);
}
public static ErrorResponse of(ErrorCode errorCode, List<FieldError> errors) {
return new ErrorResponse(
errorCode.getCode(),
errorCode.getMessage(),
errors,
LocalDateTime.now()
);
}
public record FieldError(
String field,
String rejectedValue,
String message
) {}
}
μ°Έκ³ : μλ¬ μλ΅ κ΅¬μ‘°λ νλ‘μ νΈλ³λ‘ 컀μ€ν°λ§μ΄μ§ν μ μμ΅λλ€. μ€μν κ²μ μΌκ΄μ± μλ νμμ μ μ§νλ κ²μ λλ€.
μλ¬ μλ΅ μμ
λ¨μΌ μλ¬:
{
"code": "E302",
"message": "μ¬μ©μ(id=123)λ₯Ό μ°Ύμ μ μμ΅λλ€",
"errors": [],
"timestamp": "2024-12-17T10:30:00"
}
Validation μλ¬:
{
"code": "E001",
"message": "μλͺ»λ μ
λ ₯κ°μ
λλ€",
"errors": [
{
"field": "email",
"rejectedValue": "invalid-email",
"message": "μ¬λ°λ₯Έ μ΄λ©μΌ νμμ΄ μλλλ€"
}
],
"timestamp": "2024-12-17T10:30:00"
}
μλΉμ€ λ μ΄μ΄μμ μμΈ μ¬μ©
1. μν°ν° μ‘°ν μ μμΈ μ²λ¦¬
@Service
public class UserService {
private final UserRepository userRepository;
@Transactional(readOnly = true)
public User findUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
}
}
2. λΉμ¦λμ€ λ‘μ§ κ²μ¦
@Service
public class UserService {
@Transactional
public User createUser(SignUpRequest request) {
// μ€λ³΅ 체ν¬
if (userRepository.existsByEmail(request.email())) {
throw new DuplicateResourceException("User", "email", request.email());
}
User user = User.create(request.email(), request.password());
return userRepository.save(user);
}
@Transactional
public void deleteUser(Long id, Long currentUserId) {
User user = userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
// κΆν 체ν¬
if (!user.getId().equals(currentUserId)) {
throw new ForbiddenException("λ³ΈμΈμ κ³μ λ§ μμ ν μ μμ΅λλ€");
}
userRepository.delete(user);
}
}
λ‘κΉ μ λ΅
1. λ‘κΉ λ 벨
@Service
@Slf4j
public class UserService {
// DEBUG: κ°λ° μ λλ²κΉ
μ 보
log.debug("Finding user by id: {}", id);
// INFO: μ μμ μΈ λΉμ¦λμ€ νλ‘μ°
log.info("User created successfully: userId={}", user.getId());
// WARN: λΉμ¦λμ€ μμΈ (μμλ μλ¬)
log.warn("User not found: userId={}", id);
// ERROR: μμ€ν
μμΈ (μμνμ§ λͺ»ν μλ¬)
log.error("Unexpected error occurred while creating user", e);
}
μ°Έκ³ : λ‘κΉ λ 벨과 νμμ νλ‘μ νΈμ λ‘κΉ μ μ± μ λ°λΌ λ€λ₯Ό μ μμ΅λλ€.
2. λ‘κΉ ν¬λ§·
// β
κΆμ₯: ꡬ쑰νλ μ 보
log.info("User signup completed: userId={}, email={}, signupAt={}",
user.getId(), user.getEmail(), LocalDateTime.now());
log.warn("Failed login attempt: email={}, reason={}",
email, "Invalid password");
// β νΌνκΈ°: λ¨μ λ¬Έμμ΄ μ°κ²°
log.info("User " + user.getId() + " signed up");
When to Use This Skill
μ΄ skillμ λ€μ μν©μμ μλμΌλ‘ μ μ©λ©λλ€:
- 컀μ€ν μμΈ ν΄λμ€ μμ±
- Service λ μ΄μ΄μμ μμΈ throw
- Global Exception Handler ꡬν
- μλ¬ μλ΅ DTO μμ±
- λ‘κΉ μ½λ μμ±
Checklist
μλ¬ νΈλ€λ§ μ½λ μμ± μ νμΈμ¬ν:
- λΉμ¦λμ€ μμΈλ BusinessExceptionμ μμνλκ°?
- ErrorCode enumμ μ μ ν HTTP μν μ½λκ° μ μλμλκ°?
- Global Exception Handlerμ μμΈ μ²λ¦¬κ° μΆκ°λμλκ°?
- μλ¬ μλ΅μ΄ νμ€ νμμ λ°λ₯΄λκ°?
- λΉμ¦λμ€ μμΈλ WARN λ λ²¨λ‘ λ‘κΉ νλκ°?
- μμ€ν μμΈλ ERROR λ λ²¨λ‘ λ‘κΉ νλκ°?
- λ―Όκ°ν μ 보(λΉλ°λ²νΈ λ±)κ° λ‘κ·Έμ ν¬ν¨λμ§ μλκ°?
- orElseThrowλ₯Ό μ¬μ©ν΄ Optionalμ μ²λ¦¬νλκ°?