Добавьте bean-компонент с отслеживанием состояния, используя производителя и полиморфизм с CDI в JEE.

Я действительно новичок в JEE CDI, но половину прошлой ночи пытался найти решение проблемы.

У меня есть класс контроллера, который при вызове запуска должен внедрить bean-компонент с отслеживанием состояния с помощью производителя в зависимости от параметра. Этот упомянутый bean-компонент с состоянием сам содержит внедренный bean-компонент.

Честно говоря, не уверен, что это вообще работает, любой отзыв приветствуется =)

Вот некоторый фиктивный код, который должен помочь понять, что я хочу сделать (на основе https://docs.jboss.org/weld/reference/1.0.0/en-US/html/producermethods.html). Наверное, я сейчас много чего напутал... но я не смог найти пример решения такой проблемы или не смог понять =/

Контроллер (основной сервис)

@Singleton
@Startup
public class Controller
{

    private IEngine engine;

    @PostConstruct
    private void startup(int typeID) 
    {
        Factory f = new Factory();
        engine = f.getEngine(typeID)
    }

 }

Фабрика

public class Factory
{
    @Produces
    public IEngine getEngine(int typeID) 
    {
        if(typeID==1)
        {
          return new EngineA();
        }    
        else
        {
          return new EngineB();
        }

    }

Интерфейс IEngine для полиморфизма

public interface IEngine 
{
    void startUp();
}

Вот пример EngineA, EngineB похож

@Stateful
public class EngineA implements IEngine
{

    @Inject
    private CoinManager cm;

    //@Override
    public void startUp() 
    {
      cm.doSomeThing();
    }
}

К сожалению, это, даже если работает, не позволяет мне использовать @injection в EngineA. На самом деле cm в EngineA равен нулю. Как я могу заставить это работать?

БР и СПАСИБО! Стефан


person user3354754    schedule 15.04.2017    source источник


Ответы (1)


Хорошо, давайте сделаем шаг назад и посмотрим на это. Во-первых, не вызывайте производителей самостоятельно. Позвольте CDI сделать всю работу и просто скажите ему, куда его вводить. Ваш Controller может выглядеть так (но, вероятно, не будет, в вашем сообщении много недоразумений).

@Singleton
@Startup
public class Controller
{
    @Inject // just tell CDI to give you this
    // it won't be this easy here, but it is just to give you an idea
    private IEngine engine;

}

При использовании CDI вы хотите по возможности избегать создания экземпляров через new. Причина в том, что когда вы сами создаете экземпляр, CDI не имеет контроль над созданием и, следовательно, не может ничего в него вводить! Вот откуда ваш null.

Теперь, если у вас есть продюсер...

1) Он должен быть помещен в класс bean (при условии, что это нормально)

2) Любой параметр метода производителя должен быть инжектируемым

3) Производители обычно создают экземпляры через new, поэтому CDI не может ничего внедрить. Если вам это нужно, вы можете рассмотреть другой подход (производители часто используются для превращения объектов, отличных от CDI, в bean-компоненты, поэтому им не нужно инъекции в произведенные бобы).

У вашего производителя есть параметр int typeID, означающий, что CDI даже может вызывать и создавать экземпляры чего-либо с помощью этого метода, он должен иметь эту инъекцию (для int вам понадобится другой производитель, я думаю). Или вы можете поместить логику, извлекающую этот typeID непосредственно внутри метода производителя, вместо того, чтобы передавать его как параметр.

Подводя итог, подход, который вы захотите использовать, зависит от того, как и когда вы извлекаете свой int typeID и может ли он измениться во время выполнения. В любом случае я бы посоветовал вам отказаться от метода производителя и вместо этого взглянуть на Instance<?> в сочетании с @Qualifier. Это должно дать вам достаточную универсальность и динамическое разрешение.

person Siliarus    schedule 18.04.2017