Search code examples
javajakarta-eedependency-injectionejbjavabeans

EJB Cannot resolve reference because there are multiple ejbs in the application with the same interface


disclaimer: I am rather new to the whole concept of EJB

I am trying to make a simple enterprise application that makes use of the EJB dependency injection mechanism. The objects that I am trying to inject are of different (non-generic) classes that both implement the same (generic) interface and are also exposed as being of that interface's type to their containing class. The problem is that EJB does not know what class to use to instantiate said objects in their containing class. How would I go about resolving this problem?

(apologies for bad code formatting)

The classes that i'm trying to inject are:

@Stateless
public class HumidityRepository implements ITimeStampedDataRepository<Humidity>, Serializable {

@PersistenceContext(unitName = "WeatherPU")
private EntityManager em;

@Override
public List<Humidity> getAll() {
    Query q = em.createQuery("allHumidity");
    System.out.println(q.getResultList());
    List<Humidity> result = q.getResultList();
    return result;
}

@Override
public List<Humidity> getAllOnDate(LocalDate date) {
    Query q = em.createQuery("onDateHumidity")
            .setParameter("date", date);
    System.out.println(q.getResultList());
    List<Humidity> result = q.getResultList();
    System.out.println(result);
    return result;
}

@Override
public List<Humidity> getAllAfter(LocalDate date, LocalTime time) {
    Query q = em.createQuery("afterHumidity")
            .setParameter("date", date)
            .setParameter("time", time);
    List<Humidity> result = q.getResultList();
    return result;
}

@Override
public void remove(LocalDate date, LocalTime time) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

@Override
public void store(Humidity data) {
    em.persist(data);
}

}

and:

@Stateless
public class TemperatureRepository implements ITimeStampedDataRepository<Temperature>, Serializable {

@PersistenceContext(unitName = "WeatherPU")
private EntityManager em;

@Override
public List<Temperature> getAll() {
    Query q = em.createQuery("allTemperature");
    System.out.println(q.getResultList());
    List<Temperature> result = q.getResultList();
    return result;
}

@Override
public List<Temperature> getAllOnDate(LocalDate date) {
    Query q = em.createQuery("onDateTemperature")
            .setParameter("date", date);
    System.out.println(q.getResultList());
    List<Temperature> result = q.getResultList();
    System.out.println(result);
    return result;
}

@Override
public List<Temperature> getAllAfter(LocalDate date, LocalTime time) {
    Query q = em.createQuery("afterTemperature")
            .setParameter("date", date)
            .setParameter("time", time);
    List<Temperature> result = q.getResultList();
    return result;
}

@Override
public void remove(LocalDate date, LocalTime time) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

@Override
public void store(Temperature data) {
    em.persist(data);
}
}

Their common interface is:

public interface ITimeStampedDataRepository<T extends TimeStampedData> {

    public List<T> getAll();

    public List<T> getAllOnDate(LocalDate date);

    public List<T> getAllAfter(LocalDate date, LocalTime time);

    public void remove(LocalDate date, LocalTime time);

    public void store(T data);

}

Finally, their containing class is:

@Dependent
public class Service implements IService {

    @EJB
    private ITimeStampedDataRepository<Humidity> humidityRepository;
    @EJB
    private ITimeStampedDataRepository<Temperature> temperatureRepository;

    ...

}

Solution

  • You have two options:

    1.Give a name to your EJBs:

    @Stateless(name="BeanNameOne")
    public class TemperatureRepository implements.....
    
    @Stateless(name="BeanNameTwo")
    public class HumidityRepository implements.....
    

    and tell which EJB to inject in the client.

    @EJB(beanName="BeanNameOne")
    private ITimeStampedDataRepository<Temperature> temperatureRepository;
    @EJB(beanName="BeanNameTwo")
    private ITimeStampedDataRepository<Humidity> humidityRepository;
    

    2.refer to the unqualified name

    @EJB(beanName="TemperatureRepository ")
    private ITimeStampedDataRepository<Temperature> temperatureRepository;
    @EJB(beanName="HumidityRepository")
    private ITimeStampedDataRepository<Humidity> humidityRepository;