Inject list of objects in CDI (Weld)
Asked Answered
D

2

40

Let's say I have an interface called SocialNetworkService, and three implementations - TwitterService, FacebookService and FriendFeedService.

Now I want, whenever my managed bean (or whatever web component) receives a message, to share it in all social networks. I tried:

@Inject private List<SocialNetworkService> socialNetworkServices;

But it didn't work (deployment error). (Also tried to the @Any qualifier - same result)

So, is there a way to inject a list of all (or some) implementations of an interface?

I know the rule that a given injection point should not have more than one possible bean. I guess I can achieve that by making a producer that produces the list, and using Instance<SocialNetworkService>, but that seems like too much for this task.

Dora answered 24/10, 2010 at 17:19 Comment(1)
330 and 299 .. That should be sufficientDora
D
71

Combining my attempts with an answer from the Weld forum:

@Inject @Any
private Instance<SocialNetworkService> services;

Instance implements Iterable, so it is then possible to simply use the for-each loop. The @Any qualifier is needed.


Another way to do this is by using the event system:

  • create a MessageEvent (containing all the information about the message)
  • instead of injecting a list of social networks, simply inject the event:

    @Inject private Event<MessageEvent> msgEvent;
    

    and fire it: msgEvent.fire(new MessageEvent(message));

  • observe the event in all services (regardless of their interface, which might be a plus):

    public void consumeMessageEvent(@Observes MessageEvent msgEvent) {..}
    
Dora answered 24/10, 2010 at 21:50 Comment(3)
@Dora The find-all-instances approach looks like an anti-pattern with a well-known-but-not-obvious solution using EventsEvansville
well, I think both are valid. The first means more coupling, indeed, but is, for example, easier to trace later. It depends on your objectives.Dora
(Ancient subject, I know, but also be aware of issues.jboss.org/browse/CDI-535: the ordering of @Inject @Any Instance<Something> stuff; is not guaranteed.)Zerlina
M
0

I had a look at the JSR-299 specification and it doesn't seem that you can do what you want to do easily and I do not have experience enough with Weld to provide code for this special case.

However, based on chapter 12.3 "Bean Discovery" you might be able to declare the implementations as @Alternative's (to avoid Weld complain about multiple implementations) and listen to ProcessBean events to collect when implementations of SocialNetworkService are seen.

Mediocrity answered 24/10, 2010 at 18:18 Comment(2)
that would be even more tedious than the my initial suggestion. Thanks anyway.Dora
The initial suggestion still needs to know about all your implementations - Weld cannot as far as I can see tell you.Bricker

© 2022 - 2024 — McMap. All rights reserved.