콘텐츠로 이동

Annotation Reference

Complete reference for all Curve annotations.

@PublishEvent

Marks a method to automatically publish events after execution.

Package

io.github.closeup1202.curve.spring.audit.annotation.PublishEvent

Parameters

Parameter Type Required Default Description
eventType String No "" Unique event type identifier (auto-generated from method name if empty)
severity EventSeverity No INFO Event severity level
payloadIndex int No -1 Parameter index for payload (-1: use return value, 0+: use parameter)
payload String (SpEL) No "" Payload extraction SpEL expression (overrides payloadIndex)
topic String No "" Kafka topic name (overrides curve.kafka.topic if set)
phase Phase No AFTER_RETURNING When to publish (BEFORE, AFTER_RETURNING, AFTER)
failOnError boolean No false Throw exception if event publishing fails
outbox boolean No false Enable transactional outbox pattern
aggregateType String No "" Entity type for outbox (required if outbox=true)
aggregateId String (SpEL) No "" Entity ID SpEL expression for outbox (required if outbox=true)

Example

@PublishEvent(
    eventType = "ORDER_CREATED",
    severity = EventSeverity.INFO,
    payload = "#result.toDto()",
    phase = PublishEvent.Phase.AFTER_RETURNING,
    failOnError = false,
    outbox = true,
    aggregateType = "Order",
    aggregateId = "#result.id"
)
public Order createOrder(OrderRequest request) {
    return orderRepository.save(new Order(request));
}

Phase Options

public enum Phase {
    BEFORE,          // Publish before method execution
    AFTER_RETURNING, // Publish after successful execution (default)
    AFTER            // Publish after execution (even if method throws exception)
}

Payload Extraction Examples

// Use return value (default when payloadIndex=-1 and payload="")
@PublishEvent(eventType = "ORDER_CREATED")
public Order createOrder(OrderRequest req) { ... }

// Use specific parameter by index
@PublishEvent(
    eventType = "ORDER_SUBMITTED",
    payloadIndex = 0  // Use first parameter
)
public Order submitOrder(OrderSubmission submission) { ... }

// Use SpEL expression (overrides payloadIndex)
@PublishEvent(
    eventType = "USER_UPDATED",
    payload = "#args[0].toEventDto()"
)
public User updateUser(UserUpdateRequest request) { ... }

// SpEL with return value method call
@PublishEvent(
    eventType = "ORDER_COMPLETED",
    payload = "#result.toCompletedDto()"
)
public Order completeOrder(String reason) { ... }

// Multi-topic publishing (different topics per domain context)
@PublishEvent(eventType = "CART_ITEM_ADDED", topic = "cart.events")
public CartItem addItem(AddItemRequest request) { ... }

@PublishEvent(eventType = "STOCK_DECREASED", topic = "stock.events")
public Stock decreaseStock(DecreaseRequest request) { ... }

// When topic is empty, uses default curve.kafka.topic
@PublishEvent(eventType = "USER_CREATED")
public User createUser(CreateUserRequest request) { ... }

Topic Resolution

When publishing events:

  1. If topic attribute is set → publish to specified topic
  2. If topic is empty → use curve.kafka.topic (default topic from configuration)

This allows different event streams to be routed to separate Kafka topics for better domain isolation.


@PiiField

Marks a field for automatic PII protection.

Package

io.github.closeup1202.curve.spring.pii.annotation.PiiField

Parameters

Parameter Type Required Default Description
type PiiType Yes - Type of PII data
strategy PiiStrategy Yes - Protection strategy
condition String (SpEL) No "" Conditional protection

PiiType Values

  • EMAIL - Email addresses
  • PHONE - Phone numbers
  • SSN - Social Security Numbers
  • NAME - Person names
  • ADDRESS - Physical addresses
  • CREDIT_CARD - Credit card numbers
  • IP_ADDRESS - IP addresses
  • GENERIC - Custom sensitive data

PiiStrategy Values

  • MASK - Pattern-based masking
  • ENCRYPT - AES-256-GCM encryption
  • HASH - HMAC-SHA256 hashing

Example

public class UserPayload implements DomainEventPayload {

    @PiiField(type = PiiType.EMAIL, strategy = PiiStrategy.MASK)
    private String email;

    @PiiField(type = PiiType.PHONE, strategy = PiiStrategy.ENCRYPT)
    private String phone;

    @PiiField(type = PiiType.NAME, strategy = PiiStrategy.HASH)
    private String name;
}

Enums

EventSeverity

public enum EventSeverity {
    INFO,     // Normal operations (default)
    WARN,     // Warnings
    ERROR,    // Errors requiring attention
    CRITICAL  // Critical failures requiring immediate action
}

SpEL Context Variables

Available in SpEL expressions:

Variable Description Example
#result Method return value #result
#args[n] Method arguments (0-indexed) #args[0]
#root Root evaluation context #root.methodName
#this Current object #this.getId()

Example

// Use return value
@PublishEvent(payload = "#result")

// Use method argument
@PublishEvent(payload = "#args[0].toDto()")

// Call method on return value
@PublishEvent(payload = "#result.getId()")

// Call method on parameter
@PublishEvent(
    payload = "#args[0].toPayloadDto()"
)

Best Practices

  1. Event Type Naming: Use SCREAMING_SNAKE_CASE (e.g., ORDER_CREATED)
  2. Severity Levels: Choose appropriate severity for filtering (INFO, WARN, ERROR, CRITICAL)
  3. SpEL Expressions: Keep simple for maintainability
  4. PII Protection: Apply to all sensitive fields
  5. Phase Selection: Use AFTER_RETURNING for normal cases, BEFORE for pre-validation events
  6. Error Handling: Set failOnError=false (default) to prevent business logic failure from event publishing issues
  7. Transactional Outbox: Enable for critical events requiring guaranteed delivery

See Also