Dominik Sandjaja
Dominik Sandjaja

Reputation: 6466

CDI @Specializes and Constructor Injection with @Postconstruct

I have the following classes:

@Named
@ViewScoped
public class BaseClass {
    private SomeDependency dep;

    public BaseClass(){}

    @Inject
    public BaseClass(SomeDependency dep) {
        this.dep = dep;
    }

    @PostConstruct
    private void initialize() {
        dep.doSomething(); // Point "A"
    }

    public String getProperty() {
        return "BaseClass-Property";
}

@Specializes
public class SpecialClass extends BaseClass() {

    @Override
    public String getProperty() {
        return "SpecialClass-Property";
    }
}

Now in some .xhtml I have something like

<h:outputText value="#{baseClass.property}" />

This works fine without the SpecialClass. It breaks with a NullPointerException at Point "A" if I include the SpecialClass in the project.

Well, according to the Weld specification, this is more or less intended behavior:

When an enabled bean specializes another bean, the other bean is never instantiated or called by the container.

Nevertheless, now I have to make sure that every @Specializes bean implements the complete constructor like

public SpecialClass() {}

@Inject
public SpecialClass(SomeDependency dep) { super(dep); }

which IMHO is kind of counter-intuitive and produces a lot of duplicated, boilerplate code, especially with something like 5-6 arguments for every constructor. Also, this is never caught when creating a new specialized bean since the project is always still compile clean.

Am I doing something wrong or is there no alternative to implementing the constructors over and over again?

BTW, I do use Constructor Injection to create easily testable classes where I can just use the constructor to "Inject" dummy implementations of the dependencies.

Upvotes: 1

Views: 906

Answers (1)

jpangamarca
jpangamarca

Reputation: 713

CDI 1.1 spec at section 4.3 says:

"The only way one bean can completely override a second bean at all injection points is if it implements all the bean types and declares all the qualifiers of the second bean."

Your base class is annotated with the Named qualifier and the specializing class is not. You should also mark it with Alternative and enable it in beans.xml. There's also the ViewScoped annotation. Unless it's the Omnifaces' ViewScoped, it looks like you're mixing up JSF managed beans with CDI beans.

Upvotes: 1

Related Questions