Issue
I get an error after running spring boot in commandline following this: https://egkatzioura.com/2016/06/03/add-custom-functionality-to-a-spring-data-repository/
My project soruce code is on github: https://github.com/b3nhysteria/exprole_spring
The issue is on application :
System.out.println("============"+customerService.getListTransactionByCustomer());
The implementation in service is
public String getListTransactionByCustomer (){
return customerRepository.getAllTransaction();
}
After adding a custom repo + implementation for method , even after change just to return message, I still got problem.
If anyone have same suggestion, i'll try it
BTW, this script is for exploring / studying.
Solution
In CustomerRepository
you extend TransactionRepoCustom
public interface CustomerRepository extends JpaRepository<Customer, CustomerId>, TransactionRepoCustom {
// ...
}
So, Spring tries to find an implementation of method public String getAllTransaction()
declared in TransactionRepoCustom
(and fails to do so).
To fix this you need to either:
- Implement
getAllTransaction
; maybe create another classTransactionRepoCustomImpl
(recommended!), or - Declare a default implementation for
getAllTransaction
in the interface (if you use Java 8).
Following the first approach it would be something like:
public class TransactionRepoCustomImpl implements TransactionRepoCustom {
@Override
public String getAllTransaction() {
return "logic for your custom implementation here";
}
}
Following the last approach it would be:
public interface TransactionRepoCustom {
public default String getAllTransaction() {
return "Not implemented yet!"; // of course, this is just a naive implementation to state my point
}
}
Additional notes:
This happens becase Spring uses behind scenes default (method) implementations for CustomerRepository
provided by the interfaces it implements
. For example, this is the case with Jparepository
interface: you are able to use customerRepository.findAll()
, and you didn't declare (nor implemented) that method in CustomerRepository
(it was taken from an implementation of Jparepository
, packed for you in a dependency, most probably).
Now, when you create your own interface (TransactionRepoCustom
) and implemented it by CustomerRepository
, Spring tries to find an implementation of all the methods declared in TransactionRepoCustom
. As you didn't provide any, spring fails to create that bean for you.
In this case with the fix I provided Spring finds an implementation of that method, so it can create the bean for you.
Lastly, I said the recommended would be to provide an implementation for that method because the way to do things in Spring is declare the methods in an interface and provide their implementations in other classes (default implementations for that interface). In this case you can create a separate class for that or implement the getAllTransaction
method in CustomerRepository
.
When there is only one method (arguable) it could be fine to declare a default
implementation in the same interface, but if the interface grows then it could be hard to maintain.
Answered By - lealceldeiro
Answer Checked By - Marie Seifert (JavaFixing Admin)