Result Codes
Q-Framework result codes are a declaration-based contract. Response codes are declared with annotations, and type-safe constants are automatically generated at compile time.
The Result Code Contract
In traditional approaches, result codes are scattered across multiple locations:
java
// Problem: hardcoded strings — duplicated definitions, typo risk
if (result.getCode().equals("PRODUCT_NOT_FOUND")) { ... }
// Problem: constant file management — not centralized
public static final String PRODUCT_NOT_FOUND = "PRODUCT_NOT_FOUND";In Q-Framework, result codes are declared as SSOT:
java
// SSOT: declared with annotation
@QfResultCode(code = "PRODUCT_NOT_FOUND", httpStatus = 404, ...)
// → Type-safe constants auto-generated at compile time
// → Automatically included in API documentation
// → Automatically integrated with frontend i18n@QfResultCode Annotation Attributes
java
@QfResultCode(
code = "PRODUCT_NOT_FOUND", // result code string
httpStatus = 404, // HTTP status code
message = "Product not found.", // default message
i18n = @QfI18n( // localized messages
en = "Product not found",
ko = "상품을 찾을 수 없습니다."
)
)| Attribute | Type | Required | Description | Default |
|---|---|---|---|---|
code | String | ✅ | Result code identifier | — |
httpStatus | int | ✅ | HTTP status code | — |
message | String | Default message | "" | |
i18n | @QfI18n | Localized messages | — |
Code Format Rules
Result codes follow this format:
{DOMAIN}_{ACTION}_{STATUS}
↓ ↓ ↓
PRODUCT _ NOT_FOUND (none)
MEMBER _ CREATE _ FAILED
ORDER _ PAYMENT _ TIMEOUTRules:
- Uppercase letters only
- Words separated by underscore (
_) - Domain prefix required
Examples:
PRODUCT_NOT_FOUNDMEMBER_DUPLICATE_LOGIN_IDORDER_PAYMENT_TIMEOUTVALIDATION_FAILED(system-level)UNAUTHORIZED(system-level)
Defining Result Codes
Domain-Based Interface Declaration
java
// ProductResultCode.java
@QfResultCodeGroup(domain = "PRODUCT")
public interface ProductResultCode {
@QfResultCode(
code = "PRODUCT_NOT_FOUND",
httpStatus = 404,
i18n = @QfI18n(
en = "Product not found",
ko = "상품을 찾을 수 없습니다."
)
)
String NOT_FOUND = "PRODUCT_NOT_FOUND";
@QfResultCode(
code = "PRODUCT_OUT_OF_STOCK",
httpStatus = 409,
i18n = @QfI18n(
en = "Product is out of stock",
ko = "품절된 상품입니다."
)
)
String OUT_OF_STOCK = "PRODUCT_OUT_OF_STOCK";
@QfResultCode(
code = "PRODUCT_CREATE_FAILED",
httpStatus = 500,
i18n = @QfI18n(
en = "Failed to create product",
ko = "상품 등록에 실패했습니다."
)
)
String CREATE_FAILED = "PRODUCT_CREATE_FAILED";
}Auto-Generated Code Example
Type-safe constant classes are generated at compile time.
Before (declaration):
java
@QfResultCode(code = "PRODUCT_NOT_FOUND", httpStatus = 404, ...)
String NOT_FOUND = "PRODUCT_NOT_FOUND";After (auto-generated code):
java
// Auto-generated — do not modify manually
public final class QfProductResultCodes {
public static final QfResultCodeDef NOT_FOUND =
new QfResultCodeDef("PRODUCT_NOT_FOUND", 404, "Product not found");
public static final QfResultCodeDef OUT_OF_STOCK =
new QfResultCodeDef("PRODUCT_OUT_OF_STOCK", 409, "Product is out of stock");
private QfProductResultCodes() {}
}Usage
java
@QfOn(entity = ProductEntity.class, event = QfEvent.BEFORE_READ)
public class ProductReadHook implements QfHook<ProductEntity> {
@Override
public void execute(QfHookContext<ProductEntity> context) {
String id = context.getId();
if (!productRepository.existsById(id)) {
// use type-safe result code
throw new QfManagedException(QfProductResultCodes.NOT_FOUND);
}
}
}Standard Response Structure
json
{
"success": false,
"code": "PRODUCT_NOT_FOUND",
"message": "Product not found",
"data": null
}Success response:
json
{
"success": true,
"code": "SUCCESS",
"data": {
"id": "prod-001",
"name": "Laptop",
"price": 1500000
}
}System Default Result Codes
Result codes provided by Q-Framework out of the box.
| Code | HTTP Status | Description |
|---|---|---|
SUCCESS | 200 | Successful operation |
VALIDATION_FAILED | 400 | Input validation failed |
UNAUTHORIZED | 401 | Authentication required |
FORBIDDEN | 403 | Access denied |
NOT_FOUND | 404 | Resource not found |
CONFLICT | 409 | Duplicate entry or conflict |
INTERNAL_SERVER_ERROR | 500 | Internal server error |
RUNTIME_NOT_INITIALIZED | 503 | Runtime initialization failed |
Next Steps
- Annotation Reference — Complete annotation list
- SPI Extensions — Customize result code handling