CraftWeaver
CraftWeaver

Reputation: 707

Why CDI unsatisfied dependency when using annotation parameter?

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

Answers (1)

John Ament
John Ament

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

Related Questions