This documentation applies to older versions of WSO2 ESB connectors. To find the documentation relevant to the version you are using, select the connector from the WSO2 Connector Store and click Documentation.

All docs This doc
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Implementing a connector for WSO2 ESB can be split into 3 main tasks as explained below.

  1. Research on the APIs provided by the specific third-party company.
  2. Decide on which API you are going to use to write the connector. This can be one of the following.
    • REST-based connectors
    • SOAP-based connectors
    • Java API-based connectors
  3. Start writing the connector by using the connector core available with WSO2 ESB.

The rest of the docment shows how to write connectors using each of those APIs. The following standard folder structure should be followed.

Folder Structure 

1connector.xmlThis defines the connector name and dependant modules. (Metadata of the connector)
2component.xmlThis is included in each module. This defines the available methods in the module.
3init.xmlFor a connector, this is mandatory. By using this, users can initialize the connector environment, e.g. when writing the Salesforce connector login call can be included here. Sessiontoken and API URL returned as the response can be stored in a property and used with other operations.
4assemble-connector.xml/filter.propertiesThese files are used at the build time of the connector. You barely need to modify this file. So, in this article, we will not provide a detailed explanation.
5pom.xmlContains the required dependencies for connector core libraries and relevant synapse libraries as well as maven repositories for a specific connector.
6<operation-name>.xmlThis is the actual API operation calling configuration. It contains the steps necessary to call the API that is exposed by the third party. Similar to init.xml, each method of the API can be written. If there are any Java codes those can be included under Java and relevant dependants needs to be added to pom.xml

Required template can be created using the maven archetype found with following and using the mentioned command. 

https://github.com/wso2/esb-connectors/tree/master/connector-archetype

mvn archetype:generate -DarchetypeGroupId=org.wso2.carbon -DarchetypeArtifactId=org.wso2.carbon.mediation.library.connectors.connector-archetype -DarchetypeVersion=4.4.0 -DgroupId=org.wso2.carbon.connector -DartifactId=org.wso2.carbon.connector -Dversion=1.0.0

Now you have the knowledge about basic structure of a connector. The next sections of the article describes in detail the different types of connectors.

SOAP-based connectors

Since we are writing a connector for SOAP API, we can write the entire connector with Synapse configurations. You can create a maven project from your preferred IDE and the folder structure should be similar to the above.

Following is an example of a SOAP-based connector that is written for Salesforce in order to execute the query method of the API.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<templatename="query"xmlns="http://ws.apache.org/ns/synapse">
 <parametername="sessionId"/>
 <parametername="url"/>
 <parametername="queryString"/>
 <sequence>
  <payloadFactory>
   <format>
     <soapenv:Header>
      <urn:SessionHeader>
       <urn:sessionId>$1</urn:sessionId>
      </urn:SessionHeader>
     </soapenv:Header>
     <soapenv:Body>
      <urn:query>
       <urn:queryString>$2</urn:queryString>
      </urn:query>
     </soapenv:Body>
    </soapenv:Envelope>
   </format>
   <args>
    <argexpression="$func:sessionId"/>
    <argexpression="$func:queryString"/>
   </args>
  </payloadFactory>
  <propertyname="messageType"scope="axis2"value="text/xml"/>
  <headername="Action"value="urn:partner.soap.sforce.com/Soap/queryRequest"/>
  <propertyvalue="true"name="FORCE_ERROR_ON_SOAP_FAULT"/>
  <propertyname="HTTP_METHOD"scope="axis2"value="POST"/>
  <headername="To"expression="$func:url"/>
  <call>
   <endpoint>
    <defaultformat="soap11">
     <timeout>
      <duration>60000</duration>
      <responseAction>fault</responseAction>
     </timeout>
     <suspendOnFailure>
      <initialDuration>2000</initialDuration>
      <progressionFactor>1.0</progressionFactor>
      <maximumDuration>3000</maximumDuration>
     </suspendOnFailure>
    </default>
   </endpoint>
  </call>  
 </sequence>
</template>

 

In the above example, we are creating the required payload using payload factory mediator and we send the request using call mediator.

REST-based connectors

Writing a REST-based connector is no different from writing a SOAP connector. The only difference is the underlying communication mechanism. Other than that, you can basically write a REST-based connector just by using synapse configuration similar to SOAP connectors.

