Injecting just beans ?

Until now I’ve shown you how to inject beans with a simple @Inject. If we focus on the book number generator example I’ve been using, we have a Servlet and a RESTService being injected an implementation of the NumberGenerator interface. Thanks to qualifiers, the servlet can specifically ask to get the IsbnGenerator by specifying the @ThirteenDigit qualifier on the injection point and the rest service an IssnGenerator with a @EightDigits (check my first post). The following class diagram shows you some combinations of bean injection :

But as you can see, all this is are beans injecting other beans. Can we just inject beans with CDI ? The answer is no, you can inject anything anywhere.

Producers

Yes, you can inject anything anywhere, the only thing you have to do is produce the thing you want to inject. For that, CDI has producers (a nice implementation of the Factory pattern) A producer exposes any sort of :

Class : unrestricted set of bean types, superclass, and all interfaces it implements directly or indirectly

Interface : unrestricted set of bean types, interfaces it extends directly or indirectly, and java.lang.Object

Primitive and Java array type

So by that you can inject a java.util.Date, java.lang.String or even an int. Let’s start by producing and injecting some data types and primitives.

Producing data types and primitives

One example of injecting anything anywhere is the possibility to inject data types or primitives. So let’s inject a String and an int. For that I need to add extra classes to our model. Until now, the IsbnGenerator would generate a random number like 13-124-454644-4. I can say that this number is made of a String that acts like a prefix (13-124) and an int that acts like a suffix (4). The following class diagram shows the two new classes PrefixGenerator and PostfixGeneratorthat will be used by the number generators :

If we look at the code of the PrefixGenerator for example, you can see that the class itself is not annotated by any qualifier, but the methods are. The method getIsbnPrefix returns a String that is qualified with @ThirteenDigits. This String is produced by CDI (thanks to @Produces), meaning that you can now inject it with @Inject using its qualifier (@ThirteenDigits)

So now let’s change the way an ISBN number is generated. The bean IsbnGenerator now injects both a String and an int with @Inject @ThirteenDigits. You understand now what strong typing means with CDI. Using the same syntax (@Inject @ThirteenDigits), CDI knows that it needs to inject a String, an int or an implementation of a NumberGenerator.

Injecting Java EE resources with producer fields

So if CDI can inject anything anywhere, if CDI can even inject Strings and integers, what about Java EE resources ? That’s another story and producers are here to help. As I’ve said before, CDI is all about type safety : CDI doesn’t like Strings, so there is no way to inject a resource by its JNDI name such as @Inject(name=”jms/OrderQueue”). A common example is the entity manager. This is how you must inject it in Java EE 6 if you don’t use CDI :

So why can’t you just @Inject an entity manager? If you remember my first post about ambiguous injection, this is the same problem. You can have several persistence units (named with a string), so if you just use an @Inject, CDI will not know which persistence unit to inject. Instead you must produce the entity manager first, give it a name (if you don’t want the @Default) and then an @Inject as follow :

The DatabaseProducer class uses the @PersistenceContext to inject the entity manager with the persistence unit cdiPU. It gives it a name using a qualifier (@BookStoreDatabase) and produces it so it can now be injected in an EJB as follow :

Another nice use case is to produce JMS factories and destinations. @Resource allows you to get a JNDI reference to a specific JMS factory or destination, the qualifier @Order gives it a name, and the @Produces allows you to inject it :

Producing Java EE resources with producer methods

The examples above are pretty simple : produce a field and you can then inject it. That’s called producer field. But sometimes you need a more complex business logic to produce a bean, that’s what we called producer method. Let’s take another use case. When you need to send a JMS message you always end up injecting a JMS Factory, a destination (queue or topic) creating a connection, then a session and so on until you actually send your message. Because this code is repetitive and error prone, why not externalize all of if into a single class and produce a session so the other components can use when sending a message. This class could look something like that :

First, the class uses the @Resource to get a reference of the QueueConnectionFactory and Queue. For the same reason I just explain above, you can have several JMS factories and destinations and you must distinguish them by their JNDI name. And because CDI does not allow you to give a string name on an injection point, you must still use @Resource instead of @Inject. The createOrderConnection method take a QueueConnectionFactory creates a QueueConnection and produces it (while giving it the name of @Order). If you look carefully at the method createOrderSession it takes the produced QueueConnection and creates a QueueSession. An external component then just needs to inject the JMS session without going through the process of creating it :

