Search code examples
javajakarta-eeejb-3.0wildfly-8

Java ee interface conditional inject


I have the following interface:

public interface ResultEvaluationInterface {
    public void evaluateResults(Event e);
}

and I want to inject in my class depending on my Event.type different classes with the same implementation. Something like that:

@Stateless
@LocalBean    
public class ResultEvaluation implements ResultEvaluationInterface {

    @Override
    public void evaluateResults(Event e) {
        switch (e.getType()) {
            case Type.Running:
               // inject and call ResultEvaluationRunningEJB.evaluateResults(e)
            case Type.Swimming:
               // inject and call ResultEvaluationSwimmingEJB.evaluateResults(e)
            default:
               throw new UnsupportedOperationException("Not supported yet.");
        }
    }

}

ResultEvaluationRunningEJB and ResultEvaluationSwimmingEJB both implement the interface. Anybody has got a good idea how to do that in a good way?


Solution

  • If you really want to use a hard coded if statement to switch between prod and dev events you could use CDI Qualifiers simply inject the two implementations into a Facade:

    @Stateless
    @LocalBean    
    public class ResultEvaluationFacade {
    
        @Inject
        @Development
        private ResultEvalutationInterface dev;
    
        @Inject
        @Production
        private ResultEvalutionInterface prod;
    
        @Override
        public void evaluateResults(Event e) {
            switch (e.getType()) {
                case Type.Production:
                   prod.evaluteResult(e);
                   break;
                case Type.Development:
                   dev.evaluteResult(e);
                   break;
                default:
                   throw new UnsupportedOperationException("Not supported yet.");
            }
        }
    
    }
    

    And define your two implementations:

    @Development
    public class ResultEvaluationDevelopment implements ResultEvaluationInterface {
       ...
    }
    
    @Production
    public class ResultEvaluationDevelopment implements ResultEvaluationInterface {
       ...
    }
    

    However I would consider using a mock maven project to house the two separate implementations instead.

    Alternatively you could use different CDI Event types, something like this.

    public void observeDevEvent(@Observe DevEvent event) {
       //do stuff.
    }
    
    public void observeProdEvent(@Observe ProdEvent event) {
       //do stuff
    }
    

    Firing the event would look something like this:

    @Inject
    private Event<ProdEvent> prodEvent;
    
    public void someMethod() {
       ProdEvent pe = new ProdEvent()
       // set some data on ProdEvent
       prodEvent.fire(pe);
    }
    

    Note events can also work with Qualifiers, so you could also add a Qualifier annotation to the Event instead of implementing two different types of event.

    @Inject
    @Production
    private Event<MyEvent> event;
    

    And listen for @Prodcution events;

    public void handleProdEvent(@Observer @Production MyEvent myEvent) {
        // do Stuff.
    }
    

    For lazy instantiation of beans you can use CDI Instance injection.

    @Inject
    private Instance<BeanA> beanA;
    
    ....
    
    public void doStuff(Event e) {
       ...
       case Type.Production:
                //lazily evaluates and instantiatiates bean.
                beanA.get().evaluateResult(e);
    }