Define and enter a card in EJB 3.1 or CDI

After several years of development in Spring, I switched to EJB, and I'm not happy that I have no solution for this use case. Let's say this is a strategy template implemented on a map. In Spring, it might look like this.

<bean id="myBean" class="MyBeanImpl"> <property name="handlers"> <map> <entry key="foo" value-ref="fooHandler"/> <entry key="bar" value-ref="barHandler"/> </property> </bean> 

In EJB / CDI, I have this.

 @Stateless public class MyBeanImpl implements MyBean { private Map<String, Class<? extends Handler>> handlers = new HashMap<>(); @PostConstruct public void init() { handlers.put("foo", FooHandlerImpl.class); handlers.put("bar", BarHandlerImpl.class); } //jndi lookup handlerClass.getSimpleName() } 

Remember that jndi search works with implementations, not interfaces. Isn't there a better solution? And no, I don’t want to have separate fields (foo, bar), enter them and create a map afterwards (this can be a huge list and change often). Ideally, in the case of a configuration change, I would not touch the MyBeanImpl class at all.

+1
spring cdi ejb
source share
2 answers

The larger the CDI will look like this:

 @Qualifier @Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented public @interface Handles { String value(); } public class HandlerLiteral extends AnnotationLiteral<Handles> implements Handles{ private final String value; public HandlerLiteral(String value) { this.value = value; } @Override public String value() { return value; } } 

Then you should annotate each of your Handler implementations with @Handles("someName") , for example. class name as you use it here. Using the qualifier here is more consistent with how the CDI works, and we use the internal Instance object to resolve the corresponding beans. Then, in your service code (or anywhere), you simply do:

 @Inject @Any private Instance<HandlerService> handlerInstance; ... handlerInstance.select(new HandlerLiteral("whateverName")).get().handle(context); 

If you are really limited to using a card, this will not work for you. But this should allow a more dynamic registration and, essentially, look at each handler in your context.

+1
source share

Try the following:

 @Inject @Any private Instance<Handler> handlers; private Map<String, Handler> handlerMap = new HashMap<>(); @PostConstruct private void init() { for (Handler handler : handlers) { handlerMap.put(handler.getName(), handler); } } 

assuming your Handler interface has some kind of getName() method.

+1
source share

All Articles