Producing and… disposing

I can hear you saying “ok, that’s nice, I have an external class doing all the plumbing and creating a connection and a session…. but who is going to close it ?“. Indeed, someone needs to free these resources by closing them. And that’s when CDI brings you another nice bit of magic : @Disposes.

To ask CDI to close a resource you just need to create a method which signature is the same as the one that created it (createOrderSession(@Order QueueConnection conn) creates a session and closeOrderSession(@Order QueueConnection conn) closes it) and add a @Disposes. CDI will dispose the resources in the right order (session first, connection second) for you. I haven’t mentioned it yet but CDI will create and dispose resources depending on the scope (resquest, session, application, conversation…). But that’s for another post.

Conclusion

As you’ve seen in my previous posts (Part I, Part II), CDI is about injection (I’ll explain other topics later). So far I’ve been showing you how to inject beans, but you know now that you can inject anything (String, integer, entity manager, JMS factories…) anywhere (in POJOs, Servlets, EJBs…). You just need to produce what you need to inject (either with field producers or method producers).
The next article will cover alternatives, so stay tuned.

Post navigation

With @Produces it allows me to understand that the injected @EJB is conforming to the EJB container rules (pooling, transactionality, locating through beanName, beanInterface, etc.).

However, I just wander, in one of your previous post you’ve said that basically you can just swap @EJB to @Inject (in case of injecting EJB’s) and that it will work.
I wonder – without the @Produces method on @EJB annotated resource, does the CDI’s @Inject obey the EJB-container rules? I.e., will it inject me the EJB taken from the EJB-container pool?

I guess that the cooperation between CDI container and EJB container without specifying the explicit @Produces methods is quite misty for me…

Hi. Well, I have no objection with this idea. The only concern I have is that I won’t be able to understand your translation and, therefore, approve or disapprove it. But at the end of the day, if your translation points to my original post, readers can then make their mine. So if you feel like it, I’ll be honoured to have a russian translation.

Good point Pedro and that gives me inspiration for another blog (the next one maybe). From Java EE 6, JNDI name are standards. That means if you deploy an EJB, the container gives it a standard unique name. CDI “knows” about this name, so it can @Inject the EJB. But that’s not true with remote interfaces, you need to use @Produces in this case.

Keep an eye on this blog, I’ll try to answer this question with deeper information.

Oh, so the CDI uses the standardized JNDI under the hood.. didn’t know that but this makes sense.

I will surely keep an eye on your blog, thanks!

Another thing. Let’s assume I have a local business interface and more than one EJB implementation of it. Using ‘old-schooled’ @EJB annotation I can use @EJB(beanName=…) or @EJB(lookup=…).
I guess that with CDI the plain @Inject on interface type doesn’t make any sense (just like the plain @EJB – injector doesn’t know what implementation to inject), so I would end with Configuration class with i.e.:

Antonio, you’ve said that the CDI knows about the JNDI name of the EJB. If so, does it mean that the CDI uses the JNDI lookup to obtain the EJB?

There is a part in Java EE 6 spec which talks that the JNDI lookup is required to return a new instance of the requested object.
Does it mean that each @Inject uses JNDI lookup and therefore creates a new instance of the EJB?

Hi Antonio, i tried to test the ItemServlet on embedded glassfish 3.1.1 and upon invocation of InputStream os = con.getInputStream(); from my test case during the test run, the servlet gave a NPE which means during runtime within the servlet
@Inject
@NumberOfDigits(Digits.THIRTEEN)
private NumberGenerator numberGenerator;

the above injection of @NumberOfDigits(Digits.THIRTEEN) numbergenerator didn’t work, but when i ran the code on jboss 6.1.0 it worked beautifully.
Any clues as to why the NumberGenerator wasn’t injected correctly?

This note is worth highlighting as the JMS example provided didn’t work in JBoss without specifying a scope because the connection was being disposed/closed immediately after the session was created. Add @RequestScoped after all the @Produces annotations to resolve this problem.

I write you to ask you about a generic library that i have included in my proyect, i build this library using only a few concept about CDI.
i’m reading your post about CDI and I have learned new concepts like CDI producers.
You can receive my source code or a class diagram to explain my proyect configuration to estimate if is possible put (CDI producers) to build the differents artifacts in my proyect.