Skip to content

Entando REST API Engine

MEM2677 edited this page Mar 14, 2013 · 2 revisions

Entando REST API Engine

REST API in Entando

Table of Contents

Scope of the document

This documents explains how to create a REST resource on the Entando 3.0 platform.

Please note that this guide is for both Linux and Windows platforms; the same concepts apply to both the environments.

The present document is based on the demo service “Card” as shown in the PortalExample project, contained entirely in the package org.entando.entando.portalexample of the Java classes and in the directory src/main/webapp/WEB-INF/portalexample/.

What this document is not

This document neither exposes the concept of API (usage scenarios and possible applications) nor describes the advantages of REST interfaces; for the basics have a look at this page; for a catchy introduction consult this article.

Intended audience

This document is aimed to those developers who created an application service willing to expose, in a flexible and secure manner) their own service using the API engine of the platform.

Prerequisites

This document assumes the reader has a working development environment, as explained in the document Setup a Java development Environment for the Entando platform; another recommended reading is [[The Entando model]].

Create a new API Resource

To create a new REST resource for the Entando platform the first thing to do is to create its signature or prototype. It must be created inside a XML file named apiMethods.xml placed in the directory /src/main/resources/api/. This file must be placed under an aps type folder, belonging either to the core or to a plugin.

In the first case the folder will be src/main/resources/api/aps otherwise /src/main/resources/api/plugins/<PLUGIN_ID>/aps.

For a custom extension of the project the proper location would be src/main/resources/api/<PROJECT_CODE>/aps: this is exactly the case of PortalExample.

Resource definition

The file apiMethods.xml must respect the schema defined in the file

Each definition of a REST resource may present the following elements:

  • name of the resource is specified in the attribute name of the resource tag. Optional namespace specification must use the namespace attribute. The name attribute is mandatory.

  • the resource description is mandatory, must be declared in the tag description

  • the source of the service can be either plugin, core, or the <CUSTOM_PROJECT_CODE> for customization; if the source is a plugin the attribute plugin must be used to specify the plugin code (or ID). The source specification is mandatory.

  • A list of the available HTTP methods: you must specify at least one.

Each available method for the resource presents:

  • The method type through httpMethod attribute, is mandatory.

  • The default state of the method: we have the active attribute (true|false) for the activation status, requiredAuth is used to restrict access to users authenticated with OAuth while requiredPermission is needed when a specific authorization is required for users authenticated with OAuth to use the method.
    It is worth noting that none of the attributes above is mandatory; if they are omitted the the method is by default active and available to everyone (neither authentication nor authorization required!)

  • The attribute canSpawnOthers (true|false) toggles the possibility to create services based on the current method; it can be used with the GET method only.
    In other words this attribute indicates the possibility to specialize the method to create shortcuts -through the Entando back office interface for the REST services – to serve data or services of interest. Such data or services will be made available through to the default REST resources like getServices and getService. This attribute is not mandatory.

  • the description of the method, done through the tag description. This is mandatory.

  • the name of the Spring bean and the method of the Java class used to implement the service. They are declared using the tag springBean and its attributes name and method. This tag is mandatory.

  • The expected type. The tag expectedType can be used only with the POST or PUT method, It specifies the Java class whose body represents the request (of either POST or PUT), coded following the JAXB 2.0 specifications

  • The class that encapsulates the response of the GET methods. The tag, responseClass is the implementation of the class org.entando.entando.aps.system.services.api.model.AbstractApiResponse;
    The response has a standard form, as shown below

        <response>
            <errors>
                <error>
                    <code>ERROR_CODE</code>
                    <code>DESCRIPTION</code>
                </error>
                ….
                ….
            </errors>
            <result>
                <html>
                    <!- [CDATA- [ HTML RAPPRESENTATION ]]>
                </html>
                <item>
                    …
                    …
                </item>
            </result>
        </response>

