Skip to content

Latest commit

 

History

History
164 lines (130 loc) · 4.27 KB

File metadata and controls

164 lines (130 loc) · 4.27 KB

Automatic Event System with CDI Observers 🚀

How It Works

  • @HyperResource auto-generates events 📨
  • @Observes required to catch events 🕵️‍♂️
  • Built on CDI Event Bus ⚡

1. Entity Setup (User Code)

@Entity
@HyperResource(
        path = "/orders",
        events = @Events(
                onCreate = true,  // Auto CREATE events
                onUpdate = true,  // Auto UPDATE events
                onDelete = true   // Auto DELETE events
                onPatch = true,   // Auto PATCH events
                emitter = OrderEvents.class // Custom emitter
        )
)
public class Order extends BaseEntity {
    // entity fields...
}

The OrderEvents must be defined by the user to handle the events emitted by the Order entity.

@ApplicationScoped
public class OrderEvents extends AbstractTypedEmitter<Order> {

    protected OrderEvents() {
        super(Order.class);
    }

    @Override
    protected void emitTyped(EntityEvent.Type type, Order entity) {
        switch (type){
            case CREATE -> postCreate(entity);
            case UPDATE -> postUpdate(entity);
            case DELETE -> postDelete(entity);
            case PATCH -> postPatch(entity);
        }
    }

    void postCreate(Order Order) {
        System.out.println("Post-create processing for Order: " + Order.getOrderNumber());
        // Add any additional logic needed after the event is emitted
    }

    void postUpdate(Order Order) {
        System.out.println("Post-update processing for Order: " + Order.getOrderNumber());
        // Add any additional logic needed after the event is emitted
    }

    void postDelete(Order Order) {
        System.out.println("Post-delete processing for deleted Order");
        // Add any additional logic needed after the event is emitted
    }

    void postPatch(Order Order) {
        System.out.println("Post-patch processing for Order: " + Order.getOrderNumber());
        // Add any additional logic needed after the event is emitted
    }
}

2. Observer Setup (User Code)

// User-defined observer (catch all events)
@ApplicationScoped
public class GlobalEventLogger {
    public void logAllEvents(@Observes EntityEvent<?> event) {
        System.out.printf("[GLOBAL] %s %s%n",
                event.getType(),
                event.getEntity().getClass().getSimpleName());
    }
}

// User-defined observer (specific entity)
@ApplicationScoped
public class OrderEventProcessor {
    public void handleOrderEvent(@Observes EntityEvent<Order> event) {
        switch(event.getType()) {
            case CREATE -> processNewOrder(event.getEntity());
            case UPDATE -> processOrderUpdate(event.getEntity());
            case DELETE -> processOrderRemoval(event.getEntity());
        }
    }
    // ... processing methods
}

Generated Service (autogenerated)

public abstract class BaseEntityService<ENTITY, DTO, MAPPER> {

    @Inject
    protected Event<EntityEvent<ENTITY>> eventBus;

    protected void fireEvent(EntityEvent.Type type, ENTITY entity) {
        eventBus.fire(new EntityEvent(type, entity));
    }
}

Event Types

Event Types Requires Config
CREATE post-persist onCreate=true
UPDATE post-merge onUpdate=true
DELETE post-remove onDelete=true

Best Practices

1. Observer Patterns:

// Narrow observation
@Observes EntityEvent<SpecificEntity>

// Broad observation  
@Observes EntityEvent<?>

2. Error Handling:

public void safeObserver(@Observes EntityEvent<?> event) {
    try {
        // processing logic
    } catch (Exception e) {
        log.error("Event processing failed", e);
    }
}
  1. Async Processing:
public void asyncProcessing(@ObservesAsync EntityEvent<Order> event) {
    // Long-running task
}

📈 Extending for Update/Delete Events

Event Types Requires Config
CREATE post-persist onCreate=true
UPDATE post-merge onUpdate=true
DELETE post-remove onDelete=true

⚠️ Important: Events will be silently ignored if no observer exists for them. Always verify your observers are properly registered in CDI context.