Resolution of external (3rd party) beans in weld
Asked Answered
A

2

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)

Aiken answered 15/2, 2010 at 8:41 Comment(0)
F
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.

Flunk answered 26/2, 2010 at 20:37 Comment(4)
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???Susi
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)?Flunk
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 <include package="com.thirdparty.*" />. 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.Susi
@Susi you can do that easily with a CDI Extension as well. Just add a Bean<T> 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.xmlFlunk
G
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)

Guardsman answered 15/2, 2010 at 10:2 Comment(8)
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 - relation.to/Bloggers/WhyIsBeansxmlRequiredInCDI And I'm trying to see how can 3rd party objects that are not in bean archives be used.Aiken
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?Aiken
@Aiken 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 :)Guardsman
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 :) )Aiken
@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.Guardsman
@Aiken 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 :)Guardsman
@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 :) )Aiken
I edited your answer to include the answer I got at the weld forum :)Aiken

© 2022 - 2024 — McMap. All rights reserved.