Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
521 views
in Technique[技术] by (71.8m points)

jakarta ee - CDI Ambiguous dependency with @Produces - why?

I am using code like below:

public Configuration {

    private boolean isBatmanCar = someMethod(...);

    @Produces
    public Car getCar(@New Car car) {
        if(isBatmanCar) {
            car.setName("BatmanCar");
        }
        return car;
    }
}

public Car {
    private String name = "NormalCar";

    public void setName(String name) {
        this.name = name;
    }
}

public Demo {
    @Inject
    Car car;

    // rest of code
}

When I deploy an application to glassfish (Java EE 6 btw) I get

AmbiguousResolutionException: WELD-001318 Cannot resolve an ambiguous dependency between (...) Car with qualifiers [@Any @Default] (...) Producer Method [Car] with qualifiers [@Any @Default]

I know that when I add @Alternative to Car class it will work, but I wonder if this is the proper way to do it, and why do I have to do it?

Can you tell me what is the correct usage of @Produces in such case?

I'm using Java EE 6, CDI 1.0, EJB 3.1, Glassfish 3.2

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The error comes from the fact that you have 2 beans of type Car, one being the class, the other being the producer. You have 2 obvious solutions to resolve the ambiguity:

First, you put the logic behind isBatmanCar field in the original class (in a constructor or a @PostConstruct method for instance) and remove your producer. That would left only one Car bean.

Or if you really want to have 2 bean or can't avoid it you should create a qualifier for your produced bean:

 @Target({ TYPE, METHOD, PARAMETER, FIELD })
 @Retention(RUNTIME)
 @Documented
 @Qualifier
 public @interface BatmanChecked {
 }

and use it on producer,

@Produces
@BatmanChecked
public Car getCar(Car car) {...}

to be able to inject the type of car

@Inject
Car stdCar;

@Inject
@BatmanChecked
Car batCheckedCar;

Qualifier is the natural option to resolve ambiguous injection. Using @Alternative also works but it's more a trick here than a good practice.

Last remark: @New is not necessary here, since your Car bean has no scope (so is @Dependent scoped). @New is only useful when a producer inject a bean with a scope that is not @Dependent. That said, this code is not very useful if your Car class is in scope @Dependent.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...