1

Using Couchbase Enterprise Edition 5.0.0 build 2873 and Spring Data Couchbase 2.1.2, I am getting the error explained at the bottom of the question. Go forward if you just need the short story.

If you want a little more explanation, here it comes:

Imagine that the CrudRepository methods are fine to me. I mean, I don't need to add any more methods.

How the repository would look like? Would I declare an empty repository just like this?

@Repository
public interface PersonRepository extends CrudRepository<Person, String> {
// Empty
}

Or would I use directly CrudRepositoy as my Base repository. I don't think so, because you need to pass Type and ID to the CrudRepository.

But the question is not that. Here comes the question:

How Spring knows how to instantiate PersonRepository, taking into account that there is no implementation of that base repository? Take a look to PersonService and PersonServiceImpl interface/implementation.

Interface:

@Service
public interface PersonService {
    Person findOne (String id);
    List<Person> findAll();
    //...
}

Implementation:

public class PersonServiceImpl implements PersonService {

    // This is the variable for the repository
    @Autowired
    private PersonRepository personRepository;

    public Person findOne(String id){
        return personRepository(id);
    }

    public List<Person> findAll(){
        List<Hero> personList = new ArrayList<>();

        Iterator<Person> it = personRepository.iterator();

        while (it.hasNext()){
            personList.add(it.next());
        }

        return personList;
    }
//...
}

Is it really enough with declaring an empty PersonRepository extending from CrudRepository? No need to implement and say anything about each method of CrudRepository?. At least something to tell Spring about some constructor...

This doubt are all because I am getting this error when Spring tries to inject the personRepository variable:

Error creating bean with name 'personRepository': Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities).

Apparently, it is asking to have some class defining at least the constructor of the implementation. How do I tell Spring to avoid those type ambiguities mentioned in the error?

ElPiter
  • 4,046
  • 9
  • 51
  • 80
  • are you sure @EntityScan checks all of the classes ? – nabeel Nov 12 '17 at 19:43
  • In this life I am sure of nothing... What make you ask that? You think I am missing to annotate anything? The fact is that my previous error what about not injecting the repo class in the service. But now I got the engine to have it into account and my error is now at time of instantiating it. But if you still think there is something missing, just say it :). Thank you! – ElPiter Nov 12 '17 at 19:48
  • sorry the previous comment might not be relevant, check this example it might help http://www.javainterviewpoint.com/spring-boot-crudrepository-example/ – nabeel Nov 12 '17 at 20:24

1 Answers1

-1

As for the repository you'll need to extend CouchbaseRepository if you're strictly working with Couchbase, by that your repository will expose lower level couchbase objects/functionality.

For example

public interface PersonRepository extends CouchbaseRepository<Person, String> {
}

For your service, you don't need to define findOne() and findAll(), those are strictly the responsibility of the repository.

For example

public interface PersonService {
    void doOperationOnPerson(String personId);
}

@Service
public class PersonServiceImpl implements PersonService {
    @Autowired
    PersonRepository personRepo;

    @Override
    void doOperationOnPerson(String personId) {
    Person person = personRepo.findById(personId);
    //do operation
    }
}

Note that the @Service annotation goes on the implementation. (It actually should work either way but I think having the annotation on the implementation is more proper)

If you need to define custom queries then it should be done inside the repository itself.

You also might need to define an empty constructor on your Person class if you have a non-default constructor.

I suggest you to read more about Spring Data.

prettyvoid
  • 3,446
  • 6
  • 36
  • 60
  • I don't see much difference between what you answered and what I say I am doing. On the other hand, when you say "For your service, you don't need to define findOne() and findAll(), those are strictly the responsibility of the repository.", I know persistence operation must be done from the Repository. But I add those methods to the service layer just to make use of the repository from them. May be I could rename them to getAll and getOne just to difference them from the repository methods. – ElPiter Nov 17 '17 at 08:34
  • Why do you do that if you can autowire the repository anywhere and use it directly? You're just duplicating functionality. – prettyvoid Nov 17 '17 at 10:18
  • Just to commit design patterns paradigms. Service layer is one thing and repository layer is another. In this case, the service layer is "silly"; just a call to the repository one. But for scalability purposes, I always was tought that it is the right way to work. ;) – ElPiter Nov 17 '17 at 11:02