3 Replies Latest reply: Apr 17, 2012 4:46 PM by Marko Lukša RSS

Inject dynamically in for loop

Paul Grillo Newbie

Forgive me if this is a question with a simple solution, i'm trying to get my hands around all of the power of CDI.

Our traditional products were based on home grown factories that were explicitly called, and i'm trying to put together a capability that replaces all that i have.

 

At any rate, we have situation in which we need to obtain a new instance of an object at runtime.

 

Example:

 

// I would like Instance to be a container bean, most likely @Produced, and scoped @Dependent.  Assume this producer exists ...

void populateLineItems(){

     List<Instance> aList = new ArrayList<Instance>();

     for (int i=0;i<x;i++){

       aList.add(new Instance()); // well, this is not what i want.  I want the container to create it.  Moreover the producer knows what "type" of Instance to create

      // @Inject doesn't seem to be available here, so how do i add the Container created bean in the line above?

     }

}

 

While my homegrown factory could serve up the appropriate Instance, i wish them to be contaner/cdi created so they display the same capabilities as all of our beans, dependent or scoped.

Thanks for any ideas, i'm hoping i just missed something that was flat obvious...

  • 1. Re: Inject dynamically in for loop
    Marko Lukša Apprentice

    Can you give an example of what the actual classes would be (instead of your generic "Instance"). You probably have some concrete classes in mind? The fact that you are storing Instances in a List, gives me the feeling that you want to make managed beans out of objects that aren't really meant to be managed.

     

    Anyhow, you can obtain bean objects dinamically through BeanManager (see getBeans(), resolve() and getReference()).

  • 2. Re: Inject dynamically in for loop
    Paul Grillo Newbie

    Well, that's the rub, for me.  I put together basic capabilities common code so that many engineers in the company build separate products from it. We generally provide these other applications the capability to specialize most classes.  We try to abstract as much complication as we can from it.

    So traditionally, we have a base factory that builds "all" objects, and our products specialize that factory and override construction of their own objects.  It's probably a bit more complicated, but that is the idea.

     

    So, we have now introduced thin client (JSF/CDI...) capabilities and need to provide the same general functionality.

     

    We do generally have two types of beans.  ManageXXXBean and XXXBean, in which XXXBean generally is bound to jsf/xhtml and ManageXXXBean orchestrates some of the events (process, save, etc)

     

    So, to give you an idea.  ManageOrderBean and OrderBean are scoped contextually.  ManageOrderBean has a  hypothetical method in there that might be called from a page to add another LineItem to the Order.  The LineItem that gets created might be OrderLineItem or it could be a specialized one.

     

    So, i'm guessing that your question is whether OrderLineItem should be "managed".  Well, here's the problem for me.  We have a few application and session scoped beans that hold information that all of our beans might need access to, and these are generally injected.  So, i don't want our engineers to have to "know" or figure out what beans are "managed" and which are not.  OrderLineItemBean needs access to an application bean that provides base stuff like productID (our application specific id, etc).

     

    So, i'm wanting OrderLineItemBean to be Managed and @Dependent on the container (OrderBean, in this case).  Now our engineers can utilize the same "tools" injection or whatnot regardless of what "bean" they are in...

     

    So that's the long story.  In the example below, i need the container to create the appropriate "instance" of OrderLineItemBean (might be specialized), could be injected, but also needs to be created at will.

     

    So, essentially, my approach is to have a Factory that @Produces my beans, and the factory can have an alternate so that our produce a special one where needed.  However, i'm still left with ensuring that i can create a bean at will but have the container do it for me...  i will look into BeanManager.  Looks like an extension.  getBean() returns a new one from the container if required?  Thanks for your time.

     

     

    @Named("manageOrderBean")
    @ConversationScoped
    public class ManageOrderBean {
    @Inject OrderBean orderBean;
      public void addNewOrderLineItem() {
        OrderLineItemBean oli = new OrderLineItemBean();
        orderBean.getLineItems().add(oli);
      }
    }
    
    
    
    
    @Named("orderBean")
    @ConversationScoped
    public class OrderBean {
      List<OrderLineItemBean> lineItems = new ArrayList<OrderLineItemBean>();
      
      public List<OrderLineItemBean> getLineItems(){
        return lineItems;
      }
    }
    
    public class OrderLineItemBean {
     ... 
    }
    
    
    
    
    
  • 3. Re: Inject dynamically in for loop
    Marko Lukša Apprentice

    CDI beans are singleton-ish (in the context of a scope), so you will not be able to create multiple OrderLineItemBeans simply by calling BeanManager's methods.

     

    But, you can create instances yourself and then perform injection into them through InjectionTarget. See http://docs.jboss.org/weld/reference/latest/en-US/html/extend.html#d0e4978