This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.

Adding Mediation Extensions

This tutorial uses the WSO2 API Manager Tooling Plug-in .

The API Gateway has a default mediation flow, which you can extend by adding custom mediation sequences. In API Manager there are 3 default sequences engaged as  in out  and  fault . You create a custom mediation sequence either manually or using a tool such as the WSO2 API Manager Tooling Plug-in, and then engage it per API or globally to all APIs of a specific tenant. With custom mediation sequences you can modify the default mediation flow for different usabilities according to your requirement. Log the mediation flow, execute operations on message context properties, to customize, format the requests and responses are some of them.

  • The following mediators are not usable within custom sequences because they are not supported by the API Gateway.
    • Call mediator in non-blocking mode
    • Send mediator
  • When using the Loopback mediator, it is mandatory to set the following property before defining the Loopback mediator in the custom mediator sequence in the following manner.

    <property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/>
  • If you use a  respond  mediator in the inSequence, analytics will not be captured for the corresponding API.

Default mediation flow

You cannot dynamically construct the back-end endpoint of an API using the address endpoints in the WSO2 API Manager. Instead, you can use the default endpoint to achieve the requirement of a dynamic endpoint. The default endpoint sends the message to the address specified in the To header. The To header can be constructed dynamically.
For example:

<sequence xmlns="http://ws.apache.org/ns/synapse" name="default-endpoint-seq">
  <property name="service_ep" expression="fn:concat('http://jsonplaceholder.typicode.com/', 'posts/')"/>
  <header name="To" expression="get-property('service_ep')"/>
</sequence>

In this example, you have constructed the service_ep property dynamically and assigned the value of this property to the To header. The default endpoint sends the message to the address specified in the To header, in this case, http://jsonplaceholder.typicode.com/posts/. For more details about working with dynamic endpoints, see Dynamic Endpoints.

Adding a non-blocking send operation

In this example, the Send mediator in a proxy service using the VFS Transport is transferring a file to a VFS endpoint. VFS is a non-blocking transport by default, which means a new thread is spawned for each outgoing message. The Property mediator added before the Send mediator removes the ClientAPINonBlocking property from the message to perform the mediation in a single thread. This is required when the file being transferred is large and you want to avoid out-of-memory failures.

<inSequence>
   <property name="ClientApiNonBlocking"
           value="true"
           scope="axis2"
           action="remove"/>
   <send>
      <endpoint name="FileEpr">
         <address uri="vfs:file:////home/kim/file-out"/>
      </endpoint>
   </send>
</inSequence>

Creating per-API extensions

Creating and uploading using the WSO2 API Manager Tooling Plug-in

The recommended way to engage a mediation extension sequence per API is to create a custom sequence using the WSO2 API Manager Tooling Plug-in, upload it via its APIM Perspective, and then engage it using the API Publisher. The following tutorial demonstrates how to do this: Change the Default Mediation Flow of API Requests.

Creating and uploading manually in the API Publisher

You can also create a mediation sequence manually (e.g., for instance, you can copy the above default mediation flow content into an XML file to create a customized mediation sequence) and upload it from the API Publisher itself. Thereby, this allows you to add a customized sequence to your API.

Follow the instructions below to create a custom sequence for your API:

  1. Sign in to the Publisher.
  2. Select an existing API and click Edit, in order to edit the API.
  3. Click on the Implement tab of the API.
  4. Select Enable Message Mediation.

    You can add the following types of sequences based on your requirement.

    • In Flow - To change the default request

    • Out Flow - To change the default response
    • Fault Flow - To modify the default fault sequence of events.
  5. Click on the upload option based on the type of sequence that you plan to customize.
    For the example above, you need to upload the corresponding XML file to the In flow by clicking Upload  In Flow.
  6. After the file is uploaded, save and publish the API.
    When you invoke the API in this sample scenario, the request is sent to the endpoint referred to in the To header.

Editing a mediation policy

Use the following instructions if you want to edit an already uploaded mediation policy.

  1. Select the mediation policy from the drop down list.
  2. Click the download icon next to it, as shown below:
     
  3. Edit the downloaded mediation XML file and re-upload it.

Creating manually and saving in the file system

Alternatively, you can name the mediation XML file in the pattern <API_NAME>:v<VERSION>--<DIRECTION> and save it directly in the following location:

  • In the single-tenant mode, save the XML file in the <APIM_HOME>/repository/deployment/server/synapse-configs/default/sequences directory.
  • In the multi-tenant mode, save the XML file in the tenant's synapse sequence folder. For example, if tenant id is 1, then save it in <API_Gateway>/repository/tenants/1/synapse-configs/default/sequences folder. 

In the naming pattern, the <DIRECTION> can be In or Out. When it is In, the extension is triggered on the in-flow (request path) and when it is Out, the extension is triggered on the out-flow (response path). To change the default fault sequence, you can either modify the default sequence or write a custom fault sequence and engage it to APIs through the API Publisher. 

