Example REST client configurations
This page presents examples of REST client definitions that leverage the possibilities of version 2 of the Magnolia REST Client module.
The examples are derived from the configurations in the declarative-rest-demo light module, a subfolder in the Magnolia rest-client repository.
As this page focuses mainly on REST client configurations, below we deal with template definitions and template scripts only marginally.
See also the Hello Magnolia - with content via REST tutorial page containing an additional and easy to configure scenario. |
Prerequisite: Magnolia
To test the REST client configurations, you need:
-
A running Magnolia instance.
If you don’t have Magnolia installed and running, go to the page called Installing Magnolia through npm CLI and complete the steps described there. -
The
declarative-rest-demo
light module.You can get a copy of the light module by cloning the https://git.magnolia-cms.com/projects/MODULES/repos/rest-client/ repository and extracting the declarative-rest-demo
directory to the folder defined by themagnolia.resources.dir
property. If you installed Magnolia using CLI, it is thelight-modules
folder, located in the root of your Magnolia installation:<your-Magnolia-installation-folder> ├── apache-tomcat/ ├── downloads/ └── light-modules/ └── declarative-rest-demo/
Case 1: Simple configuration
In this case, a REST client is configured to send a request to the /countries
path of the https://placesapi.dev/api/v1/
endpoint to get a list of countries:
Client configuration
The client is called countries
, its name is derived from the configuration file’s name. The REST call is named allCountries
in this definition.
baseUrl: https://placesapi.dev/api/v1/
restCalls:
allCountries:
method: GET
entityClass: com.fasterxml.jackson.databind.JsonNode
path: /countries
Component template script
Example component script that renders the list of countries.
[#assign response = restfn.call("countries", "allCountries")]
[#assign countries = response.get("data")]
<h2>Countries</h2>
<ul>
[#list countries.elements() as country]
<li>${country.get("name").textValue()}</li>
[/#list]
</ul>
Case 2: Configuration with a security scheme
If the REST API service needs an authentication of a REST call, you can configure a security (authentication) scheme for it under the securitySchemes
node. You can use scheme types basic
and bearer
, which are available out of the box in the REST client module.
For an example with the basic
scheme, see basic security scheme. Below, the example configuration shows a client with the bearer
scheme.
Client configuration (bearer security scheme)
Example configuration of a client called bearer-security
utilizing the bearer security scheme and an expiration limit. The scheme’s configuration is defined under the bearerTokenWithExpiryDuration
node, the authentication call is configured under authenticateWithDurationAsLong
.
baseUrl: 'http://localhost:${wiremockPort}'
securitySchemes:
bearerTokenWithExpiryDuration:
class: 'info.magnolia.rest.client.authentication.definition.BearerSecuritySchemeDefinition'
restClientName: 'bearer-security'
restCallName: 'authenticateWithDurationAsLong'
tokenJsonPath: '$.access_token'
expiry:
class: 'info.magnolia.rest.client.authentication.definition.DurationExpiryDefinition'
expiryJsonPath: '$.expires_in'
expiryTimeUnit: 'SECONDS'
restCalls:
getDataWithBearer:
method: GET
entityClass: com.fasterxml.jackson.databind.JsonNode
path: '/getDataWithBearer'
securityScheme: 'bearerTokenWithExpiryDuration'
authenticateWithDurationAsLong:
method: POST
entityClass: 'com.fasterxml.jackson.databind.JsonNode'
path: '/oauth2/token'
headers:
'Content-Type': 'application/x-www-form-urlencoded'
'X_Test_Expiry_Type': 'DURATION_AS_LONG'
Case 3: Configuration with a JavaScript model
This case makes use of a REST client called books
and a JavaScript model called search
. The model invokes the configured searchByIsbn
call that queries the https://openlibrary.org/dev/docs/api/read API with a request for a record of a book identified by the ISBN 13 number.
The component template script then renders the book’s title, number of pages and its cover image (if available).
Client configuration
baseUrl: http://openlibrary.org/api
restCalls:
searchByIsbn:
method: get
entityClass: java.lang.String
path: /volumes/brief/isbn/{isbn}.json
defaultValues:
isbn: 978-3-16-148410-0
The path property uses the {isbn} template, where the JavaScript model injects the value submitted by the user in the search field.
|
Component template script
[#assign isbn = ctx.getParameter("isbn")!]
[#assign isSubmitted = ctx.getParameter("submit")?has_content?then(true, false)]
[#if isbn?has_content && isSubmitted]
[#assign result = model.search(isbn)]
[/#if]
<h2>Search books by isbn13</h2>
<p>For example: 9780261103252, 9780582517349</p>
<div style="margin:10px">
<form method="get">
<p>
<label for="isbn">Isbn</label>
<input type="text" name="isbn" />
</p>
<input type="submit" name="submit" value="Search" />
</form>
[#if result?has_content]
<p>Title: ${result.title}</p>
<p>Number of pages: ${result.number_of_pages}</p>
<img src="${result.cover.large}" alt="Cover"/>
[/#if]
</div>
JavaScript
var BookModel = function () {
var restClient = restClientFactory.createClientIfAbsent(restClientRegistry.getProvider("books").get());
this.search = function (isbn) {
var result = restClient.invoke("searchByIsbn", { isbn: isbn});
var data = JSON.parse(result.getEntity());
if (data && data.records) {
var keys = Object.keys(data.records);
return data.records[keys[0]].data;
}
return null;
}
};
new BookModel();
Case 4: Configuration using an OpenAPI schema
The benefit of a configuration using an OpenAPI schema is that all that is required to configure a REST client is reduced just to two properties, class
and schemaUrl
.
-
For the
class
, you useinfo.magnolia.openapi.client.OpenApiRestClientDefinition
. -
For the
schemaUrl
, you provide a link to an existing definition (file or URL) complying with the OpenAPi v3 specification.
Client configuration
class: info.magnolia.openapi.client.OpenApiRestClientDefinition
schemaUrl: https://en.wikipedia.org/api/rest_v1/?spec
Component template script
[#assign aDateTime = .now]
[#assign results = restfn.call("wikipedia", "onThisDay", {"type":"all", "mm":aDateTime?string["MM"], "dd":aDateTime?string["dd"]}) ] (1)
<h2>What happened on ${aDateTime?string["MMMM"]} ${aDateTime?string["dd"]} in the past?</h2>
[#list results.get("selected").elements() as event]
<p>
${event.get("text").textValue()} (${event.get("year").intValue()?c}) (2)
</p>
[/#list]
<p>(Source: en.wikipedia.org)</p>
1 | The alias onThisDay is used to target the endpoint path since the alias is defined in the schema. If this weren’t the case, you can always refer to a call name using the following pattern: method:/path/pathAction . |
2 | At the end of the directive, the c FreeMarker builtin is used to render the intValue() for the year without formatting for human audience, for example as 2019 rather than 2,019 . |
After passing the template values for type, month and date, the component displays a list of notable events that happened on the given day at some point in the past, for example: