turkraft / springfilter

Dynamically filter JPA entities and Mongo collections with a user-friendly query syntax. Seamless integration with Spring APIs. Star to support the project! ⭐️
https://turkraft.com/springfilter
225 stars 38 forks source link

No primary or default constructor found for interface org.springframework.data.jpa.domain.Specification.How to solve it? #229

Closed VS-88 closed 2 years ago

VS-88 commented 2 years ago

Hi!

I have problem while integrating this library with my project (Spring boot 2.7.2, Spring Data Rest (last stable)). I need to write custom controller for search logic but with all of advantages of the Spring Data Rest library and this library, so I used @RepositoryRestController annotation - and as a result I got error "No primary or default constructor found for interface org.springframework.data.jpa.domain.Specification". Signature of Controller method looks like the example https://github.com/turkraft/spring-filter :

@RequestMapping(method = RequestMethod.GET, value = "/someUrl") public @ResponseBody ResponseEntity search(@Filter Specification specification);

Will be grateful for any idea!

torshid commented 2 years ago

Hi @VS-88 Do you get the same error when using the following?

public @responsebody ResponseEntity search(FilterSpecification<T> specification);
VS-88 commented 2 years ago

Hi @VS-88 Do you get the same error when using the following?

public @responsebody ResponseEntity search(FilterSpecification<T> specification);

Hi!

Thank you for reply!

But the issue is the same: java.lang.IllegalStateException: No primary or single unique constructor found for class com.turkraft.springfilter.boot.FilterSpecification

torshid commented 2 years ago

Hello @VS-88,

I think that this should do the job:

@RepositoryRestResource
public interface MyRepo extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {

  @ResponseBody
  default ResponseEntity<List<T>> search(@Filter Specification<T> specification) {
    return ResponseEntity.ok(findAll(specification));
  }

  @ResponseBody
  default ResponseEntity<T> searchOne(@Filter Specification<T> specification) {
    return ResponseEntity.ok(findOne(specification).orElseThrow(new NotFoundException()));
  }

}

Feel free to reopen the issue if it's not working as expected. Also do note that this is more a Spring related issue, you can always support me to be prioritized over other pending issues.

Thank you.

akbartrinanda commented 1 year ago

Hello @VS-88,

I think that this should do the job:

@RepositoryRestResource
public interface MyRepo extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {

  @ResponseBody
  default ResponseEntity<List<T>> search(@Filter Specification<T> specification) {
    return ResponseEntity.ok(findAll(specification));
  }

  @ResponseBody
  default ResponseEntity<T> searchOne(@Filter Specification<T> specification) {
    return ResponseEntity.ok(findOne(specification).orElseThrow(new NotFoundException()));
  }

}

Feel free to reopen the issue if it's not working as expected. Also do note that this is more a Spring related issue, you can always support me to be prioritized over other pending issues.

Thank you.

Hello @torshid , i want reopen this case, because this way still error.

"detail": "Invoked method public abstract javax.persistence.criteria.Predicate org.springframework.data.jpa.domain.Specification.toPredicate(javax.persistence.criteria.Root,javax.persistence.criteria.CriteriaQuery,javax.persistence.criteria.CriteriaBuilder) is no accessor method!; nested exception is java.lang.IllegalArgumentException: Invoked method public abstract javax.persistence.criteria.Predicate org.springframework.data.jpa.domain.Specification.toPredicate(javax.persistence.criteria.Root,javax.persistence.criteria.CriteriaQuery,javax.persistence.criteria.CriteriaBuilder) is no accessor method!"

torshid commented 1 year ago

Hi @akbartrinanda

Can you share your code?

akbartrinanda commented 1 year ago

Hello @torshid This is my code:

public interface UserRepository extends JpaRepository<User, String>, JpaSpecificationExecutor<User> {

    @ResponseBody
    default ResponseEntity<List<User>> search(@Filter Specification<User> specification) {
        return ResponseEntity.ok(findAll(specification));
    }

    @ResponseBody
    default ResponseEntity<User> searchOne(@Filter Specification<User> specification) {
        return ResponseEntity.ok(findOne(specification).orElse(null));
    }

}
@GetMapping(value = "/search")
public ResponseEntity<List<User>> search(@Filter Specification<User> spec) {
    return userRepository.search(spec);
}

This is the response:

{ "title": "Internal Server Error", "status": 500, "detail": "No primary or single unique constructor found for interface org.springframework.data.jpa.domain.Specification" }

torshid commented 1 year ago

Can you extend SimpleJpaRepository in your repository and check if you still get an error?

akbartrinanda commented 1 year ago

Can you extend SimpleJpaRepository in your repository and check if you still get an error?

Hi @torshid

I have tried it, But the issue is the same:

No primary or single unique constructor found for interface org.springframework.data.jpa.domain.Specification

akbartrinanda commented 1 year ago

Can you extend SimpleJpaRepository in your repository and check if you still get an error?

@torshid hello, can u help me ?

torshid commented 1 year ago

I am not sure why you are getting this error... Can you check the jpa-example project?