Wednesday, November 9, 2016

Use Case – Salesforce REST Connector + Google Spread Sheet connector

The below section describes the Google Spreadsheet connector use case by integrating the spreadsheet connector with the Salesforce REST Connector. For example you can use the Salesforce REST Connector to get the account details (Eg :- Id, Name of the records in your organization) from Salesforce and add that account details into Google Spreadsheet using Google Spreadsheet connector.


Overview

The following diagram illustrates the use case for the Google Spreadsheet connector.
  1. Get the account details from the Salesforce using query operation.
  2. Add the account details into the Spreadsheet using the addRowsColumnsData  operation.

Environment setup for running the Google Spread Sheet use cases

  • Download ESB 5.0.0 from here.
  • Upload the following connectors to the ESB:
  • Follow the instructions given in the developer guide of the above connectors.
  •  Import the certificate into the ESB client keystore to use the Salesforce REST connector.Refer this link to import the certificate.  
  • Creating the credentials to use the Google Spreadsheet connector:
 Creating a Client ID and Client Secret
      1. As the email sender, navigate to the URL  https://console.developers.google.com/projectselector/apis/credentials  and log in to your google account.
      2. If you do not already have a project, create a new project and navigate to Create Credential -> OAuth client ID.
      3. At this point, if the consent screen name is not provided, you will be prompted to do so.
      4. Select the Web Application option and create a client. Provide  https://developers.google.com/oauthplayground  as the redirect URL under Authorized redirect URIs and click on Create. The client ID and client secret will then be displayed.
      5. See Google Spreadsheet API documentation for details on creating the Client ID and Client Secret.
      6. Click on the Library on the side menu, and select Google Sheets API. Click enable.
Obtaining the Access Token and Refresh Token 
Follow these steps to automatically refresh the expired token when connecting to Google API:
  1. Navigate to the URL  https://developers.google.com/oauthplayground and click on the gear wheel at the top right corner of the screen and select the option Use your own OAuth credentials. Provide the client ID and client secret you previously created and click on Close.
  2. Now under Step 1, select Google Sheets API v4 from the list of APIs and check all the scopes listed down and click on Authorize APIs. You will then be prompted to allow permission, click on Allow.
  3.  In Step 2, click on Exchange authorization code for tokens to generate and display the access token and refresh token. 

Sample configuration


