Skip to content

No qualifiers available from InjectionPoint (always EMPTY) #1802

@sarxos

Description

@sarxos

Hi @mkouba,

This is in regards to the problem I described on Zulip. Let me elaborate on this a little more. I have a test bean where I inject qualified injectees:

package org.acme.quickstart2;

import static org.assertj.core.api.Assertions.assertThat;

import javax.inject.Inject;
import javax.inject.Singleton;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;

@Singleton
@QuarkusTest
public class BuuTest {

	@Inject
	@BuuQualifier("foo")
	BuuRef ref1;

	@Inject
	@BuuQualifier("bar")
	BuuRef ref2;

	@Test
	void test_injectQualifiedDependentBeans() {
		assertThat(ref1).isNotNull();
		assertThat(ref2).isNotNull();
		assertThat(ref1).isNotSameAs(ref2);
	}
}

And I have a factory which produces these qualified injectees:

package org.acme.quickstart2;

import java.lang.annotation.Annotation;
import java.util.Set;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Singleton;
import io.quarkus.arc.CurrentInjectionPointProvider;

@Singleton
public class BuuRefFactory {

	@Produces
	@Dependent
	@BuuQualifier
	public BuuRef create(final InjectionPoint injection) {
		final BuuQualifier qualifier = getQualifier(injection);
		final String name = qualifier.value();
		return new BuuRef(name);
	}

	private BuuQualifier getQualifier(final InjectionPoint injection) {
		final Set<Annotation> qualifiers = injection.getQualifiers();
		for (Annotation qualifier : injection.getQualifiers()) {
			if (qualifier instanceof BuuQualifier) {
				return (BuuQualifier) qualifier;
			}
		}
		throw new IllegalStateException("Qualifier not found in a set " + qualifiers);
	}
}

My qualifier is the following and is special in a way that it has a @Nonbinding value definition (not sure if this is important) in order to bind my producer to BuuRef beans, but without exact qualification values matching:

package org.acme.quickstart2;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.enterprise.util.Nonbinding;
import javax.inject.Qualifier;

@Qualifier
@Documented
@Target({ FIELD, METHOD })
@Retention(RUNTIME)
public @interface BuuQualifier {

	@Nonbinding
	String value() default "#UNKNOWN";
}

A BuuRef is a very simple POJO:

package org.acme.quickstart2;

public class BuuRef {

	private final String name;

	public BuuRef(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}
}

The problem lies in the fact that each time new BuuRef is produced by a factory, the InjectionPoint passed down in the argument is always the same instance, an EMPTY object from CurrentInjectionPointProvider.

I see valid InjectionPointImpl being created, but these are never passed down to producer, which receives EMPTY instead.

When you run above test against master 999-SNAPSHOT you should receive exception which indicates that no expected qualifier has been found in a set (which is empty by definition because it's EMPTY object passed down to producer instead of valid InjectionPointImpl):

throw new IllegalStateException("Qualifier not found in a set " + qualifiers);

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions