After two days, I have solved in this way.
Custom Repository Interface:
public interface PersonRepositoryCustom {
Page<Person> customFind(String param1, String param2, Pageable pageable);
}
Custom Repository Implementation
public class PersonRepositoryImpl implements PersonRepositoryCustom{
@Override
public Page<Person> customFind(String param1, String param2, Pageable pageable) {
// custom query by mongo template, entity manager...
}
}
Spring Data Repository:
@RepositoryRestResource(collectionResourceRel = "person", path = "person")
public interface PersonRepository extends MongoRepository<Person, String>, PersonRepositoryCustom {
Page<Person> findByName(@Param("name") String name, Pageable pageable);
}
Bean Resource representation
public class PersonResource extends org.springframework.hateoas.Resource<Person>{
public PersonResource(Person content, Iterable<Link> links) {
super(content, links);
}
}
Resource Assembler
@Component
public class PersonResourceAssembler extends ResourceAssemblerSupport<Person, PersonResource> {
@Autowired
RepositoryEntityLinks repositoryEntityLinks;
public PersonResourceAssembler() {
super(PersonCustomSearchController.class, PersonResource.class);
}
@Override
public PersonResource toResource(Person person) {
Link personLink = repositoryEntityLinks.linkToSingleResource(Person.class, person.getId());
Link selfLink = new Link(personLink.getHref(), Link.REL_SELF);
return new PersonResource(person, Arrays.asList(selfLink, personLink));
}
}
Custom Spring MVC Controller
@BasePathAwareController
@RequestMapping("person/search")
public class PersonCustomSearchController implements ResourceProcessor<RepositorySearchesResource> {
@Autowired
PersonRepository personRepository;
@Autowired
PersonResourceAssembler personResourceAssembler;
@Autowired
private PagedResourcesAssembler<Person> pagedResourcesAssembler;
@RequestMapping(value="customFind", method=RequestMethod.GET)
public ResponseEntity<PagedResources> customFind(@RequestParam String param1, @RequestParam String param2, @PageableDefault Pageable pageable) {
Page personPage = personRepository.customFind(param1, param2, pageable);
PagedResources adminPagedResources = pagedResourcesAssembler.toResource(personPage, personResourceAssembler);
if (personPage.getContent()==null || personPage.getContent().isEmpty()){
EmbeddedWrappers wrappers = new EmbeddedWrappers(false);
EmbeddedWrapper wrapper = wrappers.emptyCollectionOf(Person.class);
List<EmbeddedWrapper> embedded = Collections.singletonList(wrapper);
adminPagedResources = new PagedResources(embedded, adminPagedResources.getMetadata(), adminPagedResources.getLinks());
}
return new ResponseEntity<PagedResources>(adminPagedResources, HttpStatus.OK);
}
@Override
public RepositorySearchesResource process(RepositorySearchesResource repositorySearchesResource) {
final String search = repositorySearchesResource.getId().getHref();
final Link customLink = new Link(search + "/customFind{?param1,param2,page,size,sort}").withRel("customFind");
repositorySearchesResource.add(customLink);
return repositorySearchesResource;
}
}
search
– Neckwearhttp://localhost:8080/people/search/findByFirstName{?name}
that exposes my custom implementation ofPersonRepository.findByFirstName(name)
– CartiePersonRepository
has nofindByFirstName
method. I guess you want it to extend thePersonRepositoryCustom
interface. – PakistanPersonRepositoryCustom
is not a repository, but as spring looks for implementations ofPersonRepository
(that have Impl as suffix) before implementing it itself I thought it could exposes the other method.findByFirstName(name)
which is not true as provided in the answer below. – Cartie