Page tree
Skip to end of metadata
Go to start of metadata

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.

Version 2.0 of the module, released with Magnolia 6.2, includes a number of improvements and changes. For an overview, see the Changes in the REST Client module section of the Magnolia 6.2 Release Notes.

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

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>2.0.1</version>
</dependency>

<dependency>
  <groupId>info.magnolia.restclient</groupId>
  <artifactId>magnolia-rest-client-app</artifactId>
  <version>2.0.1</version>
</dependency>

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 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:

Properties

<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.

class

required

The following classes are available:

  • info.magnolia.rest.client.ConfiguredRestClientDefinition (default class)
  • info.magnolia.openapi.client.OpenApiRestClientDefinition (leveraging a schema based on the OpenAPI Specification)

clientFactoryClass

required

The factory class.

If using the ConfiguredRestClientDefinition, you must implement the info.magnolia.rest.client.factory.DefaultClientFactory class (default class).

The OpenApiRestClientDefinition class uses by default the info.magnolia.openapi.client.factory.OpenApiClientFactory 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.

See also https://en.wikipedia.org/wiki/Java_API_for_RESTful_Web_Services.

components

optional

List of components (for example ClientRequestFilter, ClientResponseFilter ).

Registered components will be executed on every request.

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 ProxyDefinition objects.

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

REST call

<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

(warning) 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. (warning) If you intend to send a list of values in the body, you need to convert the list to a string.

 Example. (Click to expand.)

To send this

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

you need to convert it to and send this:

body: '{"userId": 1, "title": "aTitle", "list": {list}}'
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]"

cookies

optional

List of accepted request cookies.

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"

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}\""

responseContentType

optional

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.

<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:

Basic security scheme
<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
<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'

Timeout configuration properties

<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.

See also Cache configuration properties

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.

Cache configuration properties

<rest client name>


cacheConfiguration

optional

A node to configure how caching should be handled.

implementationClass

optional, default is info.magnolia.rest.client.cache.filter.CachingFilter

Specifies the implementation class.

expireIn

optional

Specifies an expiration time (in seconds) for a cache entry. In the default implementation, the expiration time is set to 0.

See also the fallbackToCache property in Timeout configuration properties.

Example configuration for caching and timeouts
baseUrl: http://httpbin.org/
cacheConfiguration:
  expireIn: 60

timeoutConfiguration:
  readTimeout: 5
  fallbackToCache: true

restCalls:
  delay:
    method: GET
    entityClass: java.lang.String
    path: delay/{delay_period}
    defaultValues:
      delay_period: 3

Hiding sensitive information

In the pathqueryParameters,  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  http://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

The 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

Display the response status code (https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/Response.html#getStatus--):

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

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

Get StatusInfo

Display the response status information (https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/Response.html#getStatusInfo--):

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

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

See also RFC-2616: 10 Status Code Definitions.

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>

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>

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

Magnolia REST Client module API

  • RestClient