1

I've always needed to get concrete type from generic type at run time for many reasons, but this was not available in java. Until now by using CDI in Java EE, I can inject one generic facade and use all CRUD operations needed for the entity concrete type at run time, with out the need of extension from AbstractFacade as usually in-order to define class type.

Generic Facade:

@Transactional
public class Facade<T> {

    @PersistenceContext(unitName = "PU")
    protected EntityManager em;

    private Class<T> entityClass;

    public Facade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    public Facade() {
    }

    @Inject
    public Facade(InjectionPoint ip) {
        try {
            Type t = ip.getType();
            Field f = t.getClass().getDeclaredField("actualTypeArguments");
            f.setAccessible(true);
            Type[] ts = ((Type[]) f.get(t));
            this.entityClass = (Class<T>) ts[0];
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public T save(T entity) {
        return getEntityManager().merge(entity);
    }

    public void delete(T entity) {
        getEntityManager().remove(getEntityManager().merge(entity));
    }

    public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }


    public List<T> findAll() {
        @SuppressWarnings("rawtypes")
        CriteriaQuery cq = getEntityManager().getCriteriaBuilder()
                .createQuery();
        cq.select(cq.from(entityClass));
        return getEntityManager().createQuery(cq).getResultList();
    }

...  

Then by using @Inject:

@Inject
Facade<Person> personFacade;

@Inject
Facade<OtherType> otherTypeFacade;
...

Every thing worked fine, and concrete type is read at runtime.The question is If there is no need for custom queries or business on specific types,can this solution be an alternative for AbstractFacade which needs to be extended?

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
ali
  • 11
  • 1
  • I frankly don't understand why this is marked as a duplicate of the respective question. It's actually vice versa: Here, the questions is how to avoid using an abstract superclass, while the suggested duplicate answers how to retrieve the class type argument from the superclass. – Alexander Langer Aug 06 '15 at 16:32
  • I cannot answer, so here's my comment: While this is obviously possible (and works as you noticed), I'd rather not suggest this approach but use concrete subclasses for every type (even if these are simply extending an abstract super class). The reason is that you might have to add/change functionality for some specific types, and you'll end up with a maintenance nightmare if you have to change every occurrence of `@Inject Facade ...` later. Better do `@Inject MyChangedTypeFacade` such that you can change the facade logic without touching consumers. – Alexander Langer Aug 06 '15 at 16:38

0 Answers0