-
Notifications
You must be signed in to change notification settings - Fork 3
Entando REST API Engine
REST API in Entando
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/
.
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.
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.
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]].
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.
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 classorg.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>
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:
- the code of the current language (constant
API_LANG_CODE_PARAMETER
defined in the classcom.agiletec.aps.system.SystemConstants
- the object
com.agiletec.aps.system.services.user.UserDetails
for the current user, whose parameter name is defined through the constantAPI_USER_PARAMETER
and implemented in the classcom.agiletec.aps.system.SystemConstants,
for OAuth trusted users - the object
net.oauth.OAuthConsumer
for the “OAuth Consumer” whose parameter name is defined through the constantAPI_OAUTH_CONSUMER_PARAMETER
and implemented in the classcom.agiletec.aps.system.SystemConstants
, for OAuth trusted users.
- An optional
throws
clause to manage caught exceptions. Throw the system exceptionorg.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;
}
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
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
.
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
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:
void
- 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:
- 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
- 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 exceptionorg.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);
}
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);
}
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:
-
the code of the current language (constant
API_LANG_CODE_PARAMETER
defined in the classcom.agiletec.aps.system.SystemConstants
-
the object
com.agiletec.aps.system.services.user.UserDetails
for the current user, whose parameter name is defined through the constantAPI_USER_PARAMETER
and implemented in the classcom.agiletec.aps.system.SystemConstants
,for OAuth trusted users -
the object
net.oauth.OAuthConsumer
for the “OAuth Consumer”, whose parameter name is defined through the constantAPI_OAUTH_CONSUMER_PARAMETER
and implemented in the classcom.agiletec.aps.system.SystemConstants
, for OAuth trusted users.
- An optional
throws
clause to manage caught exceptions. Throw the system exceptionorg.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);
}
All the material here contained is published under the GNU Free Documentation License v1.3
The Entando trademark and logo are registered trademarks of Entando, srl. All
Rights Reserved.
All other trademarks are the property of their respective owners.