Search code examples
javagenericscdidecorator

Java CDI: Decorator with multiple generic params


I have the following structure:

@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) { ... }

} 

This is the EntityService interface declaration:

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

}

Unfortunately, the decorator save method never get called when it should, although no errors are shown ... The only way I got it working was like this:

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

Without the Q extends QueryParams generic param.

The MyDecorator is declared inside 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>

Any clues?


Solution

  • Managed to solve the issue. My problem was that I was using QueryParams directly in most of the endpoints/services implementations, for instance:

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

    In fact, QueryParams don't actually extends QueryParams, it is the class itself! That's why the PersonService wasn't triggering MyDecorator at all!

    Being so I created an interface called IQueryParams and used that instead, like that:

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

    Now PersonService save method does trigger the MyDecorator.