Search code examples
javajakarta-eecdi

CDI Produce Instance Created At Runtime


I am new to cdi producer pattern and so far I have seen examples producing simple content already known at initialization point of a class. Now I have to produce an instance created at runtime and filled with some data which also happens at runtime. Here is my current approach but to me it aint that good... Is there a better approach so please help me out with some patterns and practices

 public class myBean {
 private DataHolder dataHolder;

  @Produces
  public DataHolder {
   // dataHolder is null until I later init instance 
   return dataHolder;
  }
}

At some point in my code I set the dataHolder to new istance and allow futher injections to use runtime data by doing this:

dataHolder = new DataHolder(data1, data2, data3);

That looks kinda cheep :) is there a better way? or a nice pattern for producing cdi stuff?


Solution

  • Your approach is indeed clumsy because if there is an injection of DataHolder any time before you initialize it - it will return null (if you produce a @Dependent object) or even crash (with any other scope).

    I suggest you do some reading on Producer methods either in CDI spec or Weld doc.

    Now, my take on this. The cleanest approach would be to let the body of the producer work do all the creation job every time. That means either:

    1. Adding parameters to producer method (NOTE: they have to be injectable beans)
    2. Having the parameters necessary to create DataHolder in your MyBean class ever since it's creation and read them (they have to be available to producer at all times)
    3. Put the logic necessary to retrieve these parameters to the producer method

    If you stick with returning a @Dependent bean, your producer is allowed to return null - you can make use of that if you so wish. The injection point can then expect a possible null value which can be interpreted as 'not yet initialized'. Or, if you need different scope (@ApplicationScoped, @RequestScoped, ...) then it's probably easier to create a second dummy implementation of DataHolder which will, again, mean 'not yet implemented'.

    Side note: Any manually created object (e.g. using new) in CDI will not have it's injection points resolved automatically. That means, if you inject anything into DataHolder while creating the DataHolder itself using new, there will be null.