Saturday, February 11, 2017

WSO2 API Manager : Configure timeouts

A server connection timeout error does little to tell you what went wrong or why the error happened: it just identifies that the error occurred. Since Endpoints send the message out, they can encounter various transport errors. For example connection may time out, or connection may be closed by the actual service and even an Internet connection can be at fault.

Today we are talking how we can deal with Connection timed out errors in APIM.

Use-Case


Suppose a user is having a backend which is taking more than 5 -6 minutes to give a response back, The API that is waiting for backend response and will make timeout error after waiting 30000ms since exceeding of default value of the endpoint timeout by thinking connection may be closed by the actual service. 

We can get over with this kind of situations by doing manual configurations inside the apim configurations.        



There are 3 types of timeouts in API Manager

  • Endpoint timeout/connection timeout in per API level
  • Socket timeout
  • Global timeout


  1. When it’s needed to Set timeout in API level per each API you can go for following method. You can set the timeout value through management console for the API you want to increase the time out for 6 min.(60000miliseconds * 6 = 360000 ms)Please note that this configuration will override the "synapse.global_timeout_interval" value for that API

  2. <api name="admin--Emailverification" context="/phoneverify" version="1.0.0" version-type="url">
     <send>
       <endpoint name="admin--Emailverification_APIproductionEndpoint_0">
          <http uri-template="  http://ws.cdyne.com/emailverify/emailverify.asmx" />
          <timeout>
             <duration> 360000 </duration>
             <responseAction>fault</responseAction>
          </timeout>
       </endpoint>
    </send>
    </api>
    



  3. Socket timeout defined in the passthru-http.properties (APIMHOME\repository\conf\passthru-http.properties)

  4. http.socket.timeout=60000000
  • But According to the scenario we are talking here you can see endpoint timeout > http.socket.timeout since our default socket.timeout is 60000ms ..


  •  It's important If the endpoint timeout > http.socket.timeout, whatever value we set in endpoint timeout is not getting applied, but the value of http.socket.timeout will be used in request timeouts. Basically, when endpoint timeout > http.socket.timeout, the engine will timeout the endpoint after http.socket.timeout, irrespective of the timeout action or timeout value we configured in endpoint level.

  • So it is a must to configure http.socket timeout to higher value than the synapse global timeout or endpoint timeout values.

So I am increasing the socket timeout value here, adhering to the above condition ("http.socket.timeout=60000000" )

3. Global timeout defined in synapse.properties (\repository\conf\synapse.properties)This can’t be set per API level but when it’s applied it will affect globally for all API’s 

    synapse.global_timeout_interval=60000000


Note:

If you need any further assistance or have queries regarding the "WSO2 API Manager  : Configure timeouts"  Do not hesitate to comment below ....

Saturday, December 10, 2016

WSO2 API Manager, What is the Difference, relation between handlers and mediators.


I’ve already discussed how to write a custom handler in my previous post, but say, you are having a use case which will mix up you to get a decision such as “should i achieve this by writing custom handler? Or should i write a custom mediator instead of handler?”  for getting a decision in a such situations hope this post will helps you...


One main difference between a class mediator and a handler is that handlers are executed in both request flow and response flow, and you can write 2 logics for those 2 cases in the same handler. But a class mediator has only a single section (i.e. mediate() method). When you engage a class mediator in a sequence, you can decide if you want to put it in request flow or response flow, or in both.
If your logic is not complex, you can use existing mediators instead of writing a class mediator. In that case, you don't need to write any java code.
Existing handlers are executed first in the request flow. Mediation sequences are executed after that. But if you write a custom handler, you can put it after mediation sequences as well, because mediation sequences are also executed by a handler (APIManagerExtensionHandler). So if you place your handler after APIManagerExtensionHandler(which you can find in <APIM HOME>/repository/deployment/server/synapse-configs/default/api/apiconfiguration file), it will execute after mediation sequences.(figure 1.0)

Figure 1.0

The most important point is both mediation sequences and handlers are code extensions that run after the gateway receives a response or request.

According to my findings, here are the primary differences between handlers and mediation sequences. Using one over the other should be determined by your specific requirements.

Custom Handlers


  • Are strictly "per-API," though they can be added to each API via inclusion in the velocity-template.xml file.
  • Can be executed in any order with respect to other handlers.
  • Do not require sequences in addition to the inclusion of the handler within the API definition sequence. All of the tasks must be contained in Java code.
  • Handlers extend the org.apache.synapse.rest.AbstractHandler class,requiring implementation of AbstractHandler.handleRequest and AbstractHandler.handleResponse

