apim
2016/04/27
27 Apr, 2016

[Article] Customizing Your API Lifecycle with WSO2 API Manager

  • Chamila Adhikarinayake
  • Associate Technical Lead - WSO2

Table of contents


Applies to

WSO2 API Manager Version 1.10 or above


Introduction

Designing and managing an API is essential for both API providers and consumers. A good API needs to have a proper RESTful design and implementation with lifecycle management in order to

  • Increase reliability, stability and availability
  • Enable effective collaboration between operations and stakeholders
  • Allow the version strategy of an API to be managed
  • Help attract app developers to adopt APIs

This article will showcase a scenario that explains how to completely manage an API’s lifecycle with WSO2 API Manager.


What is an API lifecycle?

API lifecycle is an agile process for managing the life of an API. Figure 1 shows the default lifecycle state of an API in WSO2 API Manager.

Figure 1


Managing an API’s lifecycle

The earlier versions of WSO2 API Manager had only predefined API lifecycle states (created, prototyped, published, blocked, deprecated and retired). The all new WSO2 API Manager 1.10 provides new capability to modify the API lifecycle and customize it based on specific user needs.

This feature gives you the following capabilities:

  • Ability to plug a configurable API lifecycle (XML based)
  • Customizable lifecycle states and state transition execution process
  • Dynamic UI for API Publisher lifecycle tab view
  • Integrated WSO2 Governance Registry lifecycles

There can be many use cases where the default lifecycle may not be enough. For example, the following use cases cannot be handled using the existing lifecycle:

  • Pushing APIs to different API manager instances
  • Providing workflow extension support
  • Adding a notification mechanism for state changes
  • Restricting lifecycle state changes based on user roles, etc.

The following section describes how to implement one of the above mentioned use cases.


Deploying an API in multiple environments

Scenario

An organization needs to govern their APIs across multiple API Manager environments as shown in figure 2.

Figure 2

In this scenario, an API is exported to different API manager instances such as Development Environment, QA Environment and finally Production Environment. In a real world scenario, an API developer would start development in the Development Environment. Next it will be pushed to the Governing API Manager Environment, which will then take it to the QA Environment. It will later be promoted to the Production Environment.

To implement this using WSO2 API Manager 1.10, you need to design the lifecycle and create an executor.

Sample code and configurations provided below only contains a part of the above scenario. It demonstrates the transactions between Governing API Manager Environment and the QA Environment. Similar lifecycle and executor can be used to implement the complete scenario.


Designing the lifecycle

Figure 3

A new lifecycle state QA is introduced for this.The lifecycle event Export to QA will push the API from one API manager instance to another. The lifecycle event Demote to Create will delete the API from the QA environment. The custom lifecycle configuration file for this state transition can be found in the attached resource file at the end of this article.

Following is the modifications done to the default lifecycle. Existing Created state is modified and a new state QA is introduced to the existing lifecycle. You can see the modified section in the default lifecycle below.

<state id="Created">
                	<datamodel>

                    	<data name="checkItems">
                        	<item name="Deprecate Old Versions" forEvent="">
                        	</item>
                        	<item name="Require Re-Subscription" forEvent="">
                        	</item>
                    	</data>

                    	<data name="transitionExecution">
                        	<execution forEvent="Deploy as a Prototype"
                                   	class="org.wso2.carbon.apimgt.impl.executors.APIExecutor">
                        	</execution>
                        	<execution forEvent="Publish"
                                   	class="org.wso2.carbon.apimgt.impl.executors.APIExecutor">
                        	</execution>
                        	<execution forEvent="Export to QA"
                                   	class="org.wso2.carbon.apimgt.APIImportExportExecutor">
                             	<parameter name="localServerUrl" value="https://localhost:9443/api-import-export-v1.0.1" />   	 
   			  <parameter name="remoteServerUrl" value="https://localhost:9444/api-import-export-v1.0.1" />    
   			  <parameter name="localCredentials" value="YWRtaW46YWRtaW4=" />    
   			  <parameter name="remoteCredentials" value="YWRtaW46YWRtaW4=" />    
                        	</execution>                      	 
                    	</data>
                	</datamodel>
                	<transition event="Publish" target="Published"/>              	 
                	<transition event="Export to QA" target="QA"/>
                	<transition event="Deploy as a Prototype" target="Prototyped"/>
 </state>            
<state id="QA">   
                	<datamodel>                  	 
                    	<data name="transitionExecution">                       	 
                        	<execution forEvent="Publish"
                                   	class="org.wso2.carbon.apimgt.impl.executors.APIExecutor">
                        	</execution>    
                        	<execution forEvent="Demote to Created"
                                   	class="org.wso2.carbon.apimgt.APIDeploymentExecutor">
                             	<parameter name="server" value="https://localhost:9444" />   							 
   			  <parameter name="tokenEndpoint" value="https://localhost:8244/token" />    
   			  <parameter name="clientId" value="pusA7vjnT0mQgkDcKtAHyoSJASIa" />    
   			  <parameter name="clientSecret" value="zlx_PdR0pIdEgTyB0Pd_shqHjIQa" />   		 
                        	</execution>                  	 
                    	</data>
                   	 
                	</datamodel>            	 
                	<transition event="Demote to Created" target="Created"/>
                	<transition event="Publish" target="Published"/>
 </state>

