marlon
marlon

Reputation: 7633

@Producer annotation in Java EE

I am learning Java EE CDI, dependency injection, and @Produces in particular. I am wondering why in getGreedingCard() method, it needs a @Produces annotation at all, since the two classes GreetingCardImpl and AnotherGreetingCardImpl are already imported into the space. This is just like the regular package/class dependency and a simple import solves the problem. Why does it need a dependency injection through a @producer annotation?

Thanks for explanation in advance.

public interface GreetingCard {
    void sayHello();
}


public class GreetingCardImpl implements GreetingCard {

    public void sayHello() {
        System.out.println("Hello!!!");
    }
}


public class AnotherGreetingCardImpl implements GreetingCard {

    public void sayHello() {
        System.out.println("Have a nice day!!!");
    }
}

import com.javacodegeeks.snippets.enterprise.cdibeans.impl.AnotherGreetingCardImpl;
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;

@SessionScoped
public class GreetingCardFactory implements Serializable {

    private GreetingType greetingType;

    @Produces
    public GreetingCard getGreetingCard() {
        switch (greetingType) {
            case HELLO:
                return new GreetingCardImpl();
            case ANOTHER_HI:
                return new AnotherGreetingCardImpl();
            default:
                return new GreetingCardImpl();
        }
    }
}

Upvotes: 1

Views: 4280

Answers (2)

Gas
Gas

Reputation: 18020

In your case it doesn't need @Produces as you will be injecting factory bean and using its method directly to create instances, and not injecting the greetingCard beans themseleves.

@Inject
GreetingCardFactory factory;

...

GreetingCard card = factory.getGreetingCard();

If you would define it as @Produces method, and the try to inject GreetingCard, then you would get exception that I've described in the comment.

However, if you would additionally create qualifier, like this:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface ProducedCard {}

and add it to the producer method:

@Produces @ProducedCard 
public GreetingCard getGreetingCard() {
...

then you would be able to inject just GreetingCard beans using your producer method like this:

@Inject @ProducedCard
GreetingCard card;

since now there is no ambiguity, as there is only one place to create greeting cards marked with @ProducedCard :-)

Upvotes: 0

Jan Groth
Jan Groth

Reputation: 14636

I am wondering why in getGreedingCard() method, it needs a @Produces annotation at all, since the two classes GreetingCardImpl and AnotherGreetingCardImpl are already imported into the space.

Well, it's not that getGreetingCard needs the @Produces annotation. The point is to enable other classes to recieve GreetingCards via Dependency Injection.

public class Foo {

@Inject // <--- will invoke @Producer method
GreetingCard foosGreetingCard

...

}

See here for more details:

A producer method is a method that acts as a source of bean instances. The method declaration itself describes the bean and the container invokes the method to obtain an instance of the bean when no instance exists in the specified context.

Upvotes: 1

Related Questions