Force REST APIs using Scala

This tutorial provides samples on how to use Scala to make REST APIs calls in Force.com.

Reference Source Code : force-rest-scala

Setup

Structure of the Project

src
|   `-- main
|       |-- resources
|       |   |-- application.conf
|       `-- scala
|           |
build.sbt
  1. create a source directory src

  2. Create a build file buid.sbt. Add following content to this file

    name := "ForceSamples"
    version := "1.0"
    scalaVersion := "2.10.4"
    libraryDependencies += "org.apache.httpcomponents" % "httpclient" % "4.5.1"
    libraryDependencies += "org.skife.com.typesafe.config" % "typesafe-config" % "0.3.0"
    libraryDependencies += "com.google.code.gson" % "gson" % "1.7.1"
    
  3. Create directories src/main/resources and src/main/scala under src folder

  4. Create file src/main/resources/application.conf file from util/src/main/resources/application.conf.sample file and fill in the values appropriately from salesforce.com developer account.

$ cp util
$ cp src/main/resources/application.conf.sample \
 src/main/resources/application.conf
$ cat src/main/resources/application.conf

Update the "" with appropriate values for ClientId, ClientSecret, UserName, PassWord, LoginURL and GrantService.

force {
  UserName     = ""
  PassWord     = ""
  LoginURL     = ""
  GrantService = ""
  ClientID     = ""
  ClientSecret = ""
}

Common Methods

File src/main/scala/Util.scala provides common methods for getting access token.

Get Access Token

Access token GET is implemented in method getAccessToken() of Util.scala. We define a class Util in this file and add method getAccesssToken()

class Util {
  def getAccessToken() : String = {

  }
}

Getting access token consists of following steps.

  1. Load Credentials from application.conf into appropriate variables and create loginURL
val conf = ConfigFactory.load()
val UserName = conf.getString("force.UserName")
val PassWord     = conf.getString("force.PassWord")
val LoginURL     = conf.getString("force.LoginURL")
val GrantService = conf.getString("force.GrantService")
val ClientID     = conf.getString("force.ClientID")
val ClientSecret = conf.getString("force.ClientSecret")

