Search code examples
javaspringreflectiondependency-injectioncdi

Equivalent of @Configurable for CDI JavaEE 7


Currently I have a big problem with CDI, when I would like to create a new object by their annotaitons.

With reflections I got all classes taged with '@Connector'. After that I create for each class a new object. This works fine, but I would like to inject a ServiceHandler into the objects which try to inject it via '@Inject'. The Problem here is that CDI doesn't know these objects and will not be able to inject them. Currently I have a workaround to solve this problem, but this is not really pretty. I'm new to CDI and I'm looking for an equivalent of Spring's '@Configurable' annotation.

private Set<ApiDao> determineApiDaos() {
Set<Class<?>> classes = new Reflections("###packageName###").getTypesAnnotatedWith(Connector.class);
return FluentIterable.from(classes)
    .transform(CLASS_TO_API_DAO_FUNCTION)
    .filter(Predicates.notNull())
    .toSet(); 
}

private ApiDao instantiateApiDao(Class apiDao) {
try {
  ApiDao newApiDao = (ApiDao) apiDao.newInstance();
  newApiDao.setConfigurationService(configurationService); // Workaround inject service during creation
  return newApiDao;
} catch (Exception e) {
  LOG.error("Could not initialize Connector.", e);
  return null;
  }
}

Solution

  • Your question is very broad. So will be my answer.

    First, do not try to imitate Spring when working with Java EE. It is useful to read to CDI specifications.

    If I understand your problem correctly, you have a class unknown to CDI, yet you want CDI to Inject it. This is easily solveable in CDI. In fact, much more easily than with Spring. Use producers.

    public class ConfigurationServiceProducer{
    
     @Produces
     public ConfigurationService produceConfigurationService(){
      //Instantiate and return the ConfigurationService accordingly.
      return new ConfigurationService();
     }
    }
    

    You can also use Qualifiers to differentiate beans types as ConfigurationService, if required. If you need to inspect the injection point more deeply directly in the producer method, you can pass InjectionPoint as an argument to the producer method.