Following is a sample proxy service that illustrates how to test the above scenario.


 <?xml version="1.0" encoding="UTF-8"?>  
 <proxy xmlns="http://ws.apache.org/ns/synapse"  
     name="ImportDatatoSpreadsheet"  
     startOnLoad="true"  
     statistics="disable"  
     trace="disable"  
     transports="http,https">  
   <target>  
    <inSequence>  
      <property expression="json-eval($.salesforceRESTHostName)"  
           name="salesforceREST.hostName"/>  
      <property expression="json-eval($.salesforceRESTRefreshToken)"  
           name="salesforceREST.refreshToken"/>  
      <property expression="json-eval($.salesforceRESTClientSecret)"  
           name="salesforceREST.clientSecret"/>  
      <property expression="json-eval($.salesforceRESTClientId)"  
           name="salesforceREST.clientId"/>  
      <property expression="json-eval($.salesforceRESTAccessToken)"  
           name="salesforceREST.accessToken"/>  
      <property expression="json-eval($.salesforceRESTQueryString)"  
           name="salesforceREST.queryString"/>  
      <property expression="json-eval($.salesforceRESTApiVersion)"  
           name="salesforceREST.apiVersion"/>  
      <property expression="json-eval($.salesforceRESTApiUrl)"  
           name="salesforceREST.apiUrl"/>  
      <property expression="json-eval($.salesforceRESTIntervalTime)"  
           name="salesforceREST.intervalTime"/>  
      <property expression="json-eval($.salesforceRESTRegistryPath)"  
           name="salesforceREST.registryPath"/>  
      <property expression="json-eval($.googlespreadsheetAccessToken)"  
           name="googlespreadsheet.accessToken"/>  
      <property expression="json-eval($.googlespreadsheetRefreshToken)"  
           name="googlespreadsheet.refreshToken"/>  
      <property expression="json-eval($.googlespreadsheetClientId)"  
           name="googlespreadsheet.clientId"/>  
      <property expression="json-eval($.googlespreadsheetClientSecret)"  
           name="googlespreadsheet.clientSecret"/>  
      <property expression="json-eval($.googlespreadsheetApiUrl)"  
           name="googlespreadsheet.apiUrl"/>  
      <property expression="json-eval($.spreadsheetId)"  
           name="googlespreadsheet.spreadsheetId"/>  
      <property expression="json-eval($.range)" name="googlespreadsheet.range"/>  
      <property expression="json-eval($.valueInputOption)"  
           name="googlespreadsheet.valueInputOption"/>  
      <property name="fields" scope="operation" value="["/>  
      <property name="length" scope="operation" value=""/>  
      <salesforcerest.init>  
       <apiVersion>{$ctx:salesforceREST.apiVersion}</apiVersion>  
       <hostName>{$ctx:salesforceREST.hostName}</hostName>  
       <accessToken>{$ctx:salesforceREST.accessToken}</accessToken>  
       <refreshToken>{$ctx:salesforceREST.refreshToken}</refreshToken>  
       <clientSecret>{$ctx:salesforceREST.clientSecret}</clientSecret>  
       <clientId>{$ctx:salesforceREST.clientId}</clientId>  
       <apiUrl>{$ctx:salesforceREST.apiUrl}</apiUrl>  
       <intervalTime>{$ctx:salesforceREST.intervalTime}</intervalTime>  
       <registryPath>{$ctx:salesforceREST.registryPath}</registryPath>  
      </salesforcerest.init>  
      <salesforcerest.query>  
       <queryString>{$ctx:salesforceREST.queryString}</queryString>  
      </salesforcerest.query>  
      <property expression="//records" name="records"/>  
      <iterate continueParent="true" description="" expression="//records" id="records_iterator" sequential="true">  
       <target>  
         <sequence>  
          <property expression="json-eval($.records)" name="records"/>  
          <property expression="get-property('operation','fields')" name="fields"/>  
          <script language="js">  
               var records = mc.getProperty("records");                
               var obj = eval ("(" + records + ")");  
               var ans;  
               var fields = mc.getProperty("fields");  
               fields = fields.concat("[");               
               var Id = obj['Id'];  
               var Name = obj['Name'];  
               if(Id !="" &amp;&amp; Id !=null &amp;&amp; Name !="" &amp;&amp; Name !=null){  
                   fields = fields.concat('"' + Id + '","' + Name + '"');  
               }  
               fields = fields.concat("],");  
               mc.setProperty("fields",fields);  
               mc.setProperty("length",fields.length());  
          </script>  
          <property expression="get-property('fields')" name="fields" scope="operation"/>  
          <property expression="get-property('length')" name="length" scope="operation"/>  
         </sequence>  
       </target>  
      </iterate>  
      <property expression="get-property('operation','fields')" name="fields" scope="operation"/>  
      <property expression="get-property('operation','length')" name="length" scope="operation"/>  
      <property expression="fn:concat(fn:substring(get-property('operation','fields'),0,get-property('operation','length')),']')" name="values"/>  
      <googlespreadsheet.init>  
       <accessToken>{$ctx:googlespreadsheet.accessToken}</accessToken>  
       <refreshToken>{$ctx:googlespreadsheet.refreshToken}</refreshToken>  
       <clientId>{$ctx:googlespreadsheet.clientId}</clientId>  
       <clientSecret>{$ctx:googlespreadsheet.clientSecret}</clientSecret>  
       <apiUrl>{$ctx:googlespreadsheet.apiUrl}</apiUrl>  
      </googlespreadsheet.init>  
      <googlespreadsheet.addRowsColumnsData>  
       <spreadsheetId>{$ctx:googlespreadsheet.spreadsheetId}</spreadsheetId>  
       <range>{$ctx:googlespreadsheet.range}</range>  
       <valueInputOption>{$ctx:googlespreadsheet.valueInputOption}</valueInputOption>  
       <values>{$ctx:values}</values>  
      </googlespreadsheet.addRowsColumnsData>  
      <property expression="$axis2:HTTP_SC" name="addRowsColumnsDataStatusCode"/>  
      <filter regex="true"  
          source="get-property('addRowsColumnsDataStatusCode') != 200">  
       <then>  
         <log level="full"/>  
         <property name="message" value="Unable to Insert the row "/>  
         <loopback/>  
       </then>  
       <else>  
         <log level="full"/>  
         <property name="message" value="Success: Successfully Import the Data"/>  
         <loopback/>  
       </else>  
      </filter>  
      <respond/>  
      <send/>  
    </inSequence>  
    <outSequence>  
      <property name="messageType" scope="axis2" value="application/json"/>  
      <payloadFactory media-type="json">  
       <format>  
           {  
           "Response":{  
           "process":"ImportDataIntoSpreadsheet",  
           "activityResponse":"$1"  
           }  
           }  
         </format>  
       <args>  
         <arg evaluator="xml" expression="get-property('message')"/>  
       </args>  
      </payloadFactory>  
      <log/>  
      <send/>  
    </outSequence>  
   </target>  
   <description/>  
 </proxy>