Following is an example of a connector calling Twitter rest API.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<templatexmlns="http://ws.apache.org/ns/synapse"name="search">
 <parametername="search"/>
 <parametername="accessToken"/>
  <sequence>
   <propertyname="uri.var.twitter.search"expression="$func:search"/>
   <propertyname="Authorization"expression="$func:accessToken"scope="transport"/>
   <propertyname="messageType"value="application/x-www-form-urlencoded"scope="axis2"/>
   <payloadFactorymedia-type="xml">
    <format>
      <soapenv:Header/>
      <soapenv:Body/>
     </soapenv:Envelope>
    </format>
    <args/>
   </payloadFactory>
  <call>
   <endpoint>
    <httpmethod="GET"uri-template="https://api.twitter.com/1.1/search/tweets.json?q={uri.var.twitter.search}"/>
   </endpoint>
  </call>
 </sequence>
</template>

 

Java API-based connectors

When you are writing Java API-based connectors, you have to use custom class mediators to implement it. You need to extend the AbstractConnector class and implement its connect method. All the required logic must go within this method. Once you have implemented this method, it can be called using the synapse configuration, which is in the .xml

Following in an example of a connector Java class that is written for Twilio in order to send an SMS.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.util.HashMap;
import java.util.Map;
import org.apache.axiom.om.OMElement;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseException;
import org.apache.synapse.SynapseLog;
import org.wso2.carbon.connector.core.AbstractConnector;
import org.wso2.carbon.connector.core.util.ConnectorUtils;
import org.wso2.carbon.connector.twilio.util.TwilioUtil;
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.resource.factory.SmsFactory;
import com.twilio.sdk.resource.instance.Sms;
public class SendSms extends AbstractConnector {
 public void connect(MessageContext messageContext) {
  SynapseLog log = getLog(messageContext);
  log.auditLog("Start: send SMS");
  String to =  (String) ConnectorUtils.lookupTemplateParamater(messageContext, TwilioUtil.PARAM_TO);
  String from = (String) ConnectorUtils.lookupTemplateParamater(messageContext, TwilioUtil.PARAM_FROM);
  String body = (String) ConnectorUtils.lookupTemplateParamater(messageContext, TwilioUtil.PARAM_BODY);
  String statusCallBackUrl = (String) ConnectorUtils.lookupTemplateParamater(messageContext, TwilioUtil.PARAM_STATUS_CALLBACK_URL);
  String applicationSid = (String) ConnectorUtils.lookupTemplateParamater(messageContext, TwilioUtil.PARAM_APPLICATION_SID);
  Map<string, string=""> params = new HashMap<string, string="">();
  params.put(TwilioUtil.TWILIO_TO, to);
  params.put(TwilioUtil.TWILIO_FROM, from);
  params.put(TwilioUtil.TWILIO_BODY, body);
  if (applicationSid != null) {
   params.put(TwilioUtil.TWILIO_APPLICATION_SID, applicationSid);
  }
  if (statusCallBackUrl != null) {
   params.put(TwilioUtil.TWILIO_STATUS_CALLBACK, statusCallBackUrl);
  }
  try {
   TwilioRestClient twilioRestClient = TwilioUtil.getTwilioRestClient(messageContext);
   SmsFactory messageFactory = twilioRestClient.getAccount().getSmsFactory();
   Sms message = messageFactory.create(params);
   OMElement omResponse = TwilioUtil.parseResponse("sms.create.success");
   TwilioUtil.addElement(omResponse, TwilioUtil.PARAM_MESSAGE_SID, message.getSid());
   TwilioUtil.addElement(omResponse, TwilioUtil.PARAM_STATUS, message.getStatus());
   TwilioUtil.preparePayload(messageContext, omResponse);
  } catch (Exception e) {
   log.error(e.getMessage());
   messageContext.setProperty(SynapseConstants.ERROR_EXCEPTION, e);
   messageContext.setProperty(SynapseConstants.ERROR_MESSAGE, e.getMessage());
   messageContext.setProperty(SynapseConstants.ERROR_CODE, "0007");
   throw new SynapseException(e);
  }
  log.auditLog("End: send SMS");
 }
}
</string,></string,>

 

Following is the associated sendSms.xml that calls the class mediator.

1
2
3
4
5
6
7
8
9
10
<templatename="sendSms"xmlns="http://ws.apache.org/ns/synapse">
 <parametername="body"/>
 <parametername="to"/>
 <parametername="from"/>
 <parametername="statusCallBackUrl"/>
 <parametername="applicationSid"/>
 <sequence>
  <classname="org.wso2.carbon.connector.twilio.sms.SendSms"/>
 </sequence>
</template>

 

So these are the currently available approaches. You should be able to write any connector using one of these approaches.

  • No labels