Please explain the @Produces annotation in CDI

61,253

Solution 1

Section 3.3 of the CDI specification gives a pretty good high level overview of the use of the @Produces annotation:

A producer method acts as a source of objects to be injected, where:

• the objects to be injected are not required to be instances of beans, or
• the concrete type of the objects to be injected may vary at runtime, or
• the objects require some custom initialization that is not performed by the bean constructor.

Let's say, for example, that you wanted to bridge between a Java EE managed component like an entity manager and other CDI components, you could utilize the @Produces annotation. Another benefit being that you avoid having to duplicate @PersistenceContext annotations throughout your data domain layer.

class A {
    @PersistenceContext       // This is a JPA annotation
    @Produces                 // This is a CDI 'hook'
    private EntityManager em; 
}

class B {
   @Inject                    // Now we can inject an entity manager
   private EntityManager em;
}

Another handy use is for getting around libraries that do not have CDI friendly beans (for example, no default constructors):

class SomeTPLClass {
    public SomeTPLClass(String id) {
    }
}

class SomeTPLClassProducer {
    @Produces
    public SomeTPLClass getInstance() {
        return new SomeTPLClass("");
    }
}

The Javadoc for produces also shows an interesting (but fairly rare case) of producing a named collection that can later on be injected into other managed beans (very cool):

public class Shop { 
    @Produces @ApplicationScoped 
    @Catalog @Named("catalog") 
    private List<Product> products = new LinkedList<Product>(8);

    //...
}

public class OrderProcessor {
    @Inject
    @Catalog
    private List<Product> products;
}

The container is responsible for processing all methods and fields marked with a @Produces annotation, and will normally do this when your application is deployed. The processed methods and fields will then be used as part of the injection point resolution for managed beans, as needed.

Solution 2

The example didn't quite work for me. What dit work was a minor tweak:

@Alternative
class SomeTPLClass {
    public SomeTPLClass(String id) {
    }
}

class SomeTPLClassProducer {
    @Produces
    public SomeTPLClass getInstance() {
        return new SomeTPLClass("");
    }
}

So i had to add @Alternative on my class to get rid of the error that there were two options for @Default.

Share:
61,253
user798719
Author by

user798719

Some questions may end up being dumb, but if I ask it, it's not dumb to me.

Updated on July 09, 2022

Comments

  • user798719
    user798719 almost 2 years

    I have read about the @Produces annotation in CDI, but I don't understand its usage.

    public class Resources {
    
    // Expose an entity manager using the resource producer pattern
    @SuppressWarnings("unused")
    @PersistenceContext
    @Produces
    private EntityManager em;                                        // 
    
    @Produces
    Logger getLogger(InjectionPoint ip) {                            // 
        String category = ip.getMember()
                            .getDeclaringClass()
                            .getName();
        return Logger.getLogger(category);
    }
    
    @Produces
    FacesContext getFacesContext() {                                 // 
        return FacesContext.getCurrentInstance();
    }
    

    }

    taken from: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/guide/GreeterQuickstart/#GreeterQuickstart-

    How does the container know to call a producer method? If I inject an EntityManager, how does the container call the @produces EntityManager? And how would a getLogger producer method get called?

    I also don't see the reason to go through all of the trouble.

  • Reitffunk
    Reitffunk almost 10 years
    Nice answer. Thx for that. But I have a question regarding your first example. Lets say Class Calso @Produces an EntityManager. Wherefrom does Class B know which from these to inject?
  • Tex
    Tex about 9 years
    @Produces can only be used once by Class
  • Rob L
    Rob L almost 9 years
    @Perception - I very much appreciate your effort here and I think you added great content. However, for a JavaEE newbie I still don't see what the annotation does? In the first example with the EntityManager, why does adding this annotation make it so you can use @Inject? Also, what does 'A producer method acts as a source of objects to be injected' exactly mean? What does it mean to be a source of objects?
  • Thang Hoang
    Thang Hoang over 8 years
    @ Inject mean you can use the object without manual create it. @ Produres is where you create it. And for EntityManager, I think jboss create it for you with @ PersistenceContext