Sample request


{   
   "googlespreadsheetAccessToken": "ya29.Ci-PA9JhMsGT5GL_wsbnI8pkoEkLja16d4ms1ugiobKGIC7dqAi9BCnL8JOd6uicUg",   
   "googlespreadsheetRefreshToken": "1/x4NQS273s3ISPcaTWJYz30nkyB-Qi_atiy4x7GupjMg",   
   "googlespreadsheetClientId": "219479486681-r9j113m7nan5nbf955if8e4are9o7mtj.apps.googleusercontent.com",   
   "googlespreadsheetClientSecret": "CArehV1yFnZi2J-9UNGuW9TE",   
   "googlespreadsheetApiUrl": "https://sheets.googleapis.com/v4/spreadsheets",   
   "spreadsheetId": "14PJALKcIXLr75rJWXlHhVjOt7z0Nby7AvcKXJGhMN2s",   
   "range":"Expenses!A1",   
   "valueInputOption":"RAW",   
   "salesforceRESTHostName": "https://login.salesforce.com",   
   "salesforceRESTRefreshToken": "5Aep861TSESvWeug_xCxj8yFaTjeV0kXa8X.gg5d1ipArZn7qCfwD9IORz9LedLqQ.HtkAr8fzUCzKKFlswxA_z",   
   "salesforceRESTClientSecret": "3543063387981089204",   
   "salesforceRESTClientId": "3MVG9ZL0ppGP5UrDt0n2ptTJ_fWBXDlYYXTic9.ApotX3azPQhMX2dw_gXGQ1JyPwTLWjrnCB.0K3vpUJV3Jv",   
   "salesforceRESTAccessToken": "00D28000000avoo!ARoAQI4rBfsxeB8OLh97Ebje7Ry0DpFXbP1wWyYUKuEWTrU70lzL2zOYXopgq6YB_ZgZz.JrSaVCC2b39mGSOTR7XZGiwCVe",   
   "salesforceRESTQueryString": "select id, name from Account limit 3",   
   "salesforceRESTApiVersion": "v32.0",   
   "salesforceRESTApiUrl": "https://ap2.salesforce.com",   
   "salesforceRESTIntervalTime": "2400000",   
   "salesforceRESTRegistryPath": "connectors/salesforcerest"   
  }

Thursday, July 14, 2016

SMPP Connector


