0

I am currently working on an CDI extension. I have to register some special custom beans, thats why a producer is not sufficient.

This is currently done inside the AfterBeanDiscovery-Phase by registering a custom implementation of Bean<> using the abd.addBean() method.

The drawback is that inside the create()-method of the bean I can't access the InjectionPoint, that may contain additional configuration inside an annotation.

As a possibility I could collect all beans I need in the ProcessInjectionTarget phase (as there I have access to the annotations) and register each of them inside the AfterBeanDiscovery phase. Then I would have to make the configuration annotation a qualifier and the attributes of the qualifier binding (not using @Nonbinding) to prevent ambigous dependencies.

But then I will register a huge amount of beans that just are different in their configuration.

Is there an alternate solution? Is it possible to access the InjectionPoint inside the beans create() method?

Thank you!

JDC
  • 4,247
  • 5
  • 31
  • 74
  • You state a producer is not sufficient, yet you don't back that up. Why do you feel that a producer method is not sufficient here, it seems like it would do exactly what you want. – John Ament Jun 25 '15 at 23:58
  • See here: http://stackoverflow.com/questions/31007892/cdi-producers-and-qualifiers-not-on-the-produced-object/31011324#31011324 – JDC Jun 27 '15 at 10:17
  • Ok, so your use case is a bit confusing. Yes, if someone wants to use a custom qualifier its going outside your framework. Typically frameworks will create producers with parameters, typically strings. DeltaSpike has a good example of such an implementation, using JPA mind you but the same idea is used here http://deltaspike.apache.org/documentation/jpa.html#ObtainingEntityManagersfromJPA – John Ament Jun 28 '15 at 00:21
  • So to be a little bit more concrete maybe (didn't want to bother with details): I am currently working on a CDI extension that allows you to inject Jenkins stuff by using e.g. `@JenkinsJob("JobName")`. For that purpose a producer is implemented by the developer that will produce an according JenkinsServer (e.g. ServerDev). Now the developer should be able to annotate the `@JenkinsJob` annotated member with a second annotation (Qualifier) that is used to determine which server to use (as his JenkinsServer-Producer will have the same qualifier). Does this help? – JDC Jun 29 '15 at 07:32
  • Just use @Nonbinding for JenkinsJob.value and provide a CDI-Producer with InjectionPoint as parameter. See e.g. https://github.com/apache/deltaspike/blob/master/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DefaultConfigPropertyProducer.java#L41 – Dar Whi Jul 08 '15 at 01:43

1 Answers1

0

I think I found a solution.

Basically I somehow needed to access the current InjectionPoint inside the beans create() method, that way one can also access the annotations of the injection point.

To get the injection point the following code snipped works (inspired by OmniFaces, using Apache Deltaspike):

public class InjectionPointGenerator {

  @Inject
  private InjectionPoint injectionPoint;

  public InjectionPoint getInjectionPoint() {
    return injectionPoint;
  }
}


public class BeanUtils {

  protected BeanUtils() {
    // Prevent instantiation
  }

  public static InjectionPoint getInjectionPoint(@Nonnull CreationalContext context) {
    Bean<InjectionPointGenerator> bean = getBean(InjectionPointGenerator.class);
    BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
    InjectionPoint injectionPoint = bean.getInjectionPoints().iterator().next();
    return (InjectionPoint) beanManager.getInjectableReference(injectionPoint, context);
  }

  private static <T> Bean<T> getBean(@Nonnull Class<T> type) {
    return BeanProvider.getBeanDefinitions(type, false, true).iterator().next();
  }
}
JDC
  • 4,247
  • 5
  • 31
  • 74