The following is an example Synapse configuration for a per-API extension sequence that is created for the API named admin--TwitterSearch version 1.0.0.

<sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--TwitterSearch:v1.0.0--In">
 <log level="custom">
    <property name="TRACE" value="API Mediation Extension"/>
 </log>
</sequence>

You can copy this content into an XML file (e.g., twittersearch_ext.xml) and save it in the <API_Gateway>/repository/deployment/server/synapse-configs/default/sequences directory.

The above sequence prints a log message on the console whenever the TwitterSearch API is invoked.

Creating global extensions

You can also engage mediation extension sequences to all APIs of a specific tenant at once. In order to do so, simply create the XML with the naming pattern WSO2AM--Ext--<DIRECTION> and save it in the <APIM_HOME>/repository/deployment/server/synapse-configs/default/sequences directory.

An example Synapse configuration of a global extension sequence is as follows:

<sequence xmlns="http://ws.apache.org/ns/synapse" name="WSO2AM--Ext--In"> 
	<property name="Authentication" expression="get-property('transport', 'Authentication')"/> 
	<property name="Authorization" expression="get-property('Authentication')" scope="transport" type="STRING"/> 
	<property name="Authentication" scope="transport" action="remove" /> 
</sequence>

This custom sequence assigns the value of your basic authentication to Authorization header.

You can copy this content into an XML file (e.g., global_ext.xml) and save it in the <API_Gateway>/repository/deployment/server/synapse-configs/default/sequences directory.

When you invoke your REST API via a REST Client, configure that client to have a custom header (Authentication) for your basic authentication credential and configure the Authorization header to contain the bearer token for the API. When you send the Authentication and Authorization headers, the Gateway drops the Authorization header, converts the Authentication to Authorization headers and sends to the backend.

Class Mediator is one specific example of mediation extension. When creating a class mediator, we are allowed to write a Java class which extends the org.apache.synapse.mediators.AbstractMediator class.

This class implements the mediate() function which access the message context and provide the facility to customize the mediation flow of the API. Through that we can read properties of the message context into variables and perform operations.

    package samples.mediators; 
 
    import org.apache.synapse.MessageContext;
    import org.apache.synapse.mediators.AbstractMediator;
    import org.apache.axiom.om.OMElement;
    import org.apache.axiom.om.OMAbstractFactory;
    import org.apache.axiom.om.OMFactory;
    import org.apache.axiom.soap.SOAPFactory;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
 
    import javax.xml.namespace.QName;
 
    public class SimpleClassMediator extends AbstractMediator {

        private String variable1 = xxx;       

        private static final Log log = LogFactory.getLog(SimpleClassMediator.class);
        
        public SimpleClassMediator(){}
 
        public boolean mediate(MessageContext mc) {
            // Do somthing useful..
            // Implementation of Reading the propertly values of Message context and modifying request / logging properties
            return true;
        }
 
        public String getType() {
            return null;
        }
 
        public void setTraceState(int traceState) {
            traceState = 0;
        }
 
        public int getTraceState() {
            return 0;
        }


        public void setVariable1(String newValue) {
            variable1=newValue;
        }
 
        public String getVariable1() {
            return variable1;
        }
  
       
    }

Then we can export this class as a jar file and add as a library to <API-M_HOME>/repository/components/lib directory.

By referring this class with the fully qualified class name in a class mediator in the API as below, we can execute it in the in-sequence or out-sequence of the API globally or per API as described above.

<class name="samples.mediators.SimpleClassMediator">                
	<property name="propertyName" value="propertyValue"/>
    ....
</class>

If any properties are specified in the Java class of the class mediator, the corresponding setter methods are invoked once on the class during initialization.

You can use the class mediator for user-specific, custom developments only when there is no built-in mediator that already provides the required functionality, because maintaining custom classes incurs a high overhead. Therefore, avoid using them unless the scenario is frequently re-used and very user-specific.

Your class mediator might not be picked up and updated, if you use an existing package when creating it.

If you are using a respond mediator in the In sequence, you need to include the APIMgtResponseHandler before the respond mediator to be able to publish the statistics.

<sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--Test:v1.0.0--In">
   <call blocking="true">
      <endpoint>
         <http method="GET" uri-template="http://abc.com">
            <timeout>
               <duration>120000</duration>
               <responseAction>fault</responseAction>
            </timeout>
         </http>
      </endpoint>
   </call>
 
   <property name="ENDPOINT_ADDRESS" value="http://abc.com"/> 
   <class name="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtResponseHandler"/>
   <respond/>
</sequence>

Make sure that you add the ENDPOINT_ADDRESS parameter to populate the destination address for statistics (API Usage by Destination) as shown in the example below.

<property name="ENDPOINT_ADDRESS" value="http://abc.com"/>