The 'responseClass' tag is not mandatory; if omitted the response is the representation of the class following the JAXB 2.0 specifications.

  • The list of the request parameters; they are declared in the form of a list of 'parameter' inside the 'parameters' element. Every parameter must specify the following attributes: 'key' for the parameter name, required (true|false) and the sub element description.

Here is an example of the representation of the 'Card' resources, as defined in the portalExample demo project.

        <resource name="card">
            <description>The card</description>
            <source>portalexample</source>
            <method httpMethod="GET" active="true" canSpawnOthers="true">
                <description>Return a card by id</description>
                <springBean name="CardManager" method="getCardForApi" />
                <responseClass>org.entando.entando.portalexample.aps.system.services.card.api.CardResponse</responseClass>
                <parameters>
                    <parameter key="id" required="true">
                        <description>The id of the card to return</description>
                    </parameter>
                </parameters>
            </method>
            <method httpMethod="POST" active="true" requiredAuth="true" requiredPermission="superuser">
                <description>Add a card</descrip
                <springBean name="CardManager" method="addCardForApi" />
                <expectedType>org.entando.entando.portalexample.aps.system.services.card.Card</expectedType>
            </method>
            <method httpMethod="PUT" active="true" requiredAuth="true" requiredPermission="superuser">
                <description>Update a card</description>
                <springBean name="CardManager" method="updateCardForApi" />
                <expectedType>org.entando.entando.portalexample.aps.system.services.card.Card</expectedType>
            </method>
            <method httpMethod="DELETE" active="true" requiredAuth="true" requiredPermission="superuser">
                <description>Delete a card by id</description>
                <springBean name="CardManager" method="deleteCardForApi" />
                <parameters>
                    <parameter key="id" required="true">
                        <description>The id of the card to delete</description>
                    </parameter>
                </parameters>
            </method>
        </resource>

Method signature

GET method

Inside the bean referred by the springBean tag and by the name attribute, must be present a method with the same name of the method attribute:

Such method must have:

  • a public access modifier
  • the returned object, a java Class that can be represented using JAXB 2.0 specs (the annotation @XmlRootElement must be present as minimum requirement)
  • A unique argument of type java.util.Properties containing the parameters of the request:
  1. the code of the current language (constant API_LANG_CODE_PARAMETER defined in the class com.agiletec.aps.system.SystemConstants
  2. the object com.agiletec.aps.system.services.user.UserDetails for the current user, whose parameter name is defined through the constant API_USER_PARAMETER and implemented in the class com.agiletec.aps.system.SystemConstants, for OAuth trusted users
  3. the object net.oauth.OAuthConsumer for the “OAuth Consumer” whose parameter name is defined through the constant API_OAUTH_CONSUMER_PARAMETER and implemented in the class com.agiletec.aps.system.SystemConstants, for OAuth trusted users.
  • An optional throws clause to manage caught exceptions. Throw the system exception org.entando.entando.aps.system.services.api.model.ApiException if you are willing to handle errors in the response of the service.

A possible implementation of the GET method:

        public Card getCardForApi(Properties properties) throws Throwable {
            String idString = properties.getProperty("id");
            int id = 0;
            try {
                id = Integer.parseInt(idString);
            } catch (NumberFormatException e) {
                throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "Invalid number format for 'id' parameter - '" + idString + "'", Response.Status.CONFLICT);
            }
            Card card = this.getCard(id);
            if (null == card) {
                throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Card with id '" + idString + "' does not exist", Response.Status.CONFLICT);
            }
            return card;
        }

Response HTML representation

If the responseClass of the GET method implements the class org.entando.entando.aps.system.services.api.model.AbstractApiResponse it is possible to associate to that response also its HTML representation, that will be encapsulated in a CDATA element within the HTML tag of the response itself.

There are currently two options to get the HTML of the returned object:

  • implementing the method <MASTER_METHOD_NAME>ToHtml
  • defining a Velocity template

Implementation of the <MASTER_METHOD_NAME>ToHtml method

