REST Client module

Developer productivity Bundled: Community edition

Edition

CE

License

MLA, GPL

Issues

Maven site

Latest

3.0.0

Magnolia REST Client module enables easy creation, configuration and usage of REST clients. Besides the ability to configure REST clients, the module also:

This page describes the module, explains how to install it and gives a quick reference how to declare and configure REST clients.

The ability to use REST clients in the UI (in apps and search result supplier) is a DX Core feature only, provided by the UI Framework REST Extensions module (artifactId magnolia-rest-client-ui, parent artifactId magnolia-parent-pom-enterprise).

Installing with Maven

Maven is the easiest way to install the module. Add the following to your bundle:

<dependency>
  <groupId>info.magnolia.restclient</groupId>
  <artifactId>magnolia-rest-client</artifactId>
  <version>3.0.0</version> (1)
</dependency>
1 Should you need to specify the module version, do it using <version>.
<dependency>
  <groupId>info.magnolia.restclient</groupId>
  <artifactId>magnolia-rest-client-app</artifactId>
  <version>3.0.0</version> (1)
</dependency>
1 Should you need to specify the module version, do it using <version>.

Module description

  • magnolia-rest-client - Defines the API for a Magnolia REST client definition class (to configure), for a REST client factory (to create instances) and for a registry (to obtain configured clients).

  • magnolia-rest-client-app - Installs the client app to test and debug configured REST clients. You can test your clients in the app before using them in template scripts, models or other Java classes.

Configuration

REST clients can be configured within all Magnolia modules in the restClients folder.

Example: A declaration of a client called programming-quotations. For the full use case, see Hello Magnolia - with content via REST, an extension of the Hello Magnolia introductory tutorial:

/hello-magnolia/restClients/programming-quotations.yaml
baseUrl: https://programming-quotes-api.herokuapp.com
restCalls:
  random:
    method: get
    entityClass: com.fasterxml.jackson.databind.JsonNode
    path: /quotes/random/lang/en

Additional examples of configuration and use are available on the Example REST client configurations page. Most of the configurations listed on that page are from the declarative-rest-demo light modules stored in our Bitbucket repository:

REST Client properties

Property Description

<rest client name>

required

Add a node for each REST client. The name is arbitrary, but it is good practice to use a descriptive name. The node name is used when obtaining instances of clients.

     baseUrl

required

Base URL of the REST endpoint to connect with the client.

You can also use the API_BASE_URL environment variable in the value. For more details, see the Using environment variables section.

     class

optional, default is `info.magnolia.rest.client.ConfiguredRestClientDefinition`

REST client definition class. In additional to the default class, you may use also the info.magnolia.openapi.client.OpenApiRestClientDefinition to leverage a schema based on the OpenAPI Specification.

     clientFactoryClass

optional, default is `info.magnolia.rest.client.factory.DefaultClientFactory`

The factory class. The default factory class is used with the ConfiguredRestClientDefinition.

The info.magnolia.openapi.client.factory.OpenApiClientFactory class is used with OpenApiRestClientDefinition class.

     schemaUrl

required if OpenApiRestClientDefinition is used

Full path (URL or file) to the resource containing an OpenAPI schema.

     clientConfiguratorClass

optional

Custom class that specifies the client builder.

Allows you to configure the client ex post, without the need to create a new factory or extend it.

     components

optional

List of components (for example ClientRequestFilter, ClientResponseFilter).

Registered components will be executed on every request.

Example configuration

baseUrl: https://cdn-url
components:
  cdn-purge:
     class: com.example.ipnp.magnolia.core.caching.CdnPurgeRequest
restCalls:
    cdn-purge-rest-call:
        method: post
        path:   /.purge-cdn

     enabled

optional, default is true

Enables or disables the client.

     exceptionHandlerClass

optional

Custom class that handles the HTTP standard response exceptions such as code 404 - Not Found.

Any javax.ws.rs.WebApplicationException will be handled.

     name

optional

Overrides the name assigned to the client through the node name.

The name should be unique. By default, file name is used in a file-based client definition.

     proxies

optional

List of info.magnolia.rest.client.proxy.ProxyDefinition objects.

You can use definitions with client.proxy() in the DefaultRestClient.

