5

Part of my problem here is using the proper vocabulary, so I apologize in advance for what might be a simple matter of terminology.

Suppose I have a Person interface, and a PersonBean class that implements that interface.

Suppose further I have a producer method somewhere (annotated @Produces) that returns a Person. Internally it returns a new PersonBean, but that's neither here nor there.

Finally, suppose I have another CDI bean somewhere with an injection point defined like this:

@Inject
private Person person;

Assuming I have all my beans.xml files in place etc. and have bootstrapped Weld or another CDI-1.0-compliant environment, as this all stands I will get an ambiguous definition error. This makes sense: Weld will find my PersonBean as a candidate for injection (it could just call the constructor) and will find the output of my producer method as a candidate for injection.

What I'd like to do is somehow force the production of Person instances in this application to always route through the producer method.

I understand I could invent some qualifier somewhere and make the producer method produce Person instances that are qualified by that qualifier. If I do that, and change my injection point to include the qualifier, then obviously there's only one source of these qualified injectables (namely my producer method), so voila, problem solved.

But suppose I don't want to invent some bogus qualifier. (I'm not saying this is the case; just trying to more deeply understand the issues.) What are my options? Do I have any? I suppose I could put @Typed(Object.class) on the PersonBean to make it so that it was not seen as a Person by CDI....

Any ideas welcomed, including pointers to documentation, or better ways to understand this. Thanks.

Laird Nelson
  • 12,770
  • 15
  • 64
  • 105

3 Answers3

3

Annotate you PersonBean as @Alternative then it will use the producer method.

Justin
  • 4,015
  • 1
  • 20
  • 31
2

From digesting several different answers here and elsewhere, the solution I've adopted is to use the @Typed annotation with a value of Object.class on my bean. This means that it will only be eligible to be injected into fields that are declared like this:

@Inject
private Object something;

...which thankfully prove to be pretty much nonexistent. :-)

Laird Nelson
  • 12,770
  • 15
  • 64
  • 105
1

What I'd like to do is somehow force the production of Person instances in this application to always route through the producer method.

Seam solder has a solution for this.

I'm not 100% sure how this will develop with the merge of Seam 3 and Deltaspike (the page is so 90s, but the content rocks :-), but putting Solder in your classpath is certainly a safe bet.

Oh, and as far as I know a comparable mechanism made it into the CDI 1.1 spec.

jan groth
  • 12,429
  • 5
  • 34
  • 51
  • So basically: can't force it except by using the `@Typed` annotation in CDI 1.0? – Laird Nelson Jun 06 '12 at 21:47
  • I'm not sure if I understand your comment. You can force the production independently by using `@Unwraps` from Solder. And there is no such thing as `@Typed` in CDI...!? – jan groth Jun 07 '12 at 04:12
  • `@Typed`: http://docs.oracle.com/javaee/6/api/javax/enterprise/inject/Typed.html Briefly, you throttle back the bean types your bean exposes to the CDI innards. It would be one way of telling the CDI machinery to keep its hands off your object and allowing your producer method to instantiate it directly. My use case is creating a `Logger` instance (no no-arg constructor!) so that I can control the kind of `LogRecord` it creates when it logs. – Laird Nelson Jun 07 '12 at 19:44