CDI when injectionpoint.getBean() can be null - dependency-injection

I'm playing with CDI producers and spotted in doc that
InjectionPoint.getBean()
can return null if the injection point does not belong to a bean.
What does it effectively mean? How can injection point not belong to a bean? Is it possible to inject something into something other what is not CDI bean?
I'd like to get class name of class containing this injection point and now I don't know if I can rely on getBean() method if it can return null?

Chances are VERY good (AFAIK) you'd only see a null if you manually created an InjectionPoint through an extension.

Related

Can CDI dependency injection be optional?

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]
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 Freds 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!

CDI Keeps all Injected tree references of SessionScoped beans?

I am starting a new project with JavaEE 7 and declared a Sessionscoped bean to maintain the web logged user information in session.
The UserSessionBean, as I named it, is intended to be lightweight - trying to avoid lots of data to be kept in the session by Weld. But in some cases I need to get all user information, so added a getUser() method which must query and retrieve a UserEntity from JPA. In order for the method to do its job, I need to #Inject other resources onto the UserSessionBean.
My question is: These dependant resources will be kept and serialised within the UserSessionBean by Weld until the context is destroyed?
The weld documentation says this:
An instance of a dependent bean is never shared between different
clients or different injection points. It is strictly a dependent
object of some other object. It is instantiated when the object it
belongs to is created, and destroyed when the object it belongs to is
destroyed.
That makes me think the all SessionBean tree is kept by weld during session life, but how can I keep a lightweight SessionBean and use injected CDI resources on it?
Since what you're injecting are also CDI beans, it is not the beans themselves that get serialised, but their lightweight proxies. Upon deserialisation, the proxies dynamically resolve the correct beans for whatever scope they are. See section 5.4 Client Proxies of the CDI1.0 spec. Hence, your bean is as lightweight as possible.

Using CDI to inject a Data Access Object

Assuming I have a data access object that I've already written, I'd like to be able to use CDI to inject that into say, a service class. Furthermore, I have two implementations of that DAO.
My understanding of CDI is that I'd have to annotate my DAO implementation class so that CDI would know which implementation to inject.
The problem is, the DAO is in a .jar file. By annotating it with CDI annotations, I'm using JavaEE imports in a non-JavaEE class.
For example, let's say I have the following class
public class BusinessService {
#Inject #SomeMybatisQualifier AccountDAO accountDao;
...
}
The #Inject annotation comes from javax.inject.Inject. Now, this service class is dependent on a JavaEE environment.
Can someone please explain to me what I'm missing? How do I inject a non-annotated class into another non-annotated class? This is fairly simple with Spring.
I agree with LightGuard if there's enough classes. But for a couple, why not just produce them with #Produces?
Here's a decent example of implementing your own producer:
Depedency inject request parameter with CDI and JSF2
You should be able to write return new MyObject(); and you can add whatever qualifiers you want
Not sure what's unclear but here's the gist of things: For CDI to scan a jar for beans it must have a beans.xml. Else it will not be scanned and thus not available for injects.A String is not available either. If you try to inject a String say;
#Inject
String myString;
CDI will have no clue what to give you just like your jar. But I know what String I want (a requestparam) and I can let CDI know as well. How? Well I supply a qualifier #RequestParam to my producer (see example again) and now when I want to use it in client code I do it like this:
#Inject
#RequestParam
String myString;
You can do the same thing. Have a producer and just create a new instance of whatever you need and then return it. Now CDI will know just how to dependency inject that particular bean.
Now say you have 40 classes. Then it gets messy to produce them and you want to make sure it gets scanned instead. Then you write your own little extension, observe when CDI is about to scan and instruct it to scan additional jars. Such extension is probably easy to write but I don't know the details because I have not written any extensions like it
By far, the easiest thing would be to create a CDI extension to add the classes in the jar (because there's no beans.xml in that jar so it won't be picked up by CDI) and add additional qualifiers to the metadata.

Replacing a managed bean

Couple of questions on setting managed bean using CDI.
1. If a session bean is Injected into another using #Inject annotation, how to replace the entire session Bean?
2. In CDI, Is it possible to define Injection to only inject (not to outject).
If a session bean is Injected into another using #Inject annotation, how to replace the entire session Bean?
You don't. This requirement can mean only 1 thing: the session scope is the wrong scope for the bean in question. Perhaps you're looking for the conversation scope instead.
If you really need to, you can always add some clear() method which clears the state (thus, all of its properties) of the session scoped bean, but this is still fishy. Just choose the right scope from the beginning on.

Getting bean properties names in Grails

I'm trying to write a tag, which will render my bean properties and corresponding values. I want the default behaviour be to render all properties from the bean. So I need somehow get all property names from passed bean.
I figured that I could use properties map, but despite bean properties, there are also other things and I'd have to manage it by hand which may be error prone.
I also thought of using DefaultGrailsDomainClass which is handy for domain classes, but is useless for command objects.
Have you ever done something similar and came up with something useful?
Like said here, there are also persistentProperties. But I believe you need GrailsDomainClass.properties - don't confuse with Groovy properties, the former are for domain class.
For rendering, GrailsDomainClassProperty.naturalName will also be useful.
I've done similar thing by using properties, no problem. My code was:
value.properties.entrySet().each { Map.Entry it ->
println "$it.key = $it.value"
}

Resources