views:

84

answers:

2

I know it is still not quite popular, since the spec was released just a few months ago.

I haven't "installed" weld yet, I'm just reading, and by this question I want to make sure I've understood this important point correct:

Is resolution of beans that are in 3rd-party jars achieved by declaring them as <alternatives> in your beans.xml?

If not, how to use beans from 3rd party libraries that don't have beans.xml ?

Putting the jar on the classpath won't work unless there is beans.xml in their META-INF, which you can't make true for 3rd party jars. (see Gavin King's post on the subject)

+2  A: 

My understanding of an alternative is that it's an alternative to some other implementation of an interface that you can use in a different deployment environment (e.g. a testing environment). An alternative bean is declared by annotating it with @Alternative.

To use an alternative in a given deployment scenario, you select it in the <alternatives> element of your CDI deployment descriptor META-INF/beans.xml. This will enable @Alternative beans which are disables by default.

When enabled, if the container finds an ambiguous dependency for a given injection point, it will look at alternatives that could be injected and, if there is exactly one, pick up this alternative.

In other words, alternatives are a nice way to replace an existing implementation with another one at deployment time. If there is nothing to replace, you don't need alternatives, just put your jar on the class path. Not sure this was exactly your question though, I have a doubt about the concept of 3rd-party jars.

More in 2.1.4. Alternatives, 4.6. Alternatives and 4.7. Fixing unsatisfied and ambiguous dependencies (but I guess that this is what you're reading).

Update: To answer your additional question.

If not, how to use beans from 3rd party libraries that don't have beans.xml

This can't happen, a bean archive must have a bean.xml (be it empty) as detailed in the section 15.6. Packaging and deployment of the documentation:

CDI doesn't define any special deployment archive. You can package beans in JARs, EJB-JARs or WARs—any deployment location in the application classpath. However, the archive must be a "bean archive". That means each archive that contains beans must include a file named beans.xml in the META-INF directory of the classpath or WEB-INF directory of the web root (for WAR archives). The file may be empty. Beans deployed in archives that do not have a beans.xml file will not be available for use in the application.

Then, to fix an unsatisfied and ambiguous dependency, refer to the section 4.7 previously mentioned.

Update 2: It appears that using BeforeBeanDiscovery.addAnnotatedType() it is possible to add other classes to be taken into consideration during bean discovery. (BeforeBeanDiscovery is an event)

Pascal Thivent
aha, so it's not this one. Unfortunately putting a jar in the classpath won't work, unless you have a `beans.xml` in it - see Gavin King's blogpost - http://relation.to/Bloggers/WhyIsBeansxmlRequiredInCDI And I'm trying to see how can 3rd party objects that are not in bean archives be used.
Bozho
so, if you want to use, let's say, c3p0 connection pool, they (or you) must put `beans.xml` in the jar, otherwise you won't be able to use it with DI?
Bozho
@Bozho Yes, the beans.xml is mandatory for a "bean archive" or the beans won't be available to the application, as documented (was updating my answer when you posted your comment). I didn't mention it explicitly when I wrote "put it on the class path" in my initial answer but it was implied :)
Pascal Thivent
Thanks. That sounds very bad to me, btw. I think sooner or later this will appear as a requirement.(btw, I'm reading it because I'm planning to provide a partial implementation of JSR299 as my graduation project. And there I'll probably provide some non-standard way of using external beans :) )
Bozho
@Bozha It not easy to think of all possible use case but that's my understanding indeed. Actually, I wonder what will be the impact of CDI on libraries, what kind of doors it opens (this is still so new). Maybe a wrapper bean will do the trick for now.
Pascal Thivent
@Bozho I don't think it's so bad to have to provide a beans.xml, I don't really want the entire earth to be visible (even more true now that I've read Gavin's blog post). Nice graduation project btw :)
Pascal Thivent
@Pascal of course not the entire world, but, much like spring's `<bean>` tag you should be able to use everything if you mention it explicitly. (As for the graduation project, I decided that some trivial university-style project won't be a challenge :) )
Bozho
I edited your answer to include the answer I got at the weld forum :)
Bozho
@Bozho Thanks. Extremely interesting.
Pascal Thivent
+1  A: 

Hi folks, why think so complicated?

Simply make a producerMethod for those 3rd party classes.

Let's assume you have a 3rd party library which automatically takes PDF files and sends them per faximile, and you like to use something like

private @Inject PdfFaxService faxService;

in your code, then you could simply provide this with a producer method. The PdfFaxService works stateless, so we can safely assume that we can make it @ApplicationScoped:

public @Produces @ApplicationScoped PdfFaxService createFaxService() {
  return new PdfFaxService(initparameters);
}

somewhere.

hth.

LieGrue, strub