3

I tried to implement solution from another SO question: https://stackoverflow.com/a/10059245/1943765 but it is not working in all cases.

When I put this code in CDI bean (bean code is shown on bottom):

@Inject @HttpParam
private String code; 

everything works fine. But when I try to define value for @HttpParam annotation (so, not default one) Weld is unable to start:

@Inject @HttpParam(value="code")
private String token;

I get this exception:

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type String with qualifiers @HttpParam
  at injection point [BackedAnnotatedField] @Inject @HttpParam private org.test.site.jsf.beans.request.ActivationBean.token
  at org.test.site.jsf.beans.request.ActivationBean.token(ActivationBean.java:0)
WELD-001475: The following beans match by type, but none have matching qualifiers:
  - Producer Method [String] with qualifiers [@HttpParam @Any] declared as [[BackedAnnotatedMethod] @Produces @HttpParam public org.test.site.cdi.producer.HttpParamProducer.getHttpParameter(InjectionPoint)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:359)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281)
    at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:155)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:518)
    at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:68)
    at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:66)
    at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:63)
    at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:56)
    ... 4 more

The code I used is similar to linked SO question.

The custom @HttpParam annotation:

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER})
public @interface HttpParam {
    public String value() default "";
}

The annotation value producer:

public class HttpParamProducer {

    @Inject
    FacesContext facesContext;

    @Produces
    @HttpParam
    String getHttpParameter(InjectionPoint ip) {
        String name = ip.getAnnotated().getAnnotation(HttpParam.class).value();
        if ("".equals(name)) name = ip.getMember().getName();
        return facesContext.getExternalContext()
                .getRequestParameterMap()
                .get(name);
    }
}

And CDI bean using it is something like:

@Named("activation")
@RequestScoped
public class ActivationBean implements Serializable{

    @Inject
    @HttpParam(value="code")
    private String token;

    // rest of valid class code
}

Also I am using Tomcat 8 server with Weld Servlet 2.3.1.Final.

So.. what am I doing wrong? :-/

Community
  • 1
  • 1
Andrija
  • 367
  • 3
  • 14

3 Answers3

3

You need to add @Nonbinding to your value attribute so that its value does not necessarily select which producer method to invoke, but allows for a single factory style producer inspecting your injection point.

You may also want to review what is the purpose of @Nonbinding annotation in a Qualifier supposed to be in Java EE7?

Community
  • 1
  • 1
John Ament
  • 11,595
  • 1
  • 36
  • 45
3

By default , attributes in CDI Qualifier also are used to determine which bean to be injected.

Since you inject @HttpParam(value="code") , but your producer just produces @HttpParam(value=""). They are not matched and CDI don't know what to inject.

To make CDI ignore attributes in CDI Qualifier when determining which bean to be injected, you can mark @Nonbinding on these attributes

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER})
public @interface HttpParam {
    @Nonbinding
    public String value() default "";
}
Tiny
  • 27,221
  • 105
  • 339
  • 599
Ken Chan
  • 84,777
  • 26
  • 143
  • 172
0

I am late to add this, but for the sake of others who may be using this question to write similar parameter based injections, let me add this.

Adding a specific which I did not find above. I faced the same situation, but with a twist in the flavor.My Qualifier and the Producer method were in a module (say injector-module) different from the one in which I was doing the injection (say injected-module). All NonBinding annotations were given.

However, I had the beans.xml only in the injected-module.

The injection failed.

Adding the beans.xml in the META-INF of the injector-module did the trick.

Venkata Rahul S
  • 304
  • 2
  • 10