SMPP Connector allows you to send SMS through the WSO2 ESB. It uses jsmpp API to communicate with a SMSC. jsmpp is a java implementation of SMPP protocol. 


How to send SMS using SMPP

SMPP client communicates with SMPP server by SMPP protocol, which is a native way for sending SMS. SMPP client must take care of SMS and deliver them to server. When there is a change of status for an SMS, then SMPP server will transmit a delivery report back to client. So, we don't have to care about making extra actions to retrieve the delivery report for a message. SMPP protocol will take care of that.




SMPP (Short Message Peer-to-Peer)

What is SMPP ?


The Short Message Peer-to-Peer (SMPP) is a protocol used by the telecommunications industry for exchanging SMS messages between Short Message Service Centers (SMSC) and/or External Short Messaging Entities (ESME). SMPP is able to carry short messages including EMS, Voice Mail notifications, Cell Broadcasts, WAP messages including WAP Push messages (used to deliver MMS notifications), USSD messages and others. Because of its versatility and support for non-GSM SMS protocols, like UMTS, IS-95 (CDMA), CDMA2000, ANSI-136 (TDMA) and iDEN, the SMPP is the most commonly used protocol for short message exchange outside SS7 networks.

What is SMSC ?


A Short Message service center (SMSC) is a network element in the mobile telephone network. Its purpose is to store, forward, convert and deliverShort Message Service (SMS) messages.

When an SMS message is sent from a mobile phone, it will reach an SMSC first. Then it forwards the SMS message towards the destination. Here, SMSC is to route SMS messages and regulate the process. If the recipient is unavailable, the SMSC will store the SMS message and forward the SMS message when the recipient is available until the message's expiry period. It is possible on most mobile handset to specify an expiry period of SMS message after which the SMS message will be deleted from the SMSC. Once deleted, the SMS message will not be available for dispatch to the recipient mobile phone. The validity period should be regarded by the handset user as a request, as the SMSC itself can be configured to ignore or otherwise handle message delivery schedules. To get the status report of the message, SMS sender needs to set a flag in the SMS message to notify the SMSC that he wants the status report about the delivery of this SMS message. This status report is sent to the SMS sender via an SMS.

What is ESME ?

External Short Messaging Entity (ESME) is an external application that connects to a Short Message Service Center (SMSC) to sending and/or receiving of SMS messages.
SME is a term used to describe a network entity (mobile/cell phone) that can send/receive messages. ESME is essentially one of these but without all the wireless aspects. Eg: it is connected via TCP/IP, X.25 or similar. 

Sunday, May 22, 2016

Create a Class mediator and Use it in the sequences of the sample proxy

Step 1: Creating Class mediator
First create maven project called org.example.mediator using eclipse. The add the following dependencies in the pom.xml.

 <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>org.wso2.biruntha</groupId> 

  <artifactId>org.example.mediator</artifactId> 

  <version>0.0.1-SNAPSHOT</version> 

  <packaging>jar</packaging> 

  <name>org.example.mediator</name> 

  <url>http://maven.apache.org</url> 

  <properties> 

   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 

  </properties> 

  <repositories> 

     <repository> 

       <id>wso2-maven2-repository</id> 

       <url>http://dist.wso2.org/maven2</url> 

     </repository> 

     <repository> 

       <id>apache-Incubating-repo</id> 

       <name>Maven Incubating Repository</name> 

       <url>http://people.apache.org/repo/m2-incubating-repository</url> 

     </repository> 

     <repository> 

       <id>apache-maven2-repo</id> 

       <name>Apache Maven2 Repository</name> 

       <url>http://repo1.maven.org/maven2/</url> 

     </repository> 

   </repositories> 

   <build> 

     <plugins> 

       <plugin> 

         <groupId>org.apache.maven.plugins</groupId> 

         <artifactId>maven-compiler-plugin</artifactId> 

         <version>2.0</version> 

         <configuration> 

           <source>1.5</source> 

           <target>1.5</target> 

         </configuration> 

       </plugin> 

     </plugins> 

   </build> 

   <dependencies> 

        <dependency> 

         <groupId>junit</groupId> 

         <artifactId>junit</artifactId> 

         <version>3.8.1</version> 

         <scope>test</scope> 

        </dependency> 

     <dependency> 

       <groupId>org.apache.synapse</groupId> 

       <artifactId>synapse-core</artifactId> 

       <version>2.1.1-wso2v7</version> 

     </dependency> 

   </dependencies> 

 </project> 


