Canonical _links with Spring HATEOAS

好久不见. 提交于 2019-11-30 21:42:58

There is a discussion somewhere Spring Data Rest team explained why properties are rendered as links that way. Having said you could still achieve what you like by suppressing link generated by SDR and implementing ResourceProcessor. So your Person class would look like below. Note the annotation @RestResource(exported = false) to suppress link

@Entity
public class Person {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  private String firstName;
  private String lastName;

  @ManyToOne
  @RestResource(exported = false)
  private Person father;

  // getters and setters
}

Your ResourceProcessor class would look like

public class EmployeeResourceProcessor implements
        ResourceProcessor<Resource<Person>> {

    @Autowired
    private EntityLinks entityLinks;

    @Override
    public Resource<Person> process(Resource<Person> resource) {
        Person person = resource.getContent();
        if (person.getFather() != null) {
            resource.add(entityLinks.linkForSingleResour(Person.class, person.getFather().getId())
                .withRel("father"));
        }
        return resource;
    }

}

The above solution works only if father value is eagerly fetched along with Person. Otherwise you need to have property fatherId and use it instead of father property. Don't forget to use Jackson @ignore... to hide fatherId in response JSON.

Note: I haven't tested this myself but guessing it would work

Since I had the same problem, I created a Jira issue at spring-data-rest: https://jira.spring.io/browse/DATAREST-682

If enough people vote for it, perhaps we can convince some of the developers to implement it :-).

It's weird that you're pushing to display the canonical link. Once that resource at /father is retrieved the self link should be canonical...but there's really not a good reason to force the father relationship to be canonical...maybe some cacheing scheme?

To your specific question...you're relying on auto-generated controllers so you've given up the right to make decisions about a lot of your links. If you were to have your own PersonController than you would be more in charge of the link structure. If you created your own controller you could then use EntityLinks https://github.com/spring-projects/spring-hateoas#entitylinks with the Father's ID..IE

@Controller
@ExposesResourceFor(Person.class)
@RequestMapping("/people")
class PersonController {

  @RequestMapping
  ResponseEntity people(…) { … }

  @RequestMapping("/{id}")
  ResponseEntity person(@PathVariable("id") … ) {
    PersonResource p = ....
    if(p.father){
      p.addLink(entityLinks.linkToSingleResource(Person.class, orderId).withRel("father");
    }
  }
}

But that seems like a lot of work to just change the URL

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!