I'm trying to apply the constructor injection pattern to beans in my CDI application and am encountering the following error message:
15:18:11,852 ERROR [izone.adams.webapp.error.IzoneExceptionHandler] (default task-40) org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435: Normal scoped bean class webapp.util.LoginManagerAction is not proxyable because it has no no-args constructor - <unknown javax.enterprise.inject.spi.Bean instance>.
at org.jboss.weld.bean.proxy.DefaultProxyInstantiator.validateNoargConstructor(DefaultProxyInstantiator.java:50)
Indeed, in order to use the constructor injection pattern, I have intentionally designed my class with a single constructor requiring arguments:
@ApplicationScoped
@Typed(LoginManagerAction.class)
public class LoginManagerAction extends UtilBasicDispatchAction {
@Inject
public LoginManagerAction( SessionManager sessionManager, JMSHealthCheckService jmsHealthCheckService) {
super();
this.sessionManager = sessionManager;
this.jmsHealthCheckService = jmsHealthCheckService;
}
...
...
}
Looking through the CDI Specs of Unproxyable bean types, I see that:
3.15. Unproxyable bean types
The container uses proxies to provide certain functionality. Certain legal bean types cannot be proxied by the container:
- classes which don’t have a non-private constructor with no parameters,
- classes which are declared final,
- classes which have non-static, final methods with public, protected or default visibility,
- primitive types,
- and array types.
A bean type must be proxyable if an injection point resolves to a bean:
- that requires a client proxy, or
- that has an associated decorator, or
- that has a bound interceptor.
Otherwise, the container automatically detects the problem, and treats it as a deployment problem.
And in further in section Normal scopes and pseudo-scopes it states:
All normal scopes must be explicitly declared @NormalScope, to indicate to the container that a client proxy is required.
Given @ApplicationScoped
beans are by definition @NormalScope
, I need to have a non-private no-args constructor. So then I need to have a protected no-arg constructor just to satisfy the CDI spec? I've tried with a protected no-args constructor, and it seems to work, but I do not understand how WELD is working in that case; in which conditions does it use the no-args constructor? Why is this a requirement in CDI at all?
Does Weld only use the no-arg to create the proxy, but when actually calling the underlying implementation, it uses the inject-based constructor with arguments?