Then to build the package use mvn clean install Step 2: Create class mediator create class mediator called MyMediator that extends AbstractMediator.

 package org.example.mediator; 

 import org.apache.synapse.MessageContext; 

 import org.apache.synapse.Mediator; 

 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.SOAPBody; 

 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 MyMediator extends AbstractMediator { 

   private static final Log log = LogFactory.getLog(MyMediator.class); 

   public MyMediator(){} 

   public boolean mediate(MessageContext mc) { 

     //get the SOAP body from message context 

    SOAPBody soapBody = mc.getEnvelope().getBody(); 

     //now you can modify the SOAP body as you wish 

     //... 

     return true; 

   } 

   public String getType() { 

     return null; 

   } 

   public void setTraceState(int traceState) { 

     this.traceState = traceState; 

   } 

   public int getTraceState() { 

     return 0; 

   } 

 } 


again run "mvn clean install" this will create org.example.mediator-0.0.1-SNAPSHOT.jar in the target folder.

copy that paste into wso2esb-4.9.0/repository/components/lin folder.

Then Run the ESB server.

cd wso2esb-4.9.0/samples/axis2Server/src/SimpleStockQuoteService
Run ant

cd wso2esb-4.9.0/samples/axis2Client ant stockquote -Dtrpurl=http://localhost:8280/services/StockQuoteProxy -Dmode=quote -Dsymbol=IBM

this will return stock price...

Step3 : Create proxy Service Follow [1] this to Create proxy service as below. And In the in sequence of the proxy add the class mediator we created already. After all of this the proxy will be like below.

 <?xml version="1.0" encoding="UTF-8"?> 

 <proxy xmlns="http://ws.apache.org/ns/synapse" 

     name="StockQuoteProxy" 

     transports="http,https,local" 

     statistics="enable" 

     trace="disable" 

     startOnLoad="true"> 

   <target> 

    <inSequence> 

      <class name="org.example.mediator.MyMediator"/> 

    </inSequence> 

    <outSequence> 

      <send/> 

    </outSequence> 

    <endpoint> 

      <address uri="http://localhost:9000/services/SimpleStockQuoteService"/> 

    </endpoint> 

   </target> 

   <publishWSDL uri="file:./repository/samples/resources/proxy/sample_proxy_1.wsdl"/> 

   <description/> 

 </proxy> 



Run again ant stockquote -Dtrpurl=http://localhost:8280/services/StockQuoteProxy -Dmode=quote -Dsymbol=IBM

this will return stock price...

Friday, May 20, 2016

WSO2 Jaggery Application

I create simple Jaggery Application [1] which has the facility to show customer details and add customer details. For that i follow this [2].


[1] - https://github.com/Biruntha/Simple-Jaggery-Application
[2] - http://blog.lasindu.com/2014/05/how-to-write-wso2-jaggery-application.html


Creating WSO2 Carbon Component Example (Could not find src/org folder)

When i create the first carbon component, I follow this link [1] that performs two specific tasks. It will allows users to view a menu of food items offered by the O2 restaurant and they can place an order according to their choice. Once the order is placed, a confirmation message will be appeared asking users to proceed with the payment.

When i tried the maven build on org.wso2.carbon.orderprocess.mgt.stub/pom.xml , I got target/generated-code folder but i haven't got the src/org inside the generated-code folder because the format of wsdl file is wrong. Then i Right click on [2] --> view page source --> copy that code and paste in wsdl file.

 Then i have successfully created carbon components.




