default method executed instead of implementation

31 views Asked by At

When calling findBySubstring() from ArticleAutocompleteServiceImpl - default method of interface is executed instead of implementation. Is it because of generics? What did I do wrong? How to keep this structure and run implemented method instead of default method? Please can someone help me with this?

EDIT: If I remove default method from FindBySubstringRepositorySupport and leave signature only, it works as expected. Downside is that I have to add dummy implementation method to all services that implements FindBySubstringRepositorySupport and I use this method only on few that have real implementations.

ArticleAutocompleteServiceImpl.java

@Service
public class ArticleAutocompleteServiceImpl implements ArticleAutocompleteService {

    private final ArticleRepository articleRepository;

    public ArticleAutocompleteServiceImpl( final ArticleRepository articleRepository ) {
        this.articleRepository = articleRepository;
    }

    @Override
    public List<ArticleURINameDTO> autocomplete( final String q ) {

        // calling repository method and expecting to run implemented method,
        // not default mehtod of interface
        final List<Article> lst =
            this.articleRepository.findBySubstring( q, 10, ObjectStatus.ENABLED );

        final Locale locale = ...

        return lst.stream().map(a -> new ArticleURINameDTO(a, locale)).toList();
    }



ArticleRepositoryImpl.java

public class ArticleRepositoryImpl implements ArticleExtendRepository {

    @PersistenceContext
    private EntityManager entityManager;

    private final StoredProcService storedProcService;

    public ArticleRepositoryImpl( final StoredProcService storedProcService ) {
        this.storedProcService = storedProcService;
    }

    // implementation that should override default method of interface
    @Override
    public List<Article> findBySubstring(
        final String       namePart,
        final Integer      limit,
        final ObjectStatus objectStatus
    ) {
        return this.storedProcService.execute( ... );
    }


}

ArticleRepository.java

public interface ArticleRepository extends
    PagingAndSortingRepository<Article, Integer>,
    CrudRepository<Article, Integer>,
    ArticleExtendRepository
{

    //

}


ArticleAutocompleteService.java

public interface ArticleAutocompleteService {

    List<ArticleURINameDTO> autocomplete(String q);

}

FindBySubstringRepositorySupport.java

public interface FindBySubstringRepositorySupport<T> {

    // default method to be run if no implementation is present
    default List<T> findBySubstring(
        final String       namePart,
        final Integer      limit,
        final ObjectStatus objectStatus
    ) {
        throw new IllegalStateException( "Method not implemented" );
    }

}

ArticleExtendRepository.java


public interface ArticleExtendRepository extends FindBySubstringRepositorySupport<Article> {

    // some method signature not important here
    long countByStatus( ObjectStatus objectStatus );

}
1

There are 1 answers

1
horvoje On

It was my bad design and lack of knowledge:

Rules for Default Method Conflict Resolution

When a class inherits a method with the same signature from more than one interface, we have the following three rules:

  1. Classes will always win. If a class extends a parent class and implements one or more interfaces, the default method in the class or a superclass will take priority.

  2. Otherwise the subinterfaces will take the next level of precedence. The default method in the most specific default providing interface will be the chosen one. (A subinterface is the one that extends an interface).

  3. If the above rules are not applicable and a choice cannot be made, then the class that inherits from multiple interfaces has to override the method and provide an implementation. But it does not always have to provide the full implementation as there is a way for the class to choose one of the inherited default methods.

Source: https://javadevcentral.com/default-method-resolution-rules#:~:text=If%20a%20class%20extends%20a,will%20be%20the%20chosen%20one.