Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Please explain the @Produces annotation in CDI

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.

like image 754
user798719 Avatar asked May 14 '13 03:05

user798719


People also ask

What is the use of @inject annotation?

Injectable constructors are annotated with @Inject and accept zero or more dependencies as arguments. @Inject can apply to at most one constructor per class. @Inject is optional for public, no-argument constructors when no other constructors are present. This enables injectors to invoke default constructors.

What is CDI producer?

Java EE CDI introduced a concept called Producer. Producers may be used to create - or produce - bean instances to be consumed by an application. Producers are also able to provide specific interface implementations according to the consumer needs so they are a valid way to support polymorphism in a CDI application.

What is inject annotation in Java?

4.1. The @Inject annotation lets us define an injection point that is injected during bean instantiation. Injection can occur via three different mechanisms. Bean constructor parameter injection: public class Checkout { private final ShoppingCart cart; @Inject.

What are the method and producer?

A producer method generates an object that can then be injected. Typically, you use producer methods in the following situations: When you want to inject an object that is not itself a bean. When the concrete type of the object to be injected may vary at runtime.


2 Answers

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.

like image 125
Perception Avatar answered Sep 29 '22 06:09

Perception


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.

like image 23
Hans Avatar answered Sep 29 '22 06:09

Hans