Content HAL API
Introduction
The Content HAL API add-on enables you to provide JSON Hypertext Application Language based REST APIs from your delivery applications.
JSON Hypertext Application Language is a specification draft for HATEOAS (Hypermedia as the Engine of Application State), a constraint of the REST application architecture. Responses of HAL services are in the application/hal+json media type, and the HAL specification mostly uses Plain Old JSON as its primary design goals are generality and simplicity.
Swagger API Document Support
The Content HAL API Add-on supports Swagger API Document URL by default. For example, if you installed the Content HAL API on /api mount (e.g, http://localhost:8080/site/api), then the Swagger API Document URL will be available automatically at /api/api-docs/swagger.json (e.g, http://localhost:8080/site/api/api-docs/swagger.json) by default. So, if you installed a Swagger UI web application, then you can navigate the Content HAL API by explorering the Swagger Document URL (e.g, http://localhost:8080/site/api/api-docs/swagger.json).
Content HAL API URL Patterns
See the API page how to access the REST APIs.
Every Response Body is a HAL Resource
In a HAL API like the Content HAL API Add-on, every response must be a HAL resource.
Minimal HAL Resource Example
A minimal HAL resource can be an empty JSON object:
{ }
Typical HAL Resource Example
However, an empty HAL resource wouldn't be very useful, so it is very common to have links including "self" at least in a reserved property, "_links", like the following example:
{ "_links": { "self": { "href" : "/orders/523" } } }
So, it represents a resource with the link to itself at least.
But, in practical use cases, a resource should have more fields like the following example:
{ "_links": { "self": { "href": "/orders/523" }, "invoice": { "href": "/invoices/873" } }, "currency": "USD", "status": "shipped", "total": 10.20 }
A HAL resource can have properties with any names (currency, status, total, etc.) with links (in a reserved property, "_links") as long as it is a valid JSON object.
HAL Resource Example Embedding Other Resource(s)
A HAL resource can embed other resources, and the embedded resource may include all the fields or parts of its fields:
{ "_links": { "self": { "href": "/orders" } }, "_embedded": { "orders": [{ "_links": { "self": { "href": "/orders/523" } }, "total": 30.00 },{ "_links": { "self": { "href": "/orders/524" } }, "total": 20.00 }] } "currentlyProcessing": 14, "shippedToday": 20 }
So, suppose you get the above response from http://localhost:8080/sales/orders. The resource in this response may include all the order collection data inside the reserved property, "_embedded", as well as other fields, like shown above.
How Hippo Document is mapped to HAL Resource
Now, the question is how a Hippo document is mapped to a HAL resource. That's where the Content HAL API is expected to contribute.
The Content HAL API Add-on takes a straightforward approach. It takes the field names which were already defined through document type (a.k.a "namespace") designs. Let's see the following document type example ("Event" document type).
The "Event" document type contains multiple fields including "title", "introduction", "content", "startdate", "enddate", "location", etc. In "Path" configuration, it is defining the logical field names ("title", "introduction", "content", "startdate", "enddate", "location", etc.) which are different from the captions such as "Title", "Introduction", "Content", etc.
By the way, if you look at those in CMS Console, you will realize that those "Path" configurations are actually stored in hipposysedit:nodetype/hipposysedit:nodetype configuration in a document type (a.k.a "namespace") definition.
As the captions are only for displaying purpose, it makes sense to take the logical field names configured in "Path" configurations and use those for JSON properties in HAL resource representations like the following example:
So, an "Event" document can be represented as a JSON HAL resource by converting all the fields of the document into JSON properties by adopting the same logical field names (as configured in "Path") like the example shown above. Also, it can have links under the reserved "_links" property in the resource object to represent its own link ("self") that can be generated by HST-2 API.
Now, how about a compound field like "content" field which contains RichText data? The same rule applies to that, too!
A "Event" document has the "content" field which is type of "hippostd:html". It means that we can convert the "hippostd:html" node to another JSON object by converting each property of "hippostd:html" node type. An example is shown below:
Since "hippostd:html" node type contains a "content" property, the "content" field is expanded to a new JSON object containing "content" property that is expanded to a string JSON property.
By the way, it is just a coincidence to have two "content" fields in the example; one is defined in "Event" document, and the other is defined in "hippostd:html" compound node type itself. If you named the field in "Event" document to something else like "body", the first one would have been "body" instead.
Now, how about linked images/assets or documents in a document? For example, an "Event" document can have "image" field that has a link data to other CMS image asset node. How can we represent those links in a document in a HAL resource?
Since the "image" field contains only link information only ("hippo:docbase") which is very CMS-specific, it makes sense to include those metadata in a HAL resource, in a special property, "_meta".
All the CMS-specific metadata are included in a reserved property, "_meta", like the example shown above. The "_meta" property may contains JCR primary type name ("type"), and it may contain the link information in "mirror" (including both node UUID and node path for developer's convenience) JSON object if there's any link data. By the way, unlike "_links", "_meta" is introduced by Content HAL API Add-on as a HAL extension.
How to Include Site Link?
By default, a HAL resource includes a "self" link for a document (e.g, a document at content/documents/myproject/events/2019/01/introduction-speech) like the following example:
{ "_links": { "self": { "href": "http://localhost:8080/site/api/documents/18e36c35-429d-4fee-b76e-eeabcbfc08bb" } } }
Suppose you want to include "site" link as well like the following:
{ "_links": { "self": { "href": "http://localhost:8080/site/api/documents/18e36c35-429d-4fee-b76e-eeabcbfc08bb" }, "site": { "href": "http://localhost:8080/site/events/2019/01/introduction-speech.html" } } }
In this case, you should configure HST-2 mount alias mapping properly.
Here are the configuration steps you should follow:
- Set hst:alias property of the parent mount (e.g, /hst:root) of Content HAL API mount (e.g, /hst:root/api) to "site". That is, /hst:root/@hst:alias="site".
- Add hst:mountsite property (String) with a value, "site", to the Content HAL API mount (e.g, /hst:root/api). That is, /hst:root/api/@mountsite="site"
- Then Content HAL API can find the parent mount through the mapping (@hst:mountsite="site"), in its mount configuration, to the specific mount having @hst:alias="site" (i.e. /hst:root), and generate the "site" link to include it in _links property.