This post is related to an older SO Post of mine, wherein I was trying to understand the requirements of a no-args constructor by WELD.
Right now, I'm trying to figure out if there is a way in CDI to inject an @ApplicationScoped
bean (@Normal) into a @Dependent
scope. From what I've read from WELD, the requirements are to have a non-private no-arg constructor to be proxyable. However, I do not have control over the bean definition as it is provided by a library. My code is doing the following:
@Produces
@ApplicationScoped
@Named("keycloakAdmin")
public Keycloak getKeycloakAdminClient(@Named("keycloakDeployment") final KeycloakDeployment deployment) {
String clientId = deployment.getResourceName();
Map<String, Object> clientCredentials = deployment.getResourceCredentials();
// need to set the resteasy client connection pool size > 0 to ensure thread safety (https://access.redhat.com/solutions/2192911)
ResteasyClient client = new ResteasyClientBuilder().connectionPoolSize(CONNECTION_POOL_SIZE).maxPooledPerRoute(CONNECTION_POOL_SIZE)
.defaultProxy("localhost",8888)
.build();
KeycloakBuilder builder = KeycloakBuilder.builder()
.clientId(clientId)
.clientSecret((String) clientCredentials.get(CredentialRepresentation.SECRET))
.realm(deployment.getRealm())
.serverUrl(deployment.getAuthServerBaseUrl())
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.resteasyClient(client);
return builder.build();
}
// error thrown here that cannot inject @Normal scoped bean as it is not proxyable because it has no no-args constructor
@Produces
@Dependent
@Named("keycloakRealm")
public RealmRepresentation getKeycloakRealm( @Named("keycloakAdmin") final Keycloak adminClient ){
// error thrown here that cannot inject @Normal scoped bean as it is not proxyable because it has no no-arg
return adminClient.realm(resolveKeycloakDeployment().getRealm()).toRepresentation();
}
The problem is that I do not control the Keycloak
bean; it is provided by the library. Consequently, I have no way of providing a no-argument constructor to the bean.
Does this mean it is impossible to do? Are there any workarounds that one can use? This would seem like a significant limitation by WELD, particularly when it comes to @Produce
ing 3rd party beans.
My goal is to have a single Keycloak
bean for the application as it is thread-safe and only needs to be initialized once. However, I want to be able to inject it into non-application-scoped beans.
There is a @Singleton
scope which may address my issue, but if @Singleton
works for this case, what is the purpose of the 2 different scopes? Under what circumstances would one want a non-proxied singleton (@Singleton) vs a proxied one (@ApplicationScoped)? Or is @Singleton
for the entire container, whereas @ApplicationScoped
for the application (WAR) only instead? How does it apply to an EAR or multiple ears?