user3235738
user3235738

Reputation: 425

Spring Data Rest - Custom LinkRelationProvider is never used

I am creating a service based on spring-boot-starter-parent 2.6.1 and use spring data rest to expose my JPA repository:

public interface PointRepo extends CrudRepository<Point<?>, String> {}

The Point type has subtypes Quantity and Switch, so a GET /points currently returns something like:

{
  "_embedded" : {
    "switches" : [ {
      ...
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/switch/office_light"
        },
        ...
      }
    }],
    "quantities" : [ {
      ...
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/quantity/office_temp"
        },
        ...
      }
    }

Since I am not planning to expose endpoints /switches and /quantities, I want all Points to be in _embedded.points and the self hrefs to point to /points, too. I figured, I need a custom LinkRelationProvider so I created this:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class PointRelProvider extends EvoInflectorLinkRelationProvider {
    
    @Override
    public LinkRelation getCollectionResourceRelFor(final Class<?> type) {
        return super.getCollectionResourceRelFor(Point.class);
    }

    @Override
    public LinkRelation getItemResourceRelFor(Class<?> type) {
        return super.getItemResourceRelFor(Point.class);
    }

    @Override
    public boolean supports(LookupContext delimiter) {
        return Point.class.isAssignableFrom(delimiter.getType());
    }

}

I found out the bean gets created, but it has no effect on the output whatsoever. I put breakpoints into each method put none of them ever gets called. Any ideas why that might be the case?

Upvotes: 1

Views: 222

Answers (1)

flaviut
flaviut

Reputation: 2143

The following seems to work for me, at least to the point where my breakpoints are getting hit:

@Configuration
public class RestConfiguration extends RepositoryRestConfigurerAdapter {

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
         config.setLinkRelationProvider(new DelegatingLinkRelationProvider(
            new PointRelProvider(),
            // the default Spring Data REST link relation provider as a fallback
            new AnnotationLinkRelationProvider(),
            new EvoInflectorLinkRelationProvider()
        ));
    }
}

With this, no need to also extend EvoInflectorLinkRelationProvider in PointRelProvider. You can instead just implement LinkRelationProvider.

The @Order(Ordered.HIGHEST_PRECEDENCE) annotation on PointRelProvider is still needed, since DelegatingLinkRelationProvider uses these annotations (through PluginRegistryOrderAwarePluginRegistry.DEFAULT_COMPARATORAnnotationAwareOrderComparator) to determine the order in which to sort the providers.

Upvotes: 0

Related Questions