How to Build WSO2 Carbon

To build WSO2 carbon from source I follow this post [1]. But when i tried to build using this mvn clean install -Dmaven.test.skip=true, I got error like below.

"
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR] 
[ERROR]   The project org.apache.tomcat.wso2:jdbc-pool:${jdbc.pool.version}.wso2v1 (/home/biruntha/Desktop/carbon/orbit/trunk/jdbc-pool/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for org.apache.tomcat.wso2:jdbc-pool:${jdbc.pool.version}.wso2v1: Failure to find org.wso2.carbon:carbon-dependents:pom:4.0.0 in 
https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced and 'parent.relativePath' points at wrong local POM @ line 22, column 13 -> [Help 2]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] 
http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] 
http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException  "

Then Using [2] , i solve this by changing the repository link or by editing jdbc-pool/pom.xml file.




[1] - https://dzone.com/articles/how-build-wso2-carbon-420
[2] - http://mail.wso2.org/mailarchive/dev/2014-July/033978.html 




Build WSO2 ESB from source and remote debugging the source code


We have to debug an application which is not running from it's source code in a IDE. So to do we need this remote debug concept. When it runs it will broadcast debug information via a socket deployed. The IDE running locally will capture those broadcast debug information through that socket and it will do the debug through the source code. From Below image we can understand clearly.
To build, debug WSO2 ESB product i followed this link [1]. But In the middle, After deploying the
SimpleStockQuoteService sample in the axis2server i tried to execute sh axis2server.sh to run the axis2 server. But i got error 

" ls: cannot access '/home/biruntha/Downloads/axis2-1.7.2/../../repository/components/plugins/*.jar': No such file or directory
ls: cannot access '/home/biruntha/Downloads/axis2-1.7.2/../../repository/components/plugins/*.jar': No such file or directory
Using JAVA_HOME: /usr/lib/jvm/jdk1.8.0_91
Using AXIS2 Repository : /home/biruntha/Downloads/axis2-1.7.2/repository
Using AXIS2 Configuration : /home/biruntha/Downloads/axis2-1.7.2/repository/conf/axis2.xml
Error: Could not find or load main class samples.util.SampleAxis2Server "

To solve i follow [2] this by removing the AXIS2_HOME variable,then server started as expected







Sunday, May 15, 2016

Functional Components

Mediators

Basic component of ESB. Other components are build on top of mediators. When a message come to a mediator, it transform that message according to the configuration defined of that mediator and output another the message according to the configuration defined. In mediators some kind of processing will happen.


Sequences (sequence of mediators)

we need several mediators to achieve the requirement so we can have a chain of mediators define as a sequence.

End points

A logical entity to which we are sending the messages from ESB it is actual back end. It can be Http url, JMS end point. There the quality of service parameters can be defined (eg : time out value of end point, retry count).


Proxy services

A virtual service hosted in ESB. A actual entity that client can see. When a client send a message to ESB it will come to one of proxy services (In sequence, out sequence, fault sequence). In sequence is a sequence which receive message from client. After receives, it will execute the mediators defined in that in sequence. After processing the message, it will send to the end point defined in that in sequence. In that, send mediator is used to send message to back end. Then message is routed to the particular service. That server will send a response back to the ESB. Then the response will be retrieve from the out sequence. There response can be send to client or to another service.
If any error occur in back end call then the error will come to the error sequence. Depending on our requirements the fault sequence can be used log the error, ignore it or send a SOAP fault back to the client indicating that something went wrong.


REST API

In here also we have In sequence, out sequence, fault sequence.
Consider a web page with SOAP service, client send request in REST, we can use ESB to transform. Inside ESB REST API will be defined. When client send the message to REST API, the ESB will send SOP message to back end. The response will come as SOAP message then it transform into REST and send it to the client.



ESB Connectors

Connector is used to connect the cloud based APIs(facebook,linkedin,JIRA) with ESB.