Как @Inject объект с универсальным типом

Я работаю над проектом в нашей компании, и у меня проблема с вводом объекта. Предположим, у меня есть этот поставщик сущностей:

@Stateless
@TransactionManagement 
public class EntityProviderBean<T> extends CachingMutableLocalEntityProvider<T> {

    public EntityProviderBean(Class<T> entityClass) {
        super(entityClass);
        setTransactionsHandledByProvider(false);
    }

    @PersistenceContext(unitName = CoreApplication.PERSISTENCE_UNIT)
    private EntityManager em;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    protected void runInTransaction(Runnable operation) {
        super.runInTransaction(operation);
    }

    @PostConstruct
    public void init() {
        setEntityManager(em);
        setEntitiesDetached(false);
    }
}

и расширенный JPAContainer с использованием поставщика сущностей выше

@UIScoped
public class IncidentContainer extends JPAContainer<Incident> {

    private static final long serialVersionUID = 8360570718602579751L;

    @Inject
    EntityProviderBean<Incident> provider;

    public IncidentContainer() {
        super(Incident.class);
    }

    @PostConstruct
    protected void init() {
        setEntityProvider(provider);
    }

}

Проблема в том (и я это понимаю), что я не могу @Inject объект с определением типа класса, потому что для метода inject нужен пустой конструктор. Есть ли здесь какое-то решение, как заставить его работать? Теперь я получаю исключение

org.apache.webbeans.util.InjectionExceptionUtils.throwUnsatisfiedResolutionException(InjectionExceptionUtils.java:77)

Большое спасибо за ответы :) Ондрей


person s0vet    schedule 15.11.2013    source источник


Ответы (2)


AFAIK Bean нужен конструктор без аргументов, чтобы его можно было вводить, или все параметры конструктора также должны быть введены. Вы не сможете выполнить эти требования.

person raffael    schedule 15.11.2013
comment
Да, я знаю об этом :) Мне было любопытно, есть ли какое-то решение, о котором я не знаю. В противном случае я собираюсь составить список с этими контейнерами, созданными явно. - person s0vet; 15.11.2013
comment
В моем проекте я только что создал класс провайдера для каждого объекта, который я использовал для JPAContainer. - person raffael; 15.11.2013

Инъекция конструктора

Когда контейнер CDI создает экземпляр класса компонента, он вызывает конструктор компонента компонента CDI.

CDI ищет либо конструктор компонента по умолчанию, либо аннотированный с помощью @Inject, чтобы получить экземпляр компонента.

  • Контейнер CDI не примет никакого конструктора bean-компонента с параметрами/по умолчанию, если bean-компонент CDI явно не объявляет конструктор с помощью @Inject.
  • Конструктор компонента CDI может иметь любое количество параметров, и контейнер инициализирует/вводит все те параметры
    , которые являются точкой внедрения для конструктора компонента.
  • Класс bean-компонента CDI может иметь только один конструктор, аннотированный с помощью @Inject. Если контейнер CDI находит несколько конструкторов с аннотацией @Inject, он выдает ошибку.

Есть одно преимущество внедрения конструктора bean-компонента: он позволяет bean-компоненту быть неизменным.

Проблема в вашем случае

Класс компонента IncidentContainer не имеет конструктора по умолчанию или конструктора с аннотацией @Injection.

Вы можете установить следующим образом

public class IncidentContainer extends JPAContainer<Incident> {

    // @Inject no need to do filed injection here
    private EntityProviderBean<Incident> provider;

    @Inject // add this one
    public IncidentContainer(EntityProviderBean<Incident> provider) {
        super(Incident.class);
        this.provider = provider;
    }

    @PostConstruct
    protected void init() {
        setEntityProvider(provider);
    }
}

Класс bean-компонента EntityProviderBean не имеет конструктора по умолчанию или конструктора с аннотацией @Injection.

Вы можете установить следующим образом

public class EntityProviderBean<T> extends CachingMutableLocalEntityProvider<T> {

    public EntityProviderBean(Class<T> entityClass) {
        super(entityClass);
        setTransactionsHandledByProvider(false);
    }
    // add this cdi bean construtor
    @Inject
    public EntityProviderBean(Incident incident) {
        this((Class<T>) incident.getClass());
    }

    protected void runInTransaction(String operation) {
        super.runInTransaction(operation);
    }
}
person Asif Bhutto    schedule 18.11.2013
comment
Эй, спасибо за идею, но я все еще получаю ту же ошибку, когда хочу куда-то @Inject IncidentContainer. - person s0vet; 20.11.2013
comment
Наконец я заставляю его работать. Я могу внедрить IncidentContainer, но когда я хочу сохранить в него какую-то сущность, я получаю javax.persistence.TransactionRequiredException. Это из-за аннотации @TransactionManagement, которая, по-видимому, не работает :( У вас есть идеи? - person s0vet; 21.11.2013