Inside the bean referred to by the “springBean ” tag and by the “name ” attribute, must be present a method with the same name of the “method ” attribute with the suffix ToHtml

The method has the same signature of the “master ” method with the only difference that the returned object must always be a string of type java.lang.String.

Insertion of the velocity template

If the method of the previous paragraph is not present then a template is searched in the classpath classpath*:/api/aps/get/<RESOURCE_NAME>/description-item.vm, for resources defined in the Entando core.

This file contains the representation of the object (called item in the example below) to be returned.

    $item.id \n
    $item.holder \n 
    $item.descr \n
    $item.date \n
    #if ($item.note)
    $item.note \n
    #end

For plugins the template is searched in classpath*:/api/plugins/<PLUGIN_CODE>/aps/get/<RESOURCE_NAME>/description-item.vm

If the resources was defined under a namespace, the template is searched in
classpath*:/api/aps/get/<NAMESPACE>/<RESOURCE_NAME>/description-item.vm

If the resource was defined in a custom project extension, the template is searched in classpath*:/api/aps/get/<NAMESPACE>/<RESOURCE_NAME>/description-item.vm

POST method

Inside the bean referred by the springBean tag and by the name attribute, must be present a method with the same name of the method attribute.

Such method must have:

  • a public access modifier
  • one of the following possible returned objects:
  1. void
  2. a java class org.entando.entando.aps.system.services.api.model.StringApiResponse where errors may be inserted. It is possible to return a null object.
  • two options for the parameters list:
  1. a unique argument in the form of a java object representing the body of the request whose type (class) is defined in the “expectedType” tag
  2. a java object representing the body of the request whose type (class) is defined in the tag “expectedType” and the object java.util.Properties containing the parameters of the request, whose structure and values match those of the POST method.
  • Option throws clause where to handle caught exceptions. Throw the system exception org.entando.entando.aps.system.services.api.model.ApiException if you are willing to handle errors in the response of the service.

A possible implementation:

  public void addCardForApi(Card card) throws ApiException, ApsSystemException {
      if (null != this.getCard(card.getId())) {
          throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Card with id " + card.getId() + " already exists", Response.Status.CONFLICT);
      }
      this.addCard(card);
  }

PUT method

Please take the POST method as reference because POST and PUT share the same utilization.

A possible implementation:

        public void updateCardForApi(Card card) throws ApiException, ApsSystemException {
            if (null == this.getCard(card.getId())) {
                throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Card with id " + card.getId() + " does not exist", Response.Status.CONFLICT);
            }
            this.updateCard(card);
        }

DELETE method

Inside the bean referred by the springBean tag and by the name attribute, must be present a method with the same name of the method attribute.

This method must present:

  • a public access modifier

  • A unique argument of type java.util.Properties containing the parameters of the request:

  1. the code of the current language (constant API_LANG_CODE_PARAMETER defined in the class com.agiletec.aps.system.SystemConstants

  2. the object com.agiletec.aps.system.services.user.UserDetails for the current user, whose parameter name is defined through the constant API_USER_PARAMETER and implemented in the class com.agiletec.aps.system.SystemConstants ,for OAuth trusted users

  3. the object net.oauth.OAuthConsumer for the “OAuth Consumer”, whose parameter name is defined through the constant API_OAUTH_CONSUMER_PARAMETER and implemented in the class com.agiletec.aps.system.SystemConstants, for OAuth trusted users.

  • An optional throws clause to manage caught exceptions. Throw the system exception org.entando.entando.aps.system.services.api.model.ApiException if you are willing to handle errors in the response of the service.

A possible implementation:

        public void deleteCardForApi(Properties properties) throws Throwable {
            String id = properties.getProperty("id");
            int idInteger = 0;
            try {
                idInteger = Integer.parseInt(id);
            } catch (NumberFormatException e) {
                throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "Invalid number format for 'id' parameter - '" + id + "'", Response.Status.CONFLICT);
            }
            this.deleteCard(idInteger);
        }
Clone this wiki locally