palto
palto

Reputation: 3583

How to create instances on the fly in CDI

Let's assume I have a Car class. In my code I want to create 10 cars. Car class has some @Inject annotated dependencies.

What would be the best approach to do this?

CDI has a Provider interface which I can use to create the cars:

@Inject Provider<Car> carProvider;
public void businessMethod(){
    Car car = carProvider.get();
}

Unfortunately that doesn't work if I don't have a CarFactory that has a method with @Produces annotation which creates the car. As much as it reflects real world that I cannot create cars without a factory, I'd rather not write factories for everything. I just want the CDI container to create my car just like any other bean.

How do you recommend I create those Cars?

Upvotes: 15

Views: 16252

Answers (4)

FibreFoX
FibreFoX

Reputation: 2858

You could use qualifiers with your @Produces annotations:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
public @interface MyCars {
}

sample-producer-method:

@Produces
@MyCars
public Car getNewCar(@New Car car){
    return car;
}

usage:

@Inject
@MyCars
private Provider<Car> carProvider;

Upvotes: 3

temaleva
temaleva

Reputation: 321

Just use javax.enterprise.inject.Instance interface instead.

Like this:

public class Bean {

    private Instance<Car> carInstances;

    @Inject
    Bean(@Any Instance<Car> carInstances){
        this.carInstances = carInstances;
    }

    public void use(){
        Car newCar = carInstances.get();
        // Do stuff with car ...
    }

}

Upvotes: 10

Martin Andersson
Martin Andersson

Reputation: 19563

My favorite model for programmatic lookup is to use CDI.current().select().get().

Demonstrated here.

The servlet has a dependency on two CDI beans, one request scoped and the other application scoped:

private final RequestScopedBean requestScoped
            = CDI.current().select(RequestScopedBean.class).get();

private final ApplicationScopedBean applicationScoped
            = CDI.current().select(ApplicationScopedBean.class).get();

The test class that uses this servlet can be found here.

Examine the code and you will notice that the code is fully equivalent with what you would get using @Inject MyBean myBean;.

Upvotes: 10

LightGuard
LightGuard

Reputation: 5378

Another way to do it would be to simple not give Car any CDI scope, that makes it dependent and you'll get a new instance each time it's injected and those instances won't be destroyed until the containing instance is destroyed.

Upvotes: 0

Related Questions