Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Exposing and Managing Links with Spring HATEOAS

DZone's Guide to

Exposing and Managing Links with Spring HATEOAS

· Java Zone
Free Resource

Microservices! They are everywhere, or at least, the term is. When should you use a microservice architecture? What factors should be considered when making that decision? Do the benefits outweigh the costs? Why is everyone so excited about them, anyway?  Brought to you in partnership with IBM.

As a follow up to the previous Spring HATEOAS post, this post will cover how to use the @ExposesResourceFor annotation as an alternative to using the resource's Controller to obtain links.

It'll also cover how to find links based on a particular relation type in a hypermedia enabled representation.

In addition to the classes in the previous post, the SettlementController class is responsible for settling bets and exposes one method, settleBet, in order to do this. To return a link to the settled bet, the SettlementController uses the linkTo method on the ControllerLinkBuilder class:

@RequestMapping(method = RequestMethod.PUT, value = "/{betId}")
ResponseEntity<SettlementResource> settleBet(@PathVariable Long betId) {
 
    Settlement settlement = this.settlementService.settleBet(betId); 
    SettlementResource resource =
        settlementResourceAssembler.toResource(settlement);
    <b>resource.add(
        linkTo(BetController.class).slash(betId).withSelfRel());</b>
    return new ResponseEntity<SettlementResource>(resource, HttpStatus.CREATED);
}  

An alternative approach to this is to enable EntityLinks. By adding the @ExposesResourcesFor annotation to the BetController, the SettlementController need only know about the resource and not it's Controller class.

@Controller
<b>@ExposesResourceFor(Bet.class)</b>
@RequestMapping("/bets")
public class BetController {
...
}

The SettlementController by way of the EntityLinks interface can now obtain the link to a single resource or a link to a resource collection. It can either get the Link or a LinkBuilder. With the latter approach, the relation types can be overwritten:

@Controller
@RequestMapping("/settlements")
public class SettlementController {
 
    private SettlementService settlementService;
    private SettlementResourceAssembler settlementResourceAssembler;
    <b>private EntityLinks entityLinks;</b>
 
    @Autowired
    public SettlementController(SettlementService settlementService,
        SettlementResourceAssembler settlementResourceAssembler, EntityLinks entityLinks) {
        this.settlementService = settlementService;
        this.settlementResourceAssembler = settlementResourceAssembler;
        this.entityLinks = entityLinks;
    }
 
    @RequestMapping(method = RequestMethod.PUT, value = "/{betId}")
    ResponseEntity<SettlementResource> settleBet(@PathVariable Long betId) {
 
        Settlement settlement = this.settlementService.settleBet(betId);
        SettlementResource resource =
            settlementResourceAssembler.toResource(settlement);
        <b>resource.add(this.entityLinks.linkToSingleResource(Bet.class, betId));</b>
        return new ResponseEntity<SettlementResource>(
            resource, HttpStatus.CREATED);
    }
  
}

For a collection link, the call would be:

resource.add(this.entityLinks.linkToCollectionResource(Bet.class));

To obtain the builders:

LinkBuilder linkFor = this.entityLinks.linkFor(Bet.class);
LinkBuilder linkForSingleResource =
    this.entityLinks.linkForSingleResource(Bet.class, betId);

To enable all this functionality, the @EnableEntityLinks annotation must be in your Spring configuration.

Another useful feature that comes with Spring HATEOAS, is the ability to discover links. For a given hypermedia enabled representation, the Link Discoverer API can find a link or links for a particular relation type. For example, from the previous post, to find the cancelBet relation type link of a ResourceSupport object would be:

LinkDiscoverer discoverer = new DefaultLinkDiscoverer();
Link link = discoverer.findLinkWithRel("cancelBet", resource.toString());

The DefaultLinkDiscoverer will expect JSON but since 0.5 of Spring HATEOAS, the HAL variant has been supported via the HalLinkDiscoverer class.

Although still evolving, the Spring HATEOAS project provides a good foundation for implementing a HATEOAS compliant REST service. But if all you require is to expose and manage domain objects via a REST web service then the Spring Data REST project which applies the HATEOAS constraint to persisted entities is worth considering and the Restbucks example an ideal tutorial.

Discover how the Watson team is further developing SDKs in Java, Node.js, Python, iOS, and Android to access these services and make programming easy. Brought to you in partnership with IBM.

Topics:

Published at DZone with permission of Geraint Jones, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}