Monday, 28 April 2014

How to access Salesforce web services

Recently I had to create a web service in Salesforce and expose data to external application.
The first part with creating of web service on Salesforce is quite easy because SF does a good job of converting APEX classes into a web services and this information is explained very well in original SF documentaion. So, it is required to create an APEX class with "webService" keywords and download WSDL file wich can be used for proxy generation.
Here is an example: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_web_services_methods.htm

The tricky part of it is that you need to call this service from, say, C#, and this information is spread among different posts, forum topics etc.

Here is the combined and simplified C# example:


using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;

namespace WSTest
{
    [DataContract]
    internal class AuthToken
    {
        [DataMember]
        internal string id;
        [DataMember]
        internal string issued_at;
        [DataMember]
        internal string instance_url;
        [DataMember]
        internal string signature;
        [DataMember]
        internal string access_token;
    }

    class Program
    {
        private static AuthToken SalesforceAutenticate(string userName, string password)
        {
            // Sandbox URI, for production environment it should be "https://login.salesforce.com/services/oauth2/token"
            const string URI = "https://test.salesforce.com/services/oauth2/token";

            // how to obtained security token: https://success.salesforce.com/answers?id=90630000000glADAAY
            const string securityToken = "1234567890";

            // how to obtain consumer key + secret: http://feedback.uservoice.com/knowledgebase/articles/235661-get-your-key-and-secret-from-salesforce
            const string consumerKey = "XXXXXXXXXXX.YYYYYYYYYYYYYYYYYYYYYYY";
            const string consumerSecret = "0987654321";

            WebRequest req = WebRequest.Create(URI);
            req.Proxy = GetProxy();

            req.ContentType = "application/x-www-form-urlencoded";
            req.Method = "POST";

            String parameters = String.Format("grant_type=password&client_id={0}&client_secret={1}&username={2}&password={3}{4}",
                    consumerKey, consumerSecret, userName, password, securityToken);

            byte[] bytes = Encoding.ASCII.GetBytes(parameters);
            req.ContentLength = bytes.Length;
            Stream os = req.GetRequestStream();
            os.Write(bytes, 0, bytes.Length);
            os.Close();

            WebResponse resp = req.GetResponse();
            if (resp == null)
                return null;

            // parse JSON response
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(AuthToken));
            AuthToken token = (AuthToken)ser.ReadObject(resp.GetResponseStream());

            return token;
        }

        static void Main(string[] args)
        {
            var authToken = SalesforceAutenticate("my@email.dev", "mypassword");

            MyWebServiceService client = new MyWebServiceService();
            client.Proxy = GetProxy();
            client.SessionHeaderValue = new SessionHeader();
            client.SessionHeaderValue.sessionId = authToken.access_token;

            Console.WriteLine(client.SampleMethod("123456"));
        }

        private static IWebProxy GetProxy()
        {
            IWebProxy proxy = new WebProxy("server:port");
            proxy.Credentials = new NetworkCredential("ADname", "ADpassword");
            return proxy;
        }
    }
}

Wednesday, 23 April 2014

Auto-updatable chatter feed in Salesforce

Let’s consider the process of implementation of auto-updatable chatter feed. Even if it looks quite easy this task has two aspects:
1) Auto-updatable controls
2) Creation of custom controllers

In general case auto-refresh of Salesforce visual element can be implemented using this code snippet:

<apex:actionPoller action="{!updateMethod}" reRender="controlToUpdate" interval="15"/>

where:
“updateMethod” is a method of page controller
“controlToUpdate” - id of a component to update
“15” - update interval in seconds

Unfortunately, only custom controllers can have an update method, all standard controllers cannot be extended using ordinary inheritance. So this task may look quite tricky.

Let’s have a look on an example of Account controller. It can be extended using this approach:

public with sharing class Account_Controller {

   public Account_Controller (ApexPages.StandardController stdController) {
       
this.account = (Account)stdController.getRecord();
   
}

   
public Account account { get; private set; }

   
public PageReference updatePage() {
       
return null;
   
}
}

So, it can aggregate the standard controller and extend it with custom functionality.

And in this case the page for the view may look like this:

<apex:page standardController="Account" extensions="Account_Controller">
   
<apex:form >
      
<apex:actionPoller action="{!updatePage}" reRender="chatter" interval="15"/>
   
</apex:form>
   
<chatter:feed id="chatter" entityId="{!account.id}" showpublisher="True"></chatter:feed>
</apex:page>

And now we can see that two tasks are solved: standard controller is extended through adaptor pattern and the view can incorporate an auto-updatable control.

Monday, 24 February 2014

Quick hands-on tutorial of consuming external web services from SalesForce


Recently I had to perform some research of SalesForce in order to reuse some web services on SalesForce application.
Previously I had absolutely no experience of using SalesForce, so many features were unknown for me. But surprisingly the task was not so difficult.
I used freely available web service for my research:
I used this method as an example:
Add external web service URL into “Remote Site Settings” (it is important because no external web services can be used by default):
Download Weather WSDL:
Modify WSDL file: remove multiple parameters (multiple ports, bindings, services sections of WSDL file are not supported by SalesForce Apex classes):
  1. Remove extra port types:
  1. Remove extra bindings:
  1. Remove extra services:
Generate Apex class for WSDL:
Create a new controller:
public class MyController {
   public Map getElements() {
        wsCdyneComWeatherws.WeatherSoap info = new wsCdyneComWeatherws.WeatherSoap();
        info.endpoint_x = 'http://wsf.cdyne.com/WeatherWS/Weather.asmx';
        wsCdyneComWeatherws.ArrayOfWeatherDescription data = info.GetWeatherInformation();
        
        Map ret = new Map();
        
        for (wsCdyneComWeatherws.WeatherDescription item: data.WeatherDescription) {
            ret.put(item.Description, item.PictureURL);
        }
        
        return ret;
    }
}
Create a new page:

<apex:page controller="MyController"> Test page <apex:pageBlock title="Weather icons"> <table> <apex:repeat value="{!elements}" var="item"> <tr> <td>{!item}</td> <td><img src="{!elements[item]}" /></td> </tr> </apex:repeat> </table> </apex:pageBlock> </apex:page>


Now we can test the new page:
It was pretty easy, huh? :)

Sport statistics

I have a strong interest in data analysis and notice some interesting facts from everywhere.
It was a curious thing for me to see how Winter Olympics 2014 medal count correlate with the sponsor investments to the teams and found the following:



So, the most profitable team was from Netherlands and sponsorship (and advertisement) was the most effective for this team.
They just have amazing results and every second athlete in this team has a medal. Very effective team of 41 athlete was built - they received 24 medals in total.
Belorussian team was fantastic in terms of Gold medals.

Sources of information:
http://en.wikipedia.org/wiki/2014_Winter_Olympics
http://www.sochi2014.com/en/medal-standings