6

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)

skaffman
  • 398,947
  • 96
  • 818
  • 769
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140

2 Answers2

6

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.

struberg
  • 730
  • 5
  • 12
  • Is there really no way to achieve this other than defining a producer method? I sometimes really don't understand what is going through some of the designers head when such a simple use case (ie, cause a bean from a 3rd party jar to be a managed bean and able to be injected) requires all of this extra work. It seems like the beans.xml would be a perfect place for this configuration, but it only has an "excludes" element and not an "includes"...really??? – GreenieMeanie Mar 26 '15 at 20:35
  • It is 2 lines of strictly typed code. So you see this in your IDE if you search for the type usage, you have perfect CDI support in most IDEs those days, etc. So I _really_ prefer this to 2 lines of untyped XML. Did you never came across such 600 lines XML monsters nobody can ready anymore (and 80% of it is actually not needed)? – struberg Apr 09 '15 at 09:35
  • It's 2 lines of code FOR EACH CLASS that you want to be able to managed, which in the case of a third party jar, can have many, let's say 100+ for example. The XML could be very simple: ie . That's one line of optional XML (the existing discovery would still work the same way) to possibly include more classes from a JAR file that didn't happen to be built with beans.xml, not 600 like you are implying. Sorry, I still don't see your point. – GreenieMeanie Apr 09 '15 at 22:59
  • @GreenieMeanie you can do that easily with a CDI Extension as well. Just add a Bean dynamically for each scanned class which fits your needs (see ProcessAnnotatedType and AfterBeanDiscovery). Or configure the classnames + use AfterBeanDiscovery#addBean for jars without a beans.xml – struberg Apr 10 '15 at 11:36
3

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)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 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 Feb 15 '10 at 10:13
  • 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 Feb 15 '10 at 10:27
  • @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 Feb 15 '10 at 10:29
  • 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 Feb 15 '10 at 10:32
  • @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 Feb 15 '10 at 10:43
  • @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 Feb 15 '10 at 10:53
  • @Pascal of course not the entire world, but, much like spring's `` 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 Feb 15 '10 at 10:55
  • I edited your answer to include the answer I got at the weld forum :) – Bozho Feb 15 '10 at 18:58
  • @Bozho Thanks. Extremely interesting. – Pascal Thivent Feb 15 '10 at 23:06