Bentz
Bentz

Reputation: 133

Is it possible to create a CDI Event factory?

On my quarkus app i have a application scope service with a lot of cdi event injections

@ApplicationScoped
public class SomeService {

    @Inject
    Event<EventA> eventAEmitter;
    
    @Inject
    Event<EventB> eventBEmitter;
    
    ...


    public void someFunction() {
        eventAEmitter.fire(new EventA(X, Y));
        ...
        eventBEmitter.fire(new EventB(Z, W));
    }
}

@ApplicationScoped
public class Observer {

    private static final Logger LOGGER = Logger.getLogger(Observer.class);


    public void onEventA(@Observes(during = TransactionPhase.AFTER_SUCCESS) EventA event) {

        LOGGER.info("observer: EventA: " + event);
    }

    public void onEventB(@Observes(during = TransactionPhase.AFTER_SUCCESS) EventB event) {

        LOGGER.info("observer: EventB: " + event);
    }
}


public class EventA {

    public String x;
    public SomeObjectA y;
   
}
    
public class EventB {

    public Long z;
    public SomeObjectB w;
   
}
// note that EventA and EventB has different members

i'm looking for a way to create factory that given a class or a string key it will retrieve the wanted event
something like this:

@ApplicationScoped
public class SomeService {

    @Inject
    EventFactory eventfactory;


    public void someFunction() {

        Event<EventA> eventAEmitter = eventfactory.getEvent("key-that-represent-event-a");
        eventAEmitter.fire(new EventA(X, Y));

        Event<EventB> eventBEmitter = eventfactory.getEvent(EventB.class);
        eventBEmitter.fire(new EventB(Z, W));
    }
}

i'm quite new to CDI, is there a way to create this mechanism?

i thought of creating an application scoped class and inject all the events over there but i'm not sure how to access these injected beans, and im not aware of the advantages/disadvantages of injecting the events eagerly
something like that:

@ApplicationScoped
public class EventFactory {

    @Inject
    Event<EventA> eventAEmitter;
    
    @Inject
    Event<EventB> eventBEmitter;
    
    ...


    public void getEvent(Class<?> clazz) {
        ...
    }
}

Upvotes: 1

Views: 117

Answers (1)

Bentz
Bentz

Reputation: 133

ok so i found a way to implement it and get the behavior i'm looking for

i still don't know the advantages/disadvantages or the existence of any caveats.

i've created a Singleton scoped bean and Injected Event<Object> and wrapped the functionality of the Event api, specifically the select method with a default a qualifier.

@Singleton
public class EventFactory {

    @Inject
    Event<Object> eventEmitter;

    public <U extends Object> Event<U> select(Class<U> subtype) {
        return objEventEmitter.select(subtype, new AnnotationLiteral<InternalEventQualifier>(){});
    }
}


@ApplicationScoped
public class SomeService {

    @Inject
    EventFactory eventFactory;

    public void someMethod(...) {
        ...
        var emitter = eventFactory.select(EventA.class);
        
        emitter.fire(new EventA(...));
    }
}  

Upvotes: 0

Related Questions