Java CDI: Декоратор с несколькими родовыми параметрами

У меня есть следующая структура:

@Decorator
public abstract class MyDecorator<T extends BaseEntity, Q extends QueryParams> implements EntityService<T, Q> {

    @Any
    @Inject
    @Delegate
    EntityService<T, Q> delegate;

    @Override
    public T save(T entity) { ... }

} 

Это объявление интерфейса EntityService:

public interface EntityService<T extends BaseEntity, Q extends QueryParams> {

    T save(T entity);

    void deleteById(Integer id);

    void deleteAllById(List<Integer> ids);

    void delete(T entity);

    void deleteAll(List<T> entities);

    T findById(Integer id);

    QueryResultWrapper<T> query(Q parameters);

    Long count(Q parameters);

}

К сожалению, метод сохранения декоратора никогда не вызывается, когда он должен, хотя никаких ошибок не видно... Единственный способ, которым я работал, был следующим:

@Decorator
public abstract class MyDecorator<T extends BaseEntity> implements EntityService<T> { ... }

Без Q extends QueryParams общего параметра.

MyDecorator объявляется внутри beans.xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
   bean-discovery-mode="all" version="1.1">

    <decorators>
        <class>fortuna.backend.comum.decorators.MyDecorator</class>
    </decorators>

</beans>

Любые подсказки?

Ответы

Ответ 1

Удалось решить проблему. Моя проблема заключалась в том, что я использовал QueryParams непосредственно в большинстве реализаций конечных точек/сервисов, например:

public class PersonService extends EntityService<Person, QueryParams> { ... }

Фактически, QueryParams на самом деле не extends QueryParams, это сам класс! Поэтому PersonService не запускал MyDecorator вообще!

Итак, я создал интерфейс под названием IQueryParams и использовал это вместо этого:

public abstract class MyDecorator<T extends BaseEntity, Q extends IQueryParams> implements EntityService<T, Q> {

Теперь метод сохранения PersonService запускает MyDecorator.

Ответ 2

Вы делаете это →

EntityService<T extends BaseEntity, Q extends QueryParams>

Если этот интерфейс принимает два объекта, один T расширяет BaseEntity, другой Q расширяет QueryParams, соответственно, вы можете попробовать напрямую разместить определенные типы вместо. Точно так же:

К интерфейсу (Здесь наиболее важно, чтобы оно было таким общим, как возможно, поэтому вы выбираете два имени, например A, B или в вашем случае):

public interface EntityService<T, Q> {

T Save(T param);

void otherMethod(Q param);

}

Для декоратора (здесь, в этот момент, вы можете выбрать типы, поэтому не обязательно быть "общим" ):

public abstract class MyDecorator implements EntityService<BaseEntity, QueryParams>{

@Any
@Inject
@Delegate
EntityService<BaseEntity, QueryParams> delegate;
//If I understood well the problem, this just work and solve your problem, 
//or else... I'm sorry, you can give me more data so I could help you
//a little more

//Check here, I give a concrete type for T abstract generic type, in 
//your case BaseEntity
@Override
public BaseEntity save(BaseEntity entity) { 
    BaseEntity retSomething; //this is ilustrative
    super.save(entity);  //save your entity as you know how.
    return retSomething; //I really don't know why your save method has a 
                         //return statament, but, if you need it, check the 
                         //return type
}

@Override
public void otherMethod(QueryParams param) {
    // Check here, in the interface the name was Q, now here you only
    // can use as param an QueryParams type object

}

}