Reputation: 707
I've defined a qualifier to specify what bean subclass I want injected. When the qualifier has no parameters specified at the injection point, everything works as expected. When I specify an attribute and value at the injection point, I get a CDI unsatisfied dependency error. I'm deploying on Glassfish 4.0. Also, using no-interface view on the injected beans, but I didn't think that mattered in this situation.
The purpose of the qualifier is to get a Postgres-specific subclass (a variety of different db's are being used, to compare any behavioral differences). The parameter is to specify the Postgres schema (which defaults to "public").
The qualifier is defined like this in Postgres.java
:
@Qualifier
@Retention(RUNTIME)
@Target({ FIELD, TYPE, METHOD })
public @interface Postgres
{
String schema() default "public";
}
The injected subclass looks like this in DBCmdPostgres.java
:
@Stateless
@Postgres
public class DBCmdPostgres
extends DBCmd
{
...
@PostConstruct
public void postConstruct()
{
Class cl = getClass();
Postgres postgresAnnotation = (Postgres)cl.getAnnotation(Postgres.class);
if (postgresAnnotation != null) {
System.out.println(">> @Postgres(schema = " + postgresAnnotation.schema() +")");
}
}
...
}
The base class looks like this in DBCmd.java
:
@Stateless
@Default
abstract public class DBCmd
{
...
}
And the injection point is this in a JSF session-scoped backing bean indexBacker.java
:
@Inject @Postgres(schema = "foo") private DBCmd postgresCmds;
If I leave out the (schema = "foo")
at the injection point, things work as I'd expect, and the PostConstruct method displays the proper default of "public". If I add the (schema = "foo")
part, I get the following error on deployment to Glassfish:
[2013-09-18T08:36:24.209-0500] [glassfish 4.0] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=36 _ThreadName=admin-listener(3)] [timeMillis: 1379511384209] [levelValue: 1000] [[
Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [DBCmd] with qualifiers [@Postgres] at injection point [[BackedAnnotatedField] @Inject @Postgres private jsfBackers.IndexBacker.postgresCmds]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [DBCmd] with qualifiers [@Postgres] at injection point [[BackedAnnotatedField] @Inject @Postgres private jsfBackers.IndexBacker.postgresCmds]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:325)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:177)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:208)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:519)
at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:505)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:480)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:536)
at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:216)
at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:131)
at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:328)
...
The beans are currently @Stateless
, but will become @Stateful
(to store/use the value of the schema
parameter, as well as some other stuff) if we can figure out what's wrong.
Upvotes: 1
Views: 3197
Reputation: 11723
Your parameter should be marked as @Nonbinding
in order to properly resolve like this.
To read the value:
where ip is your InjectionPoint
object, annotationClass
is the class you want to read (T is the type of it)
final Set<Annotation> annotations = ip.getQualifiers();
for (final Annotation a : annotations) {
try {
if (a.annotationType().isAssignableFrom(annotationClass)) {
t = (T) a;
break;
}
}
catch (final ClassCastException e) {
}
}`
Upvotes: 1