val loginURL = LoginURL +
              GrantService +
              "&client_id=" + ClientID +
              "&client_secret=" + ClientSecret +
              "&username=" + UserName +
              "&password=" + PassWord
  1. Connect to the OAuth2 token url /services/oauth2/token
  2. Create a new HTTP Client client, :code:`HttpPost object post and call execute(post) on this client
val client = new DefaultHttpClient
val post = new HttpPost(loginURL)
val handler = new BasicResponseHandler();
val response = client.execute(post)
println("response:" +  response)
  1. Get the result body
val body = handler.handleResponse(response);
  1. Extract the access_token and return it using gson library. We also define a custom class Token into which the access_token is parsed
case class Token(access_token: String, instance_url: String,
 id: String,
 token_type: String,
 issued_at: String,
 signature: String)
val gson = new Gson
val jsonObject = gson.fromJson(body, classOf[Token])
access_token = jsonObject.access_token
println("access_token: " + access_token)

Full code Listing shown below

Reference Source Code : getAccessToken

SObject Class

Create a generic SObject class which can be used to encapsulate CRUD operations for SObject. This is created under the path src/main/scala

 src
|   `-- main
|       |-- resources
|       `-- scala
|           |-- SObject.scala
class SObject(sObjectN : String) {
    var sObjectName: String = sObjectN

}

Get List of SObjects

Url used to make request depends on the instance where your account was created ( na1, na2, ap1, ap2 etc) as well the version of the API being used. We are using the base url https://ap2.salesforce.com/services/data/v35.0/sobjects/.

The function getList() will be added to SObject class created above.. An HTTPs Get request is made to the URL listed above appended by the object_name. Header of the HTTP request has Access token set. Http Header.

This access token is obtained from getAccessToken

Content-type is set to application/json.

def getList() : String = {
  val host = "https://ap2.salesforce.com"
  val baseUrl = "/services/data/v35.0/sobjects/"
  val util = new Util()

  val access_token = util.getAccessToken()
  println(access_token)
  val url = host + baseUrl + sObjectName
  val request = new HttpGet(url)

  request.addHeader("Authorization", "Bearer " + access_token)
  request.addHeader("Content-type", "application/json")
  val client = new DefaultHttpClient
  val response = client.execute(request)
  val handler = new BasicResponseHandler()
  val body = handler.handleResponse(response)
  return body
}

This method is called from Account objects get_list function to get list of Accounts.

Get Account List

Create a SObject using the class SObject with Object name as Account.Call getList() method on the object to get List of Accounts.

object AccountList{
  def main(args: Array[String]): Unit = {
    val sObject = new SObject("Account")
    val body = sObject.getList()
    println(body)
  }
}

Compile the program

$ sbt compile

Run the program

$ sbt run
 [1] AccountList

Create Account

Create a new method createSObject() in SObject class. We will do following actions in this method

  1. Instantiate Util object and get Access Token
val access_token = util.getAccessToken()
  1. Create the url for Http Post, create a HttpPost object
val url = host + baseUrl + sObjectName
val post = new HttpPost(url)
  1. Add Authoorization and Content-type headers
 post.addHeader("Authorization", "Bearer " + access_token)
post.setHeader("Content-type", "application/json")
  1. Account name is added in the body of the HttpPost

  2. Execute the Http Request

    val response = (new DefaultHttpClient).execute(post)
    

Full Code Listing

def createSObject(jsonData : String)  =  {
    val host = "https://ap2.salesforce.com"
    val baseUrl = "/services/data/v35.0/sobjects/"
    val util = new Util()

    val access_token = util.getAccessToken()
    println(access_token)
    val url = host + baseUrl + sObjectName
    val post = new HttpPost(url)

    // set the Content-type
    post.addHeader("Authorization", "Bearer " + access_token)
    post.setHeader("Content-type", "application/json")

    // add the JSON as a StringEntity
    post.setEntity(new StringEntity(jsonData))

    // send the post request
    val response = (new DefaultHttpClient).execute(post)
    println(response)
  }

Compile and Run the Program

$ sbt compile
$ sbt run

Delete Account

In this section we look at how to use Scala to make a Delete call.

  1. Add a Delete Method deleteSObject to SObject class.

    def deleteSObject(objectId: String) {
    
    }
    
  2. Implement the following steps in this method

    • Get accessToken from Util class

      val accessToken = util.getAccessToken()
      
    • Create the url object using objectId to be deleted and sObjectName

      val url = host + baseUrl + sObjectName + "/" + objectId
      
    • Create HttpDelete object from the url

    • Add Authoorization and Content-type headers

      delete.addHeader("Authorization", "Bearer " + access_token)
      delete.setHeader("Content-type", "application/json")
      
    • Execute the delete using DefaultHttpClient instance

      val response = (new DefaultHttpClient).execute(delete)
      
def deleteSObject(objectId: String) {
  val host = "https://ap2.salesforce.com"
  val baseUrl = "/services/data/v35.0/sobjects/"
  val util = new Util()

  val accessToken = util.getAccessToken()
  println(accessToken)
  val url = host + baseUrl + sObjectName + "/" + objectId
  val delete = new HttpDelete(url);
  delete.addHeader("Authorization", "Bearer " + accessToken)
  delete.setHeader("Content-type", "application/json")

  val response = (new DefaultHttpClient).execute(delete)
  println(response)
}

Create a DeleteAccount Scala object in DeleteAccount.scala file.

  1. We will override def main(args: Array[String]): Unit method and create an SObject instance.
  2. Set the objectId of the Account to be deleted. Please change this to the appropriate value for your environment.
  3. call sObject.deleteSObject(objectId)
object DeleteAccount{
  def main(args: Array[String]): Unit = {
    val sObject = new SObject("Account")
    val objectId = "0012800000DR2Ko"
    sObject.deleteSObject(objectId)
  }
}

Compile and Run the Program

$ sbt compile
$ sbt run

Update Account

Patch SObject

To update an account we need to use Http Patch request. We will add a new method patchSObject(..) in SObject class. This method takes two parameters objectId : Object ID of the SObject to be updated, and jsonData the json of field names and values.

def patchSObject(objectId: String , jsonData: String) {

}

Steps implemented in the following code

  1. Get Access Token

    val util = new Util()
    val accessToken = util.getAccessToken()
    
  2. Create the URL to be patched

    val url = host + baseUrl + sObjectName + "/" + objectId
    
  3. Create a HttpPatch object of type org.apache.http.client.methods.HttpPatch

    val patch = new HttpPatch(url);
    
  4. Set the Http Headers with the authorization token

    patch.addHeader("Authorization", "Bearer " + accessToken)
    patch.setHeader("Content-type", "application/json")
    
  5. Set the body of HttpPatch object patch with jsonData

    patch.setEntity(new StringEntity(jsonData))
    
  6. Call execute(..) method on DefaultHttpClient.

    val response = (new DefaultHttpClient).execute(patch)
    

Complete code for patchSObject(..)

def patchSObject(objectId: String , jsonData: String) {
  val host = "https://ap2.salesforce.com"
  val baseUrl = "/services/data/v35.0/sobjects/"
  val util = new Util()
  val accessToken = util.getAccessToken()
  println(accessToken)
  val url = host + baseUrl + sObjectName + "/" + objectId
  val patch = new HttpPatch(url);
  patch.addHeader("Authorization", "Bearer " + accessToken)
  patch.setHeader("Content-type", "application/json")
  patch.setEntity(new StringEntity(jsonData))
  val response = (new DefaultHttpClient).execute(patch)
  println(response)
}

Update Account

  1. Create a Updateccount scala object
  2. Instantiate SObject in the main(..) method

3. Create jsonData json string 3. Call sObject.patchSObject(..)

object UpdateAccount{
  def main(args: Array[String]): Unit = {
      val sObject = new SObject("Account")
      val objectId = "0012800000EuoVB"
      val jsonData = """{"name":"Account1.1"}"""
      sObject.patchSObject(objectId, jsonData)
  }
}

Compile and Run the Program

$ sbt compile
$ sbt run

Run SOQL Query

To run a SOQL Query to get data from a SObject follow the steps listed below:

  1. Create a new method executeSOQL(..) in SObject class

    def executeSOQL(soql: String): String = {
    
    }
    
  2. Get accessToken

    val util = new Util()
    val accessToken = util.getAccessToken()
    
  3. Create url

    val url = host + baseUrl  + soql
    println("url: " + url)
    val request = new HttpGet(url)
    
  4. Create HttpGet request object

    val request = new HttpGet(url)
    
  5. Add Http headers

    request.addHeader("Authorization", "Bearer " + accessToken)
    request.addHeader("Content-type", "application/json")
    
  6. Create a new DefaultHttpClient

    val client = new DefaultHttpClient
    
  7. Execute the Get method, handle the response and display JSON

    val response = client.execute(request)
    val handler = new BasicResponseHandler()
    val body = handler.handleResponse(response)
    
  8. Complete Code for executeSOQL() method

def executeSOQL(soql: String): String = {
  val host = "https://ap2.salesforce.com"
  val baseUrl = "/services/data/v35.0/query/?q="
  val util = new Util()

  val accessToken = util.getAccessToken()
  println("accessToken: " + accessToken)
  val url = host + baseUrl  + soql
  println("url: " + url)
  val request = new HttpGet(url)
  request.addHeader("Authorization", "Bearer " + accessToken)
  request.addHeader("Content-type", "application/json")
  val client = new DefaultHttpClient
  val response = client.execute(request)
  val handler = new BasicResponseHandler()
  val body = handler.handleResponse(response)
  return body
}
  1. Create a ExecuteSOQLQuery.scala file with ExecuteSOQLQuery object.

    1. Create main() method

    2. Instantiate SObject with Account as the object name : sObject.

    3. Create a json data string

    4. Create a soql String

      val soql  = """SELECT+name+from+Account"""
      
    5. Call sObject.executeSOQL(soql)

      object ExecuteSOQLQuery{
        def main(args: Array[String]): Unit = {
          val sObject = new SObject("Account")
          val json = """{"name":"Account1"}"""
          val soql  = """SELECT+name+from+Account"""
          val response = sObject.executeSOQL(soql)
          println("response:" + response)
        }
      }
      

Compile and Run the Program

$ sbt compile
$ sbt run