2016-05-17 18 views
2

Я пытаюсь определить пользовательский конфигуратор DeltaSpike ConfigSource. Пользовательский источник конфигурации будет иметь наивысший приоритет и проверить базу данных для параметра конфигурации.Конфигурация ConfigSource DeltaSpike с CDI

У меня есть объект ConfigParameter, который просто имеет ключ и значение.

@Entity 
@Cacheable 
public class ConfigParameter ... { 

     private String key; 
     private String value; 

} 

У меня есть @Dependent DAO, который находит все параметры конфигурации.

То, что я пытаюсь сделать сейчас, определяет настраиваемый ConfigSource, который может получить параметр конфигурации из базы данных. Поэтому я хочу ввести свой DAO в ConfigSource. Так что в основном что-то вроде

@ApplicationScoped 
public class DatabaseConfigSource implements ConfigSource { 

    @Inject 
    private ConfigParameterDao configParameterDao; 

    .... 
} 

Однако при регистрации ConfigSource через META-INF/услуги/org.apache.deltaspike.core.spi.config.ConfigSource, класс будет инстанцирован и CDI не будет работать ,

Есть ли способ получить работу CDI в этом случае?

Заранее спасибо, если вам нужна дополнительная информация, пожалуйста, дайте мне знать.

ответ

0

Основная проблема заключается в том, что ConfigSource получает экземпляр очень рано, когда BeanManager недоступен. Даже поиск JNDI не работает в этот момент времени. Таким образом, мне нужно отложить инъекцию/поиск.

Что я сделал сейчас, добавляет статический логический элемент в мой конфигурационный источник, который я устанавливаю вручную. У нас есть InitializerService, который гарантирует правильную настройку системы. В конце процесса инициализации я вызываю allowInitialization(), чтобы сообщить источнику конфигурации, что данный компонент теперь можно вводить. В следующий раз, когда спросит ConfigSource, он сможет ввести компонент, используя BeanProvider.injectFields.

public class DatabaseConfigSource implements ConfigSource { 

    private static boolean allowInit; 

    @Inject 
    private ConfigParameterProvider configParameterProvider; 

    @Override 
    public int getOrdinal() { 
     return 500; 
    } 

    @Override 
    public String getPropertyValue(String key) { 
     initIfNecessary(); 

     if (configParameterProvider == null) { 
      return null; 
     } 

     return configParameterProvider.getProperty(key); 
    } 

    public static void allowInitialization() { 
     allowInit = true; 
    } 

    private void initIfNecessary() { 
     if (allowInit) { 
      BeanProvider.injectFields(this); 
     } 
    } 

} 

У меня есть фасоль с запросом, содержащая все мои переменные конфигурации для безопасного доступа типа.

@RequestScoped 
public class Configuration { 

    @Inject 
    @ConfigProperty(name = "myProperty") 
    private String myProperty; 

    @Inject 
    @ConfigProperty(name = "myProperty2") 
    private String myProperty2; 

    .... 

} 

При вводе класса конфигурации в другом компоненте каждый ConfigProperty будет разрешен. Поскольку мой пользовательский DatabaseConfigSource имеет самый высокий порядковый номер (500), он сначала будет использоваться для разрешения свойств. Если свойство не найдено, оно делегирует разрешение следующему ConfigSource.

Для каждого ConfigProperty вызывается функция getPropertyValue из DatabaseConfigSource. Поскольку я не хочу возвращать параметры из базы данных для каждого свойства конфигурации, я переместил разрешение конфигурации конфигурации в bean-область с запросом.

@RequestScoped 
public class ConfigParameterProvider { 

    @Inject 
    private ConfigParameterDao configParameterDao; 

    private Map<String, String> configParameters = new HashMap<>(); 

    @PostConstruct 
    public void init() { 
     List<ConfigParameter> configParams = configParameterDao.findAll(); 
     configParameters = configParams.stream() 
      .collect(toMap(ConfigParameter::getId, ConfigParameter::getValue)); 
    } 

    public String getProperty(String key) { 
     return configParameters.get(key); 
    } 

} 

Я мог бы с уверенностью изменить приложение ConfigParameterProvider с областью действия запроса на ApplicationScoped. Тем не менее, у нас есть настройка нескольких арендаторов, и параметры должны быть разрешены для каждого запроса.

Как вы можете видеть, это немного хакерство, потому что нам нужно явно указать ConfigSource, когда ему разрешено правильно создавать экземпляры (вставлять компонент).

Я бы предпочел стандартизованный решение от DeltaSpike для использования CDI в ConfigSource. Если у вас есть идея о том, как правильно это понять, сообщите мне.

+0

Вы все же можете улучшить 'initIfNecessary()' - на данный момент это работает скорее как 'initIfPossible()', т.е. поля не получают слишком скоро, но они вводятся при каждом вызове 'getPropertyValue()' , –

+0

Отступ 1.8 будет фиксировать это. –

0

DS использует java se spi механизм для этого, который не является CD'Injectable '. Одним из решений было бы использовать BeanProvider, чтобы получить доступ к вашему DatabaseConfigSource и делегировать ему операции.

+0

ConfigSources инициализируется до инициализации beanprovider. Таким образом, при попытке использовать Beanprovider в ConfigSource генерируется исключение, что провайдера нет. – kevcodez

+0

Хорошо, но если вы получаете доступ к BeanProvider в методах getPropery/getProperties, не так ли? Являются ли эти 2 свойства вызваны init? – Franck

+0

Функция 'getProperty' вызывается на разных этапах запуска приложения/контейнера. Сначала DS пытается получить несколько внутренних свойств, прежде чем пытаться разрешить мои собственные свойства конфигурации. Во время первого «прогона» BeanProvider недоступен. Функция 'getProperties' вообще не вызывается. Мне нужен ConfigSource или что-то подобное, которое будет инициализировано, когда CDI-компоненты будут инициализированы. – kevcodez

 Смежные вопросы

  • Нет связанных вопросов^_^