Mediation Sequences


  • Can be configured to be global or API specific.
  • Can be executed in any order with respect to other mediation sequences, but cannot mediate before other handlers unless all other mediators also do so (unless you write a custom mediation handler).
  • Allow you to invoke other predefined mediators within an XML tree to describe the mediation tasks. Unless the predefined mediators (provided by WSO2) do not satisfy your requirements, you won't have to write any custom code.
  • Mediators extend org.apache.synapse.mediators.AbstractMediator class and require implementing AbstractMediator.mediate

Further reading links

what i have written above just scratches the surface. I am by no means an expert on this and am keen to learn from your experience  

Saturday, October 22, 2016

SOAP and REST

SOAP and REST as a web service 

One of my friend asked me a question today "why would anyone choose SOAP(Simple Object Access Protocol) instead REST(Representative State Transfer)"? i thought about it for a minute and honestly answered that i haven't ever come a cross a reason. while i feel unsatisfied about my knowledge on web services i did some homework and here's my summery on rest vs soap 


Overview

REST(Representative State Transfer) 


REST is web standards based architecture and uses HTTP Protocol for data communication. REST Server simply provides access to resources and REST client accesses and presents the resources. It is more like a browser. It's a generic client that knows how to use a protocol and standardized methods, and an application has to fit inside that. You don't violate the protocol standards by creating extra methods, you leverage on the standard methods and create the actions with them on your media type. If done right, there's less coupling(less degree of inter dependence each other), and changes can be dealt with more gracefully. A client is supposed to enter a REST service with zero knowledge of the API, except for the entry point and the media type.

I think following points will help you out to understand more about REST and how it differs from SOAP

  • REST is protocol independent. actually REST is an architectural style not a protocol, It's not coupled to HTTP. Pretty much like you can follow an ftp link on a website, a REST application can use any protocol for which there is an standardized URI scheme.
  • RESTful Web Services are fast because there is no strict specification like SOAP. It consumes less bandwidth and resource.
  • REST concepts are referred to as resources. A representation of a resource must be stateless. It is represented via some media type. Some examples of media types include XML, JSON, and RDF. Resources are manipulated by components. Components request and manipulate resources via a standard uniform interface. In the case of HTTP, this interface consists of standard HTTP ops e.g. GET, PUT, POST, DELETE.


SOAP(Simple Access Object protocol)

SOAP is a XML-based protocol for accessing web service.It specifies exactly how to encode an HTTP header and an XML file so that a program in one computer can call a program in another computer and pass along information. SOAP also specifies how the called program can return a response. Despite its frequent pairing with HTTP, SOAP supports other transport protocols as well.

  • SOAP messages are encrypted and digitally signed at the message level, SSL works at the transport level. SSL is prone to hacking because it uses Asymmetric Encryption (public and private keys). SOAP uses Symmetric encryption that is much more difficult to break. SOAP requires XML because it is digitally signed and encrypted.
  • SOAP requires more bandwidth and resource than REST.
  • SOAP is typically much slower than other types of middleware standards, including CORBA. This due to the fact that SOAP uses a verbose XML format. You need to fully understand the performance limitations before building applications around SOAP.
  • SOAP has different levels of support, depending upon the programming language supported. For example, SOAP support within Python and PHP is not as strong as it is within Java and .NET.


Friday, September 16, 2016

Writing Custom Handler..

How to write custom handler for API Manager 1.10.0  from the scratch 


Users need to provide OAuth2 bearer token to invoke APIs under an application. Its the default authentication mechanism provided by WSO2 API Manager. But we can extend it to support any of the authentication mechanism other than the bearer token authentication.

In this post i'm going to explain  how you can write a custom handler and How to apply it to the API Manager 1.10.0

