When trying to inject arguments into the constructor of a CDI bean (ApplicationScoped), I\'m encountering the following issue:
Caused by: org.jboss.weld.exceptio
I think Vladimir is pointing you to the right direction.
I'm just learning CDI (and Weld) therefore my answer might not be 100% accurate in all aspects, but it seems like you need to pick a type at injection point that has a no arg constructor.
I hit the same error today with the next type hierarchy:
IServerInterceptor
interface,AuthenticationInterceptor
that has one constructor that takes dependencies (fun fact: this knows nothing about (C)DI),InjectableAuthenticationInterceptor
which has only one injected constructor.I have another bean where I would like to inject an instance of AuthenticationInterceptor
. It works, when I define the field as type IServerInterceptor
(as it is an interface and weld can create a proxy for it(?)), but it stops working when I define the field as AuthenticationInterceptor
.
With some code:
// IServerInterceptor.java
public interface IServerInterceptor {
}
// AuthenticationInterceptor.java
public class AuthenticationInterceptor extends InterceptorAdapter {
private final Predicate<String> validAccessTokenString;
private final Function<String, AccessToken> toAccessTokenModel;
private final LoginManager<AccessToken> loginManager;
public AuthenticationInterceptor(Predicate<String> validAccessTokenString, Function<String, AccessToken> toAccessTokenModel, LoginManager<AccessToken> loginManager) {
this.validAccessTokenString = validAccessTokenString;
this.toAccessTokenModel = toAccessTokenModel;
this.loginManager = loginManager;
}
// ...
}
// InjectableAuthenticationInterceptor.java
@ApplicationScoped
public class InjectableAuthenticationInterceptor extends AuthenticationInterceptor {
@Inject
public InjectableAuthenticationInterceptor(LoginManager<AccessToken> loginManager) {
super(isWelformedAccessToken(), toAccessToken(), loginManager);
}
}
Now,
@Inject private IServerInterceptor authenticationInterceptor;
works great, but
@Inject private AuthenticationInterceptor authenticationInterceptor;
does not.
We resolved similar problem splitting class into interface and implementation. In your case something like this:
public interface Config
{
// API here
}
@ApplicationScoped @Priority(0)
public class ConfigImpl implements Config
{
@Inject
public ConfigImpl(ConfigLocator configLocator) { ... }
// API implementation here
}
Splitting
in interface
and implementation won't solve the problem completely.
The Problem is that the interface
will not be ApplicationScoped
, because an ApplicationScoped
Bean needs a Default "no args" Construcutor
, to be proxyable.
Like this it will always create a new instance of the implementation.
So the implementation behaves like a @Dependent
annotated bean.
If you want to solve it this way, you need to use a method with @PostConstruct
to handle the inject of the argument
and only use a non arg constructor
.
This example might help you :
@ApplicationScoped
public class Config {
private String defaultConfigPath;
@Inject
public Config(ConfigLocator configLocator) {
this.defaultConfigPath = configLocator.getPath();
doStuff();
}
// create a no-args constructor which is required for any scoped bean.
public Config() {
}
}
You need to have a public non-args constructor in the @ApplicationScoped
bean.
Note : The bean for this class will created only once and is maintained for the entire life of an application. This bean will shared among all the managed beans. @ApplicationScoped beans are singleton in nature.
The mentioned issue:
Caused by: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435: Normal scoped bean class xx.Config is not proxyable because it has no no-args constructor - Managed Bean [class xx.Config] with qualifiers [@Default @Named @Any].
The possible reason for this is that a non-dependent scoped bean is required to provide a public no-args constructor for CDI, so that it can pick up the desired proxy bean at runtime.
The non-private, no-arg constructor is needed for the implementation to create a proxy to your managed bean You don't lose the functionality of your injected constructor based on the presence of the non-private, no-arg constructor.
The container uses proxies to allow things like interception, decoration, and to retrieve the right contextual instance when the bean is dereferenced. It's also needed to allow circular injection between beans.