Reputation: 1029
In Spring DI, declaring an autowired field as Optional enables a client to not inject any value to it. Is this possible using Java EE's CDI? I tried Optional and it fails. I want to know if there is an equivalent mechanism I can use.
Here is what I tried:
public class OmeletteMaker implements EggMaker{
public static void main(String[] args){
WeldContainer container = new Weld().initialize();
OmeletteMaker omeletteMaker = container.instance().select(OmeletteMaker.class).get();
}
@Inject
Optional<Vegetable> vegetable;
}
I get an error message: Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Optional] with qualifiers [@Default] at injection point [[BackedAnnotatedField] @Inject cafeteria.OmeletteMaker.vegetable]
Upvotes: 1
Views: 2061
Reputation: 16174
There are many questions lurking in this seemingly simple question. I'll try to answer them bearing in mind the spirit of the question.
First, as a general rule, if you @Inject
a Fred
, that Fred
cannot be null
unless Fred
is in @Dependent
scope, and even then a producer method or custom bean will have to explicitly be written to return null
. There are edge cases but in all modern CDI implementations this is a good rule of thumb to bear in mind.
Second, Optional
isn't special. From the standpoint of CDI, an Optional
is just another Java object, so see my first statement above. If you have something that produces an Optional
(like a producer method) then it cannot make a null
Optional
(unless, again, the production is defined to be in the @Dependent
scope—and if you were writing such a method to make Optional
instances and returning null
you are definitely going to confuse your users). If you are in control of producing Optional
instances, then you can make them any way you like.
Third, in case you want to test to see if there is a managed bean or a producer of some kind for a Fred
, you can, as one of the comments on your question indicates, inject a Provider<Fred>
or an Instance<Fred>
. These are "made" by the container automatically: you don't have to write anything special to produce them yourself. A Provider<Fred>
is an accessor of Fred
instances and does not attempt to acquire an instance until its get()
method is called.
An Instance
is a Provider
and an Iterable
of all known Fred
s and can additionally tell you whether (a) it is "unsatisfied"—there are no producers of Fred
at all—and (b) it is "resolvable"—i.e. there is exactly one producer of Fred
.
Fourth, the common idiom in cases where you want to see if something is there is to inject an Instance
parameterized with the type you want, and then check its isResolvable()
method. If that returns true
, then you can call its get()
method and trust that its return value will be non-null
(assuming the thing it makes is not in @Dependent
scope).
I hope this is helpful!
Upvotes: 11