First we need to create a new maven project from java IDE. For this article i am using eclipse since it is my favorite IDE.
  • Open eclipse and create new project and choose new maven project in wizard, you can give any artifactId and groupId as you prefer.

  • For my project i'm giving Artifact Id and group Id as following for this as i mentioned above  you can give any name  




  • We can write our own authentication handler class by extending 'org.apache.synapse.rest.AbstractHandler' class

 package com.wso2.CustomHeader.CustomeHandler;  
 import org.apache.synapse.MessageContext;  
 import org.apache.synapse.core.axis2.Axis2MessageContext;  
 import org.apache.synapse.rest.AbstractHandler;  
 import java.util.Map;  
 public class CustomAPIAuthenticationHandler extends AbstractHandler{  
  public boolean handleRequest(MessageContext messageContext) {  
     try {  
       if (authenticate(messageContext)) {  
         return true;  
       }  
     } catch (Exception e) {  
       e.printStackTrace();  
     }  
     return false;  
   }  
   public boolean handleResponse(MessageContext messageContext) {  
     return true;   
   }  
   public boolean authenticate(MessageContext synCtx) {  
     Map headers = getTransportHeaders(synCtx);  
     String authHeader = getAuthorizationHeader(headers);  
     if (authHeader.startsWith("userName")) {  
       return true;  
     }  
     return false;  
   }  
   private String getAuthorizationHeader(Map headers) {  
     return (String) headers.get("Authorization");  
   }  
   private Map getTransportHeaders(MessageContext messageContext) {  
     return (Map) ((Axis2MessageContext) messageContext).getAxis2MessageContext().  
         getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);  
   }  
 }  

  • Here i attached my working .pom file

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>com.wso2.CustomHeader</groupId>  
  <artifactId>CustomeHandler</artifactId>  
  <version>0.0.1-SNAPSHOT</version>  
  <packaging>jar</packaging>  
  <repositories>  
     <repository>  
       <id>wso2-nexus</id>  
       <name>WSO2 internal Repository</name>  
       <url>  
         http://maven.wso2.org/nexus/content/groups/wso2-public/  
       </url>  
       <releases>  
         <enabled>true</enabled>  
         <updatePolicy>daily</updatePolicy>  
         <checksumPolicy>fail</checksumPolicy>  
       </releases>  
     </repository>  
   </repositories>  
  <name>CustomeHandler</name>  
  <url>http://maven.apache.org</url>  
  <dependencies>  
   <dependency>  
    <groupId>junit</groupId>  
    <artifactId>junit</artifactId>  
    <version>3.8.1</version>  
    <scope>test</scope>  
   </dependency>  
   <dependency>  
       <groupId>org.wso2.carbon</groupId>  
       <artifactId>org.wso2.carbon.core</artifactId>  
       <version>4.4.3</version>  
     </dependency>  
     <dependency>  
       <groupId>org.apache.synapse</groupId>  
       <artifactId>synapse-core</artifactId>  
       <version>${synapse.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.wso2.carbon.mediation</groupId>  
       <artifactId>org.wso2.carbon.mediation.registry</artifactId>  
       <version>${carbon.mediation.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>com.googlecode.json-simple.wso2</groupId>  
       <artifactId>json-simple</artifactId>  
       <version>${googlecode.json-simple.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.wso2.carbon.apimgt</groupId>  
       <artifactId>org.wso2.carbon.apimgt.impl</artifactId>  
       <version>${api.mgt.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>io.swagger</groupId>  
       <artifactId>swagger-parser</artifactId>  
       <version>${swagger.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.wso2.carbon</groupId>  
       <artifactId>org.wso2.carbon.logging</artifactId>  
       <version>4.4.3</version>  
     </dependency>  
     <dependency>  
       <groupId>com.fasterxml.jackson.core</groupId>  
       <artifactId>jackson-annotations</artifactId>  
       <version>2.7.2</version>  
     </dependency>  
     <dependency>  
       <groupId>com.fasterxml.jackson.core</groupId>  
       <artifactId>jackson-core</artifactId>  
       <version>2.7.2</version>  
     </dependency>  
     <dependency>  
       <groupId>com.fasterxml.jackson.core</groupId>  
       <artifactId>jackson-databind</artifactId>  
       <version>2.7.2</version>  
     </dependency>  
  </dependencies>  
  <properties>  
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
   <!-- Misc Versions -->  
     <synapse.version>2.1.5-wso2v2</synapse.version>  
     <carbon.mediation.version>4.5.1</carbon.mediation.version>  
     <swagger.version>1.0.17</swagger.version>  
     <api.mgt.version>5.0.3</api.mgt.version>  
     <googlecode.json-simple.version>1.1.wso2v1</googlecode.json-simple.version>  
     <javax.xml.stream.imp.pkg.version>[1.0.1, 1.1.0)</javax.xml.stream.imp.pkg.version>  
     <axis2.osgi.version.range>[1.6.1.wso2v11, 1.7.0)</axis2.osgi.version.range>  
     <axiom.osgi.version.range>[1.2.11.wso2v6, 1.3.0)</axiom.osgi.version.range>  
     <carbon.platform.package.import.version.range>[4.4.1, 4.5.0)  
     </carbon.platform.package.import.version.range>  
     <carbon.registry.imp.pkg.version>[1.0.1, 2.0.0)</carbon.registry.imp.pkg.version>  
     <carbon.apimgt.imp.pkg.version>[5.0.0, 6.0.0)</carbon.apimgt.imp.pkg.version>  
     <javax.xml.soap.imp.pkg.version>[1.0.0, 1.1.0)</javax.xml.soap.imp.pkg.version>  
     <imp.pkg.version.axis2>[1.6.1.wso2v14, 1.7.0)</imp.pkg.version.axis2>  
     <imp.pkg.version.carbon.throttle>[4.2.1, 4.3.0)</imp.pkg.version.carbon.throttle>  
     <imp.pkg.version.carbon.base>[1.0.0, 1.1.0)</imp.pkg.version.carbon.base>  
     <carbon.mediation.imp.pkg.version>[4.0.0, 5.0.0)</carbon.mediation.imp.pkg.version>  
     <imp.pkg.version.org.wso2.carbon.base>[1.0.0, 1.1.0)</imp.pkg.version.org.wso2.carbon.base>  
     <imp.pkg.version.org.wso2.carbon.user.api>[1.0.1, 1.2.0)  
     </imp.pkg.version.org.wso2.carbon.user.api>  
     <imp.pkg.version.axiom>[1.2.11.wso2v6, 1.3.0)</imp.pkg.version.axiom>  
     <carbon.identity.imp.pkg.version>[5.0.0, 6.0.0)</carbon.identity.imp.pkg.version>  
  </properties>  
   <build>  
     <plugins>  
       <plugin>  
         <groupId>org.apache.maven.plugins</groupId>  
         <artifactId>maven-compiler-plugin</artifactId>  
         <version>2.0</version>  
         <configuration>  
           <encoding>UTF-8</encoding>  
           <source>1.7</source>  
           <target>1.7</target>  
         </configuration>  
       </plugin>  
       <!--  <plugin>  
           <groupId>org.apache.axis2</groupId>  
           <artifactId>axis2-java2wsdl-maven-plugin</artifactId>  
           <executions>  
             <execution>  
               <goals>  
                 <goal>java2wsdl</goal>  
               </goals>  
             </execution>  
           </executions>  
           <configuration>  
             <className>  
               org.wso2.carbon.apimgt.gateway.service.APIGatewayAdmin  
             </className>  
           </configuration>  
         </plugin>-->  
       <plugin>  
         <groupId>org.apache.felix</groupId>  
         <artifactId>maven-scr-plugin</artifactId>  
         <version>1.7.2</version>  
         <executions>  
           <execution>  
             <id>generate-scr-scrdescriptor</id>  
             <goals>  
               <goal>scr</goal>  
             </goals>  
           </execution>  
         </executions>  
       </plugin>  
       <plugin>  
         <groupId>org.apache.felix</groupId>  
         <artifactId>maven-bundle-plugin</artifactId>  
         <version>1.4.0</version>  
         <extensions>true</extensions>  
         <configuration>  
           <instructions>  
             <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>  
             <Bundle-Name>${project.artifactId}</Bundle-Name>  
             <Private-Package></Private-Package>  
             <Export-Package>  
               com.wso2.header.handler.*;version="${project.version}"  
             </Export-Package>  
             <Import-Package>  
               !com.wso2.header.handler.*;version="${project.version}",  
               javax.cache,  
               javax.naming,  
               javax.sql,  
               javax.xml.*;version="0.0.0",  
               org.slf4j,  
               org.w3c.dom,  
               org.xml.sax,  
               org.wso2.carbon.apimgt.api.*;version="${carbon.apimgt.imp.pkg.version}",  
               org.wso2.carbon.apimgt.api.model.xsd;version="${carbon.apimgt.imp.pkg.version}",  
               org.eclipse.equinox.http.helper,  
               com.google.gson,  
               org.apache.axis2.*; version="${imp.pkg.version.axis2}",  
               org.apache.commons.*,  
               org.apache.synapse.*,  
               org.osgi.service.*,  
               org.apache.commons.logging,  
               org.apache.axiom.*; version="${imp.pkg.version.axiom}",  
               org.wso2.carbon.utils;  
               version="${carbon.platform.package.import.version.range}",  
               org.wso2.carbon.registry.core.*;  
               version="${carbon.registry.imp.pkg.version}",  
               org.wso2.carbon.utils.*;  
               version="${carbon.platform.package.import.version.range}",  
               org.wso2.carbon.context;version="${carbon.platform.package.import.version.range}",  
               org.wso2.carbon.user.core.*;version="${carbon.platform.package.import.version.range}",  
               org.wso2.carbon.user.api;version="${imp.pkg.version.org.wso2.carbon.user.api}",  
               org.wso2.carbon.um.ws.api.stub,  
               org.wso2.carbon.registry.*;version="${carbon.registry.imp.pkg.version}",  
               org.apache.axis2.rpc.receivers; version="${axis2.osgi.version.range}",  
               org.apache.axiom.*; version="${axiom.osgi.version.range}",  
               org.apache.axis2; version="${axis2.osgi.version.range}",  
               org.apache.axis2.description; version="${axis2.osgi.version.range}",  
               org.apache.axis2.engine; version="${axis2.osgi.version.range}",  
               org.apache.axis2.rpc.receivers; version="${axis2.osgi.version.range}",  
               org.apache.axis2.context; version="${axis2.osgi.version.range}",  
               org.apache.axis2.transport.base,  
               org.wso2.carbon.core;  
               version="${carbon.platform.package.import.version.range}",  
               org.wso2.carbon.registry.core.service;  
               version="${carbon.registry.imp.pkg.version}",  
               org.wso2.carbon.registry.api;  
               version="${carbon.registry.imp.pkg.version}",  
               org.wso2.carbon.apimgt.impl.*;  
               version="${carbon.apimgt.imp.pkg.version}",  
               javax.xml.soap; version="${javax.xml.soap.imp.pkg.version}",  
               org.wso2.carbon.apimgt.api.*;  
               version="${carbon.apimgt.imp.pkg.version}",  
               org.apache.axis2.*; version="${imp.pkg.version.axis2}",  
               javax.cache,  
               javax.net.ssl,  
               javax.xml.namespace,  
               org.apache.commons.*,  
               org.apache.synapse.*,  
               org.wso2.carbon.registry.core.*;  
               version="${carbon.registry.imp.pkg.version}",  
               org.wso2.carbon.utils;  
               version="${carbon.platform.package.import.version.range}",  
               org.osgi.service.component,  
               org.slf4j,  
               org.wso2.carbon.apimgt.keymgt.stub.validator;  
               version="${carbon.apimgt.imp.pkg.version}",  
               org.wso2.carbon.sequences.stub.types,  
               org.wso2.carbon.context,  
               *;resolution:=optional  
             </Import-Package>  
             <DynamicImport-Package>*</DynamicImport-Package>  
           </instructions>  
         </configuration>  
       </plugin>  
     </plugins>  
   </build>  
 </project>  

Build Solution if it is successfully build you can see the .jar file on target folder like following

Then you have to copy this jar file to <AM_HOME>/repository/components/lib  folder where <AM_HOME> is the root of the WSO2 API Manager distribution

You have to put the Jars correspond to external dependencies into classpath in order to make them available in the OSGI repository. For that you can copy those to libs directory.

Following articles will show you how to add external jar libraries to wso2 carbon based products[1],[2].

[2]Adding External Libraries


Engaging the custom handler


You can engage a custom handler to all APIs at once or only to selected APIs.
here i used first method engage custom handler to all APIs, so to do this we have to add following modification to velocity_template.xml file which is located on following path  <APIM_HOME>/repository/resources/api_templates/velocity_template.xml 

 <handlers>  
    <!-- <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler">  
      <property name="inline" value="INLINE"/>  
    </handler> -->  
   <handler class="com.wso2.CustomHeader.CustomeHandler.CustomAPIAuthenticationHandler" />  
     #foreach($handler in $handlers)  
      #if(!($handler.className == "com.wso2.CustomHeader.CustomeHandler.CustomAPIAuthenticationHandler"))  
       <handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">  
       #if($handler.hasProperties())  
         #set ($map = $handler.getProperties() )  
         #foreach($property in $map.entrySet())  
           <property name="$!property.key" value="$!property.value"/>  
         #end  
       #end  
       </handler>  
      #end  
     #end  
 </handlers>  
However, please note that these changes to velocity_template.xml won't have an effect on already published APIs. So your custom authentication handler will not be engaged in already published APIs, unless you republish them. To engage it with already published APIs, you need to republish those APIs.
  • Login to publisher
  • Select your API and click on Lifecycle tab
  • Change the State to CREATED and click Update
  • Again change the State to PUBLISHED and click Update

Please find sample code here...

Thanks