In the Created state a new transaction event Export to QA is added to change the lifecycle state from Created to the newly added QA state. An executor is used to export the API to an isolated API Manager instance during the transition.

<transition event="Export to QA" target="QA"/>

Demote to Created event in QA state is used to delete the API from the previously exported API Manager instance.

<transition event="Demote to Created" target="Created"/>

Note: Add "export to qa" : "Export to QA" entry to /repository/deployment/server/jaggeryapps/publisher/site/conf/locales/jaggery/locale_default.json file. This is used to provide localization for UI elements. For any newly added event transition this needs to be done. See here for more information.


Creating an executor

The executor can be introduced to do some tasks for a lifecycle state change. Each lifecycle transition event can have it’s own executor. By default org.wso2.carbon.apimgt.impl.executors.APIExecutor is used for every lifecycle state change related to an API.

When writing a custom executor, some methods in org.wso2.carbon.governance.registry.extensions.interfaces.Execution need to be implemented.

import java.util.Map;
import org.wso2.carbon.governance.registry.extensions.interfaces.Execution;
import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext;

public class SampleExecutor implements Execution {

@Override
public void init(Map parameterMap) {
    	// TODO Auto-generated method stub
}

@Override
public boolean execute(RequestContext context, String currentState, String targetState) {
    	// TODO Auto-generated method stub
    	return false;
	}
}

The execution interface has two methods init() and execute(). The init() method is used to handle any parameters passed from the lifecycle XML. The execute() method handles lifecycle state changes. It returns a boolean value, which is used to decide the success or failure of the transition.

This sample uses the two custom executors explained below:

  1. APIDeploymentExecutor - this executor is used to remove the API from an isolated API Manager instance. It is invoked during the Demote to Created transition event. This executor calls a new Publisher REST API to delete the chosen API. See here for more information.
  2. APIImportExportExecutor - this executor exports the API from the current API manager environment to an isolated API Manager environment. It is implemented to use the API import/export tool. See here for more information.


Steps to deploy the sample

  1. Create two API manager instances (say MAIN and QA).
  2. Copy custom-executor.jar to /repository/components/lib/ location in the MAIN API manager.
  3. Download the latest WSO2 API Manager import/export tool from here and deploy it in both API manager instances.
  4. Register an OAuth application in the QA environment and get the client ID and client secret. See here for more information. WSO2 API Manager 1.10 contains a new REST API to access the publisher and store functions. These new APIs are secured using OAuth2 tokens. This step is done to create an OAuth2 application to generate tokens that access this REST API in the QA environment.
  5. Log in to the management console in the MAIN API manager instance and go to Home > Extensions > Configure > Lifecycles and open APILifeCycle. Replace it with the custom lifecycle provided in the sample.
  6. Open the custom lifecycle and update the following parameters in the following sections:

    In QA state replace the client ID and secret values with the previously generated values in step 4. The server URL and tokenEndpoint are related to the URL in the QA environment:

    <execution forEvent="Demote to Created" class="org.wso2.carbon.apimgt.APIDeploymentExecutor">
                              <parameter name="server" value="https://localhost:9444" />   							 
       			  <parameter name="tokenEndpoint" value="https://localhost:8244/token" />    
       			  <parameter name="clientId" value="mVfsmtMopw1NFKQ6hjO7DlxqYEga" />    
       			  <parameter name="clientSecret" value="ApI7lP70qhoTIwLhONSpZeXwYp0a" />   		 
    </execution>   
    

    In the created state replace server URLs and update the credentials. The credential is a base64 encoded value of the username:password value. The user also needs to have admin permission.

    <execution forEvent="Export to QA" class="org.wso2.carbon.apimgt.APIImportExportExecutor">
      	<parameter name="localServerUrl" value="https://localhost:9443/api-import-export-v1.0.1" />   	 
      	<parameter name="remoteServerUrl" value="https://localhost:9444/api-import-export-v1.0.1" />    
      	<parameter name="localCredentials" value="YWRtaW46YWRtaW4=" />    
      	<parameter name="remoteCredentials" value="YWRtaW46YWRtaW4=" />    
    </execution>              	 
    
  7. Add the following entry to the /repository/deployment/server/jaggeryapps/publisher/site/conf/locales/jaggery/local_defaul.json file in the MAIN API manager. This is done to provide localization support for newly added lifecycle events.
    "export to qa" : "Export to QA"
    
  8. Create an API and check the lifecycle tab for the newly created state transition event.

    Figure 4

Sample code: wso2.com/files/resources-for-customizing-api-lifecycles.zip


Conclusion

WSO2 API Manager 1.10 gives you the capability to customize the API lifecycle, including executing custom behavior on lifecycle transitions. This feature enables complete lifecycle management over your APIs allowing you to create an optimized API management system.

 

About Author

  • Chamila Adhikarinayake
  • Associate Technical Lead
  • WSO2 Inc.