Accessing Hypermedia REST services

HTTP web services that apply REST constraints, especially in regard to Hypermedia, need more sophisticated logic on the client side. Services direct clients to corresponding resources that need to be accessed in certain ways. Hypermedia decouples services and enables API features such as evolvability and discovery, but also require more dynamic and logic on the client side.

The Siren content type example earlier gives an impression of how service responses direct REST clients to available subsequent calls. Assume the client retrieves the response of an order and wants to follow the add-to-cart action:

{
    ... example as shown before
    ... properties of book resource
    "actions": [
        {
            "name": "add-to-cart",
            "title": "Add Book to cart",
            "method": "POST",
            "href": "http://api.example.com/shopping-cart",
            "type": "application/json",
            "fields": [
                { "name": "isbn", "type": "text" },
                { "name": "quantity", "type": "number" }
            ]
        }
    ],
    "links": ...
}

The client is only coupled to the knowledge of what business meaning the add-to-cart action has and how to provide the field value information for ISBN and quantity. This is certainly client domain logic that needs to be implemented. The information on how the subsequent resource, the shopping cart, is accessed, using which HTTP method, and what content type is now dynamic and not baked into the client.

In order to add a book to the shopping cart, the client will first access the book's resource. The add-to-cart use case is called subsequently, extracting the information of the specified Hypermedia action. The information for the required fields needs to be provided by the invocation. The client then accesses the second resource, using the information provided both by the REST service and the invocation by the control:

public class BookClient {

    @Inject
    EntityMapper entityMapper;

    public Book retrieveBook(URI uri) {
        Entity book = retrieveEntity(uri);
        return entityMapper.decodeBook(uri, book.getProperties());
    }

    public void addToCart(Book book, int quantity) {
        Entity bookEntity = retrieveEntity(book.getUri());

        JsonObjectBuilder properties = Json.createObjectBuilder();
        properties.add("quantity", quantity);

        Entity entity = entityMapper.encodeBook(book);
        entity.getProperties().forEach(properties::add);

        performAction(bookEntity, "add-to-cart", properties.build());
    }

    private Entity retrieveEntity(URI uri) {
        ...
    }

    private void performAction(Entity entity, String actionName,
            JsonObject properties) {
        ...
    }
}

The Entity type encapsulates information of the Hypermedia entity types. The EntityMapper is responsible for mapping the content type into domain models and vice versa. In this example, all the required fields for the action result from the properties of the resource plus the provided quantity parameter. To enable a certain dynamic, all entity properties are added into a map and are provided to the performAction() method. Depending on the action specified by the server, the required fields are extracted from this map. If more fields are required, the client logic obviously has to change.

It certainly makes sense to encapsulate logic for accessing Hypermedia services as well as mapping domain models to a content types into separate delegates. Functionality for accessing REST services could also sensibly be replaced by a library.

You might notice how the URI has now leaked into the public interface of the client class. This was not accidental, but required to identify resources over several use case calls. That said, the URIs move into the business domain as general identifier of resources. Since the logic of how URLs are created from technical IDs reside on the client side, the whole URL of an entity resource becomes the identifier. However, when designing client controls, engineers should take care of the public interface. In particular, no information about the communication to the external system should leak into the domain. Using Hypermedia supports this approach well. All the required transport information is retrieved and used dynamically. The navigation logic that follows Hypermedia responses resides in the client control.

This example aims to give the reader an idea how a client uses Hypermedia REST services.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.180.43