Spring Data Rest - Add link to search endpoint
Asked Answered
M

2

7

In our Spring-Data-Rest Project we have a custom (fuzzy) search on a /buergers/search/findBuergerFuzzy?searchString="..." endpoint.

Is it possible to add a link for it on the /buergers/search endpoint (Without overriding the automatically exposed Repository findBy Methods)?

The Controller exposing the search:

@BasePathAwareController
@RequestMapping("/buergers/search/")
public class BuergerSearchController {

    @Autowired
    QueryService service;

    @RequestMapping(value = "/findBuergerFuzzy", method = RequestMethod.GET)
    public
    @ResponseBody
    ResponseEntity<?> findBuergerFuzzy(PersistentEntityResourceAssembler assembler, @Param("searchString") String searchString) {
        if (searchString.length() < 3)
            throw new IllegalArgumentException("Search String must be at least 3 chars long.");
        List<Buerger> list = service.query(searchString, Buerger.class, new String[]{"vorname", "nachname", "geburtsdatum", "augenfarbe"});
        final List<PersistentEntityResource> collect = list.stream().map(assembler::toResource).collect(Collectors.toList());
        return new ResponseEntity<Object>(new Resources<>(collect), HttpStatus.OK);
    }
}
Mirza answered 25/9, 2015 at 9:17 Comment(0)
A
2

Version

migrate-to-1.0.changes

ResourceSupport is now RepresentationModel

Resource is now EntityModel

Resources is now CollectionModel

PagedResources is now PagedModel

Code

The code for new version:

import org.springframework.data.rest.webmvc.RepositorySearchesResource;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.server.RepresentationModelProcessor;
import org.springframework.stereotype.Component;

@Component
public class RepositorySearchesProcessor implements RepresentationModelProcessor<RepositorySearchesResource> {

    @Override
    public RepositorySearchesResource process(RepositorySearchesResource model) {
        System.out.println(model.getDomainType());
        model.add(Link.of(model.getRequiredLink("self").getHref() + "/findFullTextFuzzy{?q}").withRel("findFullTextFuzzy"));
        return model;
    }
}

How

About how to find what resource or model you use, after setting breakpoints in each method of RepresentationModel, you maybe find something useful :

enter image description here

Airstrip answered 8/4, 2021 at 2:58 Comment(0)
M
7

UPDATE: This is an outdated workaround answer. Upgrade to Spring HATEOAS 1.0.


Old Workaround:

Digging the spring-data-rest source i found the RepositorySearchesResource which seems to solve the problem.

@Component
public class SearchResourcesProcessor implements ResourceProcessor<RepositorySearchesResource> {

    @Override
    public RepositorySearchesResource process(RepositorySearchesResource repositorySearchesResource) {
        final String search = repositorySearchesResource.getId().getHref();
        final Link findFullTextFuzzy = new Link(search + "/findFullTextFuzzy{?q}").withRel("findFullTextFuzzy");
        repositorySearchesResource.add(findFullTextFuzzy);

        return repositorySearchesResource;
    }
}

Because we generate this code by templates, this is sufficient and fullfills our needs. Make sure to check the comments for the right and safe way.

Mirza answered 26/9, 2015 at 11:52 Comment(3)
You should check resource.getDomainType() to make sure your search function only displays at the right resource. if(ResourceClass.class.equals(resource.getDomainType()))Longoria
Your solution is quite dangerous, because you are losing consistency between the mapping of your method (where is it served) and the linking of it (where following the relation will lead). You should use linkTo and methodOn static methods from Spring Hateoas to avoid that when creating you LinkPermeability
The answer is too old nowAirstrip
A
2

Version

migrate-to-1.0.changes

ResourceSupport is now RepresentationModel

Resource is now EntityModel

Resources is now CollectionModel

PagedResources is now PagedModel

Code

The code for new version:

import org.springframework.data.rest.webmvc.RepositorySearchesResource;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.server.RepresentationModelProcessor;
import org.springframework.stereotype.Component;

@Component
public class RepositorySearchesProcessor implements RepresentationModelProcessor<RepositorySearchesResource> {

    @Override
    public RepositorySearchesResource process(RepositorySearchesResource model) {
        System.out.println(model.getDomainType());
        model.add(Link.of(model.getRequiredLink("self").getHref() + "/findFullTextFuzzy{?q}").withRel("findFullTextFuzzy"));
        return model;
    }
}

How

About how to find what resource or model you use, after setting breakpoints in each method of RepresentationModel, you maybe find something useful :

enter image description here

Airstrip answered 8/4, 2021 at 2:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.