Ckkn
Ckkn

Reputation: 139

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?

Upvotes: 1

Views: 1313

Answers (2)

Siliarus
Siliarus

Reputation: 6753

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.

Upvotes: 2

Nico
Nico

Reputation: 1803

One way would be to do this:

@Produces
@RequestScoped
public Coder getCoder(@New DataHolder dataHolder) 
{
   return dataHolder;      
}

another way would be to use what you get as informations for the producer method, such as the InjectionPoint or what else you reach into it.

@Produces
@RequestScoped
public Coder getCoder(@New DataHolder dataHolder, InjectionPoint injectionPoint, ClassA a, ClassB b) 
{
   String stringA = a.function();
   dataHolder.someFunction(stringA);
   return dataHolder;      
}

I used the last method to create my device with everything I need and need to do nothing else. Some resources to look at it can be found at byteslounge.com and Jboss docs

EDIT: The information was quite hard to find for me, but a CDI Producer works in the way that everything you declare as parameter for e.g: getCoder will be injected at call-time. So you can inject services that can help you to collect information at runtime.

Upvotes: 0

Related Questions