REST calls

Property Description

<rest client name>

     restCalls

optional

List of REST call configurations.

         <call name>

required

Add a node for each call configuration. The name is arbitrary but should be unique in the configuration.

             entityClass

required

Entity type of the REST call, for example:

  • java.lang.String

  • com.fasterxml.jackson.databind.JsonNode

  • java.util.HashMap

  • javax.ws.rs.core.Response

OpenAPI responses are always interpreted as JsonNode entities.

You can also use your own Java class. Jackson will try to map a response to it. For example:

  • info.magnolia.rest.client.Articles

             method

required

Definition of the REST method: GET, POST, HEAD, PUT, or DELETE.

             path

required

Definition of the path for the REST call.

             body

optional

Object containing request body.

If you intend to send a list of values in the body, you need to convert the list to a string.

For example, to send this:

body:
  userId: 1
  title: aTitle
  list:
    - 5

you need to convert it to and send this:

body: 'userId={userId}& title ={title}'
defaultValues:
  list: "[5]"

Likewise, none of the following will work:

body: '{"userId": 1, "title": "aTitle", "list": {list}}'
defaultValues:
  list:
    - 5
body:
  list: "{list}"
body:
  list: "[5]"
A custom body can be passed to and issued with a REST call without the need to configure them in a REST client definition file.

             cookies

optional

List of accepted request cookies.

Custom cookies can be passed to and issued with a REST call without the need to configure them in a REST client definition file.

             defaultValues

optional

List of default values. Default values can be used in any query parameter and can be overridden using invoke(<call-name>, <call-values>).

For example, the default values { theUserId: 1 } and { id: "1" } on lines 12 and 18 below are used in templates {theUserId} and {id} on lines 11 and 17, respectively:

baseUrl: https://jsonplaceholder.typicode.com

class: info.magnolia.rest.client.ConfiguredRestClientDefinition
clientFactoryClass: info.magnolia.rest.client.factory.DefaultClientFactory

restCalls:
  byUserId:
    method: get
    entityClass: com.fasterxml.jackson.databind.node.ArrayNode
    path: /posts
    queryParameters: {userId: "{theUserId}"}
    defaultValues: { theUserId: 1 }

  single:
    method: get
    entityClass: com.fasterxml.jackson.databind.JsonNode
    path: /posts/{id}
    defaultValues: { id: "1" }

             headers

optional

List of accepted request headers.

Example:

headers: + Content-Type: "application/json; charset=UTF-8"

Custom headers can be passed to and issued with a REST call without the need to configure them in a REST client definition file.

             queryParameters

optional

List of request query parameters.

