CDI bean doesn’t get discovered unless explicitly annotated - java

What does it mean when Weld says "unsatisfied dependency for type Foo" when the bean is POJO but, as soon as I add #Dependent at the top, everything works ok?
I remember it used to work fine without specifying the scope. I think I broke something.
The specs say:
A managed bean is implemented by a Java class, which is called its bean class. A top-level Java class is a managed bean if it is defined to be a managed bean by any other Java EE technology specification, such as the JavaServer Faces technology specification, or if it meets all the following conditions.
It is not a nonstatic inner class.
It is a concrete class or is annotated #Decorator.
It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in ejb-jar.xml.
It has an appropriate constructor. That is, one of the following is the case.
The class has a constructor with no parameters.
The class declares a constructor annotated #Inject.
No special declaration, such as an annotation, is required to define a managed bean.

Sounds like you were used to CDI 1.0 and are now confused by implicit bean archives introduced in CDI 1.1.
beans.xml is now optional, and implicit bean archives are the default, which means that a class is a bean candidate only if it has a bean defining annotation like #Dependent, #RequestScoped etc.

Related

CDI beans and producers

I have three questions
Generally, a bean is just a Pojo that is managed by a container (like Ejb container or CDI container), right? As for when a bean is considered an EJB is quite clear. You will have something like #Stateless or #Stateful. But I don't understand fully when a bean is considered CDI bean. Defining the scope (e.g. #RequestScope) is an indication but what about other classes? In short, when I create and write my own classes, how can I make them CDI bean instead of make them plain Java classes? The only thing I have found about this is https://docs.oracle.com/javaee/6/tutorial/doc/gjfzi.html
Related to above, in this tutorial
https://dzone.com/articles/cdi-and-the-produces-annotation-for-factory
in step 4 says that "CDI does not know how to inject the SpecialLogger object", because of LogConfiguration, so why LogConfiguration is not considered a CDI bean and cannot be injected, and needed to create a producer method ?
I don't understand when we use a producer method, in this example we use it to create a SpecialLogger object but why, we shouldn't just inject SpecialLogger?
Firstly, EJB and CDI are two different specifications with different limitations and goals. Later on in Java/Jakarta EE evolution, CDI created a bridge between the two where it considers all EJB beans to also be CDI beans (the internals of which are more complex and I won't go into now) but otherwise they are still different specs so don't conflate them.
In CDI, beans can be either managed beans or producer methods/fields. Managed beans are typically a java class which can (or in some cases must) have certain annotations to be picked up as a bean. There are some limitations as to how a managed bean looks. See this section of specification (CDI 4, Jakarta EE 10) for further information. Producer methods/fields are a way to declare a bean while also providing an instance of the bean yourself instead of letting CDI create it. In both cases, CDI then manages the bean for its lifecycle, which is typically controlled by the scope of the bean (i.e. #RequestScoped).
However, that's not all there is to it. You mentioned discovery and that's part of the process. There are three discovery modes - none, all, annotated - which can be declared in beans.xml. These control which beans will be found and if they need any kind of annotation to be recognized as beans. none simply means no beans, all means that all classes will be picked up as potential beans, even without annotations. And lastly, annotated will only pick up beans that have a so called bean defining annotation. These include scope annotations, stereotypes, and interceptor annotation. See this part of spec (CDI 4).
Note that prior to CDI 4, default discovery mode was all. With CDI 4 and onwards, it is annotated!
To your second question - SpecialLogger has no no-args constructor and has one constructor with parameters (LogConfiguration) and this constructor isn't annotated with #Inject. Therefore, CDI doesn't know how to create an instance of this object. Note that annotating the constructor with #Inject effectively tells CDI that all of its parameters are also CDI beans that it should know how to instantiate which is not going to be the case in this example.
This brings me to your last question. A producer is typically useful for when it isn't easy or even possible to have an instance of the class created automatically by CDI, but there is still value in handling the instance as a CDI bean. Once you define a producer for SpecialLogger, you can then normally #Inject SpecialLogger in your code. In the end, user won't know if their bean is a product of CDI class instantiation or a producer method. Since bean types of producer method are governed by transitive closure on method's return type, you can also choose to return one of several subclasses based on some config options etc. Overall, it gives you more control over how to create and initialize an object before you hand it over to CDI but at the cost of not having this object injected (since it is you who creates it and not CDI).

spring autowired vs resource

So my question why did #javax.annotation.Resource worked but #AutoWired did not. For a test on a Restful controller, I was trying to inject MappingJackson2HttpMessageConverter with #Autowired, on start up the container failed to find a qualifying bean even though that class was on the path. Now, to solve this I went into a context xml file and added the bean:
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
Then in the test class had member variable:
#javax.annotation.Resource(name="jsonConverter")
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
Then spring finds the bean. Does Autowire only work for beans that were identified as beans by package scan?
Thanks ahead of time.
Autowired and Resource merely make the class types of annotated field, method or constructor eligible for dependency injection - it does not automatically add those types to the context of your Spring application!
So, as you suspect, in order for the annotations to work, you have to ensure that the auto-wired types are available in the application context yourself, e.g. with the Component annotation and package scan or by explicitly defining the bean in your application-context.xml as you did in your example.
In both cases Spring wires the dependency only when the bean getting wired is defined into spring context. You have to either define the bean in xml file or use annotation based bean definition to make it eligible for wiring.
On the other note, #Resource does name based wiring whereas #Autowire by default goes with type based.
Please see #Resource vs #Autowired for more context on topic.
This is from Spring reference. The second para may provide pointers.
If you intend to express annotation-driven injection by name, do not
primarily use #Autowired, even if is technically capable of referring
to a bean name through #Qualifier values. Instead, use the JSR-250
#Resource annotation, which is semantically defined to identify a
specific target component by its unique name, with the declared type
being irrelevant for the matching process.
As a specific consequence of this semantic difference, beans that are
themselves defined as a collection or map type cannot be injected
through #Autowired, because type matching is not properly applicable
to them. Use #Resource for such beans, referring to the specific
collection or map bean by unique name.
#Autowired applies to fields, constructors, and multi-argument
methods, allowing for narrowing through qualifier annotations at the
parameter level. By contrast, #Resource is supported only for fields
and bean property setter methods with a single argument. As a
consequence, stick with qualifiers if your injection target is a
constructor or a multi-argument method.
I think, in your case, there could be some issue with the default autowiring by name. So I guess Spring would be able to #Autowire the bean if you mention the qualifier. But then again if it is a case for #Resource, I think I'd prefer using it.

When is injected bean actually initialized?

I have the following scenario in my code base:
//this bean, which will be injected,
//is not annotated
public class HelperUtil {
//only default constructor with no args
public void doThis(String _in) {
//...
}
public void doThat() {
//...
}
}
In the below class we do the injection:
#Named
#Stateless
public class BusinessManager {
#PersistenceContext(unitName = "default")
private EntityManager em;
#Inject
private HelperUtil helperUtil ;
//...
}
Q1: When is the instance of HelperUtil which will be injected actually initialized by calling the default constructor? Is it done when the first client into which it is injected (like BusinessManager) is instantiated when the app server (in my case JBoss) starts (and that one will be initialized by the container because it is annotated as #Stateless)?
Q2: In the above exhibit, will HelperUtil remain a singleton as long as no client other than the container asks for an instance by calling the constructor directly and not obtaining an instance via DI?
Q3: What is the advantage of using DI and #Inject in this case vs. simply calling the constructor directly (HelperUtil helper = new HelperUtil();)?
It depends, but you can control these event to execute some code, for example:
If you need that your bean is executed when the app start you need to add #Startup annotation to your bean.
If you need to initialize your bean without access to other injected resources you can use the normal constructor.
If you need some method to be executed when the bean is initialized then use the #PostConstruct annotation in the method.
You need to remember that the creation depends on the scope of the bean, in you case, which is a stateless bean, the bean will be created if some client injects it and there are no other instance available, if is singleton then will bean created just once, in general the bean will be created when they are needed (a singleton bean initialize until the first client uses it, or at startup with the annotation)
EDIT:
For the third question, the advantage is that if you use a resource, or other bean inside your HelperUtil, they will be initialized with the proper values, for example, if you use an entity manager, or other beans inside your helper. If your helper will handle just things like static methods or other simple utilities then you are right, the advantage is none and you could simply manage like an static helper class, but if you need EE resources the you need the bean to be managed in order to get all injections and resources loaded
EDIT 2:
After some more years programming and using dependency injection in Java and C# Core, I can add: The question 3 is very open, using DI will allow your code to:
be less coupled, if you change your constructor, you then would have to go searching all the new ObjectModified(oldParams) to add the new parameters
more easy to test, because you can inject "fake objects" as dependencies, avoiding the need to load all the system and prepare the state for the test, for example, if you want to check some code that depends on the current hour, you could connect a fake provider in test mode to give always the same hour, or some sequence
Avoid cyclical dependency, where class A depends on B and B depends on A, normally this is more complex, like
ClasssA -> ClasssB -> ClasssC -> ClasssA
When this dependencies are present, you can start a modification, then modify the class that uses it, and so on... until somehow you find yourself modifying the same class as before!, so you start in a cycle because the communication path between your objects are complex.
When you use DI, this cycles can be detected early on, so you can rethink your architecture to avoid this productivity blackholes
DI is a very powerful tool to keep big projects maintainable, is now present in a lot of environments and frameworks because is very useful, if this still does not convince you, you can try start a project in Spring boot, PlayFramework, Net Core, Java EE, Ruby on Rails.... and many others that have include this as the normal flow and build a medium size app, then try without DI
Background: Everything within CDI operates within a Context. That being said
A managed bean's fields are instantiated, on request. From the spec:
When the container creates a new instance of a managed bean, session bean, or of any other Java EE component class supporting injection, the container must:
Initialize the values of all injected fields. The container sets the value of each injected field to an injectable reference.
What this means is that the first initialization of a dependent bean is when it's first called for, which is when the parent bean is initialized. Now, the JSF #ApplicationScoped has the eager="true" attribute, which allows beans of that scope to be initialized before they're needed by any other part of the application, on startup, EJB #Startup for the same effect on EJBs. CDI beans however, don't have that capability out of the box.
The default scope of CDI beans is #Dependent. What this means is that an injected bean inherits the scope of the injection target (except when the bean has its own scope; in that case, its own scope applies). In your case, HelperUtil is not going to live beyond the lifetime of that EJB, sorta like #RequestScoped
Related
how is the #RequestScoped bean instance provided to #SessionScoped bean in runtime here?
Non-lazy instantiation of CDI SessionScoped beans
JSF Named Bean, Eager application scoped (aka #ManagedBean(eager=true) )
I think its constructor is not called until the method is called like helperUtil.dothat(), its not when its containing bean is instantiated.
About all of the injected fields must be initialized by the container when the managed beans are instantiated like the other answer, its true, but all of the injected fields are injected with proxies so they are not the real objects so the real constructors aren't called.
If its constructor is called when its containing bean is instantiated then how about a #RequestScoped bean inside a servlet for example. The servlet is only instantiated one time but the injected #RequestScoped bean must be instantiated multiple times. If its true then surely the #RequestScoped annotation wouldn't work.
So by simply looking at those CDI annotations intention and name like "request" or "session", we know that the real CDI managed bean objects are made/ instantiated independent of the containing user bean instantiation.

Spring Internal - Member instance injection clarification

Spring creates the class objects by Java dynamic proxies (java.lang.reflect.Proxy). i.e
#Component
public class NewsService implements Service{
}
But how the member variables are injected by Spring? ie
#Autowired
private EntityManager em;
Java dynamic proxies uses interface (i.e Service) to create the objects. But how member variables are injected? The instance variables are not known by interface.
Also when member instances are injected? Load time?(When containing class object is created?) or Lazy loading? (when object is used first?)
Few facts for you:
Spring instantiates specific classes, not interfaces. Dependency injection is done on the original bean instance.
When a proxy is created, Spring registers both the original bean and its proxy in the application context. JDK proxy is created for all interfaces implemented by the original bean.
Proxies are not created if they are not necessary (i.e. no aspect is applied on the target bean).
All beans are eagerly initialized by default. If you want some bean to be instantiated in a lazy fashion, you need to specify it explicitly.
Dependency injection happens right after the bean is instantiated. Some dependencies are injected based on the bean definition, other dependencies might be injected by various bean post processors (but they are executed right away as well).
How is dependency injection realized:
When using XML configuration or autowiring , dependency injection is done via Reflection API. Spring is able to either call property setter (setFoo(...)) or set field value directly (reflection allows setting private members).
When using #Bean methods in Java configuration, dependency injection is done by your method.
A bit on proxies:
JDK proxies and CGLIB proxies are two different proxying mechanisms. JDK creates artificial class based on provided interfaces, whereas CGLIB creates artificial subclass of the target class.
Which proxying mechanism is used depends on your Spring configuration (JDK is the default one). For obvious reasons JDK proxy can be used only in cases when your dependencies are referenced only by interface. From the other side you can not use CGLIB proxying for final classes.

What is the default scope of a Named CDI bean?

Is there any default scope for a #Named CDI bean without additional #...Scoped annotations? I have not found any relevant information in the official Weld documentation.
A #Named bean can be accessed over JSF without additional annotations, so some implicit scope seems likely.
Thank you
The default scope is the dependent pseudo-scope #Dependent, as stated in the weld documentation:
CDI features the so-called dependent pseudo-scope. This is the default
scope for a bean which does not explicitly declare a scope type. [...]
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.
The javadoc for this annotation gives some more information about this scope:
Beans declared with scope #Dependent behave differently to beans with
other built-in scope types. When a bean is declared to have scope
#Dependent:
No injected instance of the bean is ever shared between multiple injection points.
Any instance of the bean injected into an object that is being created by the container is bound to the lifecycle of the newly
created object.
When a Unified EL expression in a JSF or JSP page that refers to the bean by its EL name is evaluated, at most one instance of the
bean is instantiated. This instance exists to service just a single
evaluation of the EL expression. It is reused if the bean EL name
appears multiple times in the EL expression, but is never reused when
the EL expression is evaluated again, or when another EL expression
is evaluated.
Any instance of the bean that receives a producer method, producer field, disposer method or observer method invocation exists to
service that invocation only.
Any instance of the bean injected into method parameters of a disposer method or observer method exists to service the method
invocation only.

Categories