Search code examples
javadependency-injectioncdiweld

Passivation of CDI SessionBean with Constructor Injection


I have following CDI Bean:

@SessionScoped
public class ReportService implements Serializable {
    private static final long serialVersionUID = 1L;

    private MyDao myDao;

    @Inject
    public ReportService(MyDao myDao) {
        this.myDao = myDao;
    }
}

@RequestScoped
public class MyDao extends AbstractDao<Order> {

    protected MyDao() {

    }

    @Inject
    public MyDao(EntityManager em) {
        super(em);
    }
}

If i start my webapplication (Tomcat with Weld) the following Exception is thrown:

WELD-001435: Normal scoped bean class com.myorg.ReportService is not proxyable because it has no no-args constructor - Managed Bean [class com.myorg.ReportService] with qualifiers [@Any @Default].

How is it possible to use constructor injection in a SessionScoped Bean? Is it safe just to add a package-visible no-args constructor?

I already searched a lot, but i did not find any information about passivating a CDI Bean whitch uses Constructor Injection.


Solution

  • The error you are getting is based on CDI specification requirements, namely the need to have no-args constructor. When instantiating the object, CDI will of course prioritize a constructor annotated with @Inject, so don't worry about that.

    The real reason why you need no-args one is for proxies. Weld/CDI will try to create one or more proxies of your object, which are basically an enriched delegates. In order to instantiate them, you want to invoke no-arg constructor - think of it as Java limiation, you shouldn't be instantiating objects without calling constructors. Therefore the spec mandates the need for no-arg constructor. As a matter of fact, Weld itself allows you to bypass this need in certain cases, but I strongly suggest against it.

    Is it safe just to add a package-visible no-args constructor?

    Yes, go ahead and do that.