Example using a template {query} for a URL such as `http://www.example.com/search?q=title~"<something>":

queryParameters: + q: "title~\"{query}\""

Custom query parameters can be passed to and issued with a REST call without the need to configure them in a REST client definition file.

             responseContentType

optional

A Content-Type header value, in case the header is missing in a response.

Example:

responseContentType: application/json

             securityScheme

optional

Name of a configured security scheme the call uses.

Trust store

If the target server uses a self-signed certificate, you can add a trust store configuration to the client.

Property Description

<rest client name>

     trustStoreConfiguration

optional

A node for a trust store configuration.

         trustStorePassword

required

String specifying the password for the certification trust store.

Required when used with a REST client definition with SSL support.

         trustStorePath

required

String specifying the location of the certification trust store.

Required when used with a REST client definition with SSL support.

         trustStoreType

required

String specifying the type of the certification trust store.

Required when used with a REST client definition with SSL support.

         trustSelfSignedCertificates

optional, default is false

Setting the property to true makes all self-signed certificates valid without the trust store.

Security scheme

If the REST API service needs an authentication of a REST call, you can configure a security (authentication) scheme under the securitySchemes node of the client configuration. Two security handlers are available out of the box:

Example configuration

Example configuration of a security scheme named b1, with a binding to a REST call named myCommand via the securityScheme property.

$magnolia.resources.dir/example-light-module/restClients/basic-security.yaml
baseUrl: http://localhost:8080/magnoliaPublic
securitySchemes: # define one or more schemes
  b1:
    $type: basic
    username: superuser
    password: superuser
restCalls:
  myCommand:
    method: post
    entityClass: com.fasterxml.jackson.databind.JsonNode
    path: /.rest/commands/v2/myCatalog/myCommand
    securityScheme: b1 # set the scheme for the call

Basic security scheme

Property Description

<rest client name>

     securitySchemes

optional

List of basic security scheme configurations.

         <security scheme name>

required

Scheme name. The name is arbitrary.

             class or $type

required

The basic security must use the info.magnolia.rest.client.authentication.definition.BasicSecuritySchemeDefinition class.

Alternatively, $type: basic may be used instead of the class definition.

             username

optional

Username used in the basic security scheme. Template values('{@password:<uuid>}') can be used, for example:

username: ‘{@password:ec0dd396-c7f0-4851-aa62-d91eed8f8b5e}’

             password

optional

Password used in the basic security scheme. Template values ('{@password:<uuid>}') can be used, for example:

password: ‘{@password:1a057890-55bd-4aa1-92b7-aab9e9740fd1}’

Bearer security scheme

Property Description

<rest client name>

     securitySchemes

optional

List of bearer security scheme configurations.

         <security scheme name>

required

Scheme name. The name is arbitrary.

             class or $type

required

The bearer scheme must use the info.magnolia.rest.client.authentication.definition.BearerSecuritySchemeDefinition class.

Alternatively, $type: bearer may be used instead of the class definition.

             restClientName

required

Name of the REST client that invokes the authentication call.

             restCallName

required

Name of the configured authentication REST call in the REST client.

             tokenJsonPath

required

The name of the property containing token information in the response. For example:

tokenJsonPath: '$.access_token'

             expiry

optional

Node with specification of a bearer token expiration resolution. The following resolution types (classes) are available:

  • duration (info.magnolia.rest.client.authentication.definition.DurationExpiryDefinition) + Resolves token expiration as duration, presented as a long number.

  • fixedDateTime (info.magnolia.rest.client.authentication.definition.FixedExpiryDateTimeDefinition) + Resolves expiration as a date-time string.

  • fixedLong (info.magnolia.rest.client.authentication.definition.FixedExpiryInLongDefinition) + Resolves expiration time presented as a long number.

                 class or $type

required

The class used to resolve token expiration, for example info.magnolia.rest.client.authentication.definition.DurationExpiryDefinition.

Alternatively, a $type alias may be used instead of the class definition:, for example $type: duration.

                 expiryDateTimePattern

optional

Mandatory for expiration $type: fixedDateTime.

Specification of the date-time pattern that needs to be parsed to obtain the expiry value.

Example:

expiryDateTimePattern: 'yyyy-MM-dd HH:mm:ss'

                 expiryJsonPath

optional

Name of the property containing expiration information.

Example:

expiryJsonPath: '$.expires_in'

                 expiryTimeUnit

optional, default is `MILLISECONDS`

Used for expiration $type: duration.

Time unit of expiration duration. If the service requires a different unit other than MILLISECONDS, refer to java.util.concurrent.TimeUnit for a list of supported values.

Example:

expiryTimeUnit: 'SECONDS'

                 expiryZoneId

optional

Mandatory for expiration $type: fixedDateTime.

Specification of the time zone in whose context the expiration is to be evaluated.

Example:

expiryZoneId: 'UTC'

Timeouts

Property Description

<rest client name>

     timeoutConfiguration

optional

A node to configure how request timeouts should be handled.

         connectTimeout

optional

Time limit (in seconds) within which the connection to the server must be made, otherwise an exception is thrown.

         fallbackToCache

optional

The property takes a boolean value, which controls fallbacking to cache.

If set to true, the cache will be used as fallback when a timeout is reached.

         readTimeout

optional

Time limit (in seconds) within which the data-read time of the specified server must be made, otherwise an exception is thrown.

         timeoutHandlerClass

optional

Custom class that handles timeout (request processing) exceptions (javax.ws.rs.ProcessingException).

If no custom handler is provided, the default one will be used.

Using environment variables

You can use environment variables in plain YAML configuration files (not in YAML decorator files).

Example of using environment variables

Let’s say you want to target a different url and supply different credentials depending on which Magnolia environment is making the call. For example if it’s your UAT or Prod environment. In this scenario, you could define three environment variables API_BASE_URL, API_USER, API_PWD and use them in your definitions.

baseUrl: !env ${API_BASE_URL}/example/todos (1)
securitySchemes:
  basic:
    $type: basic
    username: !env ${API_USER} (1)
    password: !env ${API_PWD} (1)
1 The environment variables that you export from your terminal or IDE.
For more, see Environment variables.

Hiding sensitive information

In the path, queryParameters, headers, cookies and body properties, and in the username and password properties of the basic security scheme, you can use the password template ({@password:<passwordIdentifier>}) and the respective password identifier from the Passwords app to hide password values in the requests. Example:

baseUrl: https://example.com
restCalls:
  foo:
    headers:
      api_key: '{@password:<UUID>}'

Service interface declaration

For restfn functions that utilize a service, you need to declare a service as a Java interface using javax.ws.rs annotations. The interface must be part of a Magnolia Maven module.

You can use these service interfaces in restfn and REST clients.

Example: An interface to get a client that requests api.icndb.com/jokes/random?firstName=John&lastName=Doe.

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

public interface IcndbService {
  @GET
  @Path("/jokes/{select}")
  @Produces(MediaType.APPLICATION_JSON)
  JsonNode joke(@PathParam("select") String select, @QueryParam("firstName") String firstName, @QueryParam("lastName") String lastName);
}
  • The return type of a method and the @Produces declaration must correspond with each other. In the example above, the #joke method returns an org.codehaus.jackson.JsonNode object, which fits well together with @Produces(MediaType.APPLICATION_JSON).

  • The value of the @Path annotation is relative to the baseUrl of this Java client. In this example, the relative URL starts with /jokes followed by a parameter. The baseUrl itself is defined in the configuration.

  • Create a method for each sub-resource / parameters combination you need.

Handling errors and exceptions

info.magnolia.rest.client.exception.handler.RestClientExceptionHandler in module version 2 allows you to access response codes and exceptions and deal with them the way you need. See the example template scripts below that use the following client configuration:

baseUrl: 'http://httpbin.org/'
class: 'info.magnolia.rest.client.ConfiguredRestClientDefinition'
clientFactoryClass: 'info.magnolia.rest.client.factory.DefaultClientFactory'

restCalls:
  requestCode:
    method: 'GET'
    entityClass: 'java.lang.String'
    path: 'status/{code}'
    defaultValues:
      code: 404

Get Status

[#assign code500Call = restfn.call("errors", "requestCode", {"code": 500})]

<p>
    <b>code500Call:</b> ${code500Call.getEntity()?has_content?then(code500Call.getEntity(), code500Call.getStatus())}
</p>

Response code

Get StatusInfo

[#assign code404Call = restfn.call("errors", "requestCode", {"code": 404})]

<p>
    <b>code404Call:</b> ${code404Call.getEntity()?has_content?then(code404Call.getEntity(), code404Call.getStatusInfo())}
</p>

Not found response code

Non-existing client configuration

The script refers to a REST client definition (errors1234) that doesn’t exist:

[#assign wrongClientNameCall = restfn.call("errors1234", "requestCode1234")]

<p>
    <b>wrongClientNameCall:</b> ${wrongClientNameCall.getEntity()?has_content?then(wrongClientNameCall.getEntity(), wrongClientNameCall.getStatus())}
</p>

Unknown client code

Non-existing call name

The script refers to a call name (requestCode1234) that doesn’t exist:

[#assign wrongNameCall = restfn.call("errors", "requestCode1234")]
<p>
    <b>wrongNameCall:</b> ${wrongNameCall.getEntity()?has_content?then(wrongNameCall.getEntity(), wrongNameCall.getStatus())}
</p>

Non-existing call name code

Testing clients in the Rest Client app

See the REST Client app page.

You need to configure and declare REST clients before you can test them in the app.

See also info.magnolia.rest.client.RestClient.

Feedback

DX Core

×

Location

This widget lets you know where you are on the docs site.

You are currently perusing through the DX Core docs.

Main doc sections

DX Core Headless PaaS Legacy Cloud Incubator modules