s0vet
s0vet

Reputation: 474

How to @Inject object with generic type

I am working on project in our company and I have a problem with injecting object. Let's consider I have this entity provider :

@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);
    }
}

and extended JPAContainer using the entity provider above

@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);
    }

}

The problem is (and I understand it) that I am not able to @Inject object with class type definition, because inject method needs blank constructor. Is here some kind of solution how to make it works ? Now I am getting exception

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

Many thanks for the answers :) Ondrej

Upvotes: 2

Views: 2339

Answers (2)

Asif Bhutto
Asif Bhutto

Reputation: 3994

Consrtutor Injection

When CDI container instantiate a bean class then it call the bean constructor of CDI bean.

CDI looks for the either default bean constructor or annotated with @Inject to get the the instance of bean.

  • No parameter/default bean constructor will accepted by CDI container if CDI bean doesn't explicitly declare a constructor using @Inject.
  • CDI bean constructor may have any number of parameters and container initialize/inject all those
    paramters which are injection point for the bean constructor.
  • CDI bean class can only have single constructor annotated with @Inject. If CDI container finds multiple constructor annotated with @Inject then it throws error.

There is one advantage of bean constructor injection it allows the bean to be immutable.

The Problem in your case is

IncidentContainer bean class does not have any default constructor or a constructor annotated with @Injection.

You can set as following

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);
    }
}

EntityProviderBean bean class does not have any default constructor or a constructor annotated with @Injection.

You can set as following

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);
    }
}

Upvotes: 0

raffael
raffael

Reputation: 2456

AFAIK the Bean needs a constructor with no arguments to be injectable or all the constructor parameters must be injected as well. You will not be able to fulfil these requirements.

Upvotes: 1

Related Questions