Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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();)?

like image 810
amphibient Avatar asked Nov 25 '14 17:11

amphibient


2 Answers

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

like image 182
rekiem87 Avatar answered Sep 20 '22 20:09

rekiem87


Background: Everything within CDI operates within a Context. That being said

  1. 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.

  1. 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) )
like image 28
kolossus Avatar answered Sep 20 '22 20:09

kolossus