Connecting to the Salesforce REST APIs with Spring Boot and Java

Broadly speaking there are two types of integrations with Salesforce, either a system-to-system integration or a user interface integration. One of the primary ways to do these integrations is by using the Salesforce REST API. When using the Salesforce REST API you need to obtain an access token that identifies who is making the requests. OAuth 2 provides an HTTP interface to obtain a Salesforce access token.

When using the Salesforce OAuth 2 API there are three options for obtaining an access token:

  1. Use the Web Server Flow where a Salesforce user in a traditional web app is asked to authorize a third party application which then allows the web server to obtain an access token.
  2. Use the User Agent Flow where a Salesforce user in a mobile or JavaScript web app is asked to authorize a third party application which then allows the client side application (native mobile, JavaScript, etc) to obtain an access token.
  3. Use the Username and Password Flow where stored credentials for a system-to-system integration user are exchanged for an access token.

The OAuth Web Server Flow can seem tricky to implement by hand because there are a number of necessary steps but luckily this flow is pretty standard so many libraries have done the hard work for us. In the case of a Java Spring application the hard work has all been done by the Spring Security OAuth library. And Spring Boot makes it super easy to setup a new application that has everything needed for the OAuth Web Server Flow.

Let’s walk through the different pieces of a simple web application which has the OAuth stuff, fetches Accounts from the Salesforce REST API, and renders them in a web page via JavaScript. (Note: You can skip straight to the completed project if you just want to deploy the app on Heroku or get it all running locally.)

First we need a build system to manage dependencies, run the app, and assemble the app for deployment. I’ve chosen Gradle so here is my build.gradle:

buildscript {
    repositories {
        maven {
            url ''
    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.4.2.RELEASE'
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
repositories {
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:1.4.2.RELEASE'
    compile 'org.springframework.boot:spring-boot-devtools:1.4.2.RELEASE'
    compile 'org.springframework.boot:spring-boot-starter-security:1.4.2.RELEASE'
    compile ''
    compile 'org.webjars:salesforce-lightning-design-system:2.1.4'
    compile 'org.webjars:jquery:3.1.1'

There you can see dependencies on the Spring Boot stuff, the Spring Security OAuth library and a few WebJars for the UI.

Now we need to set some properties for the Spring Security stuff. There are a few different ways to set these and you should make sure that your OAuth client id and secret don’t end up in SCM. At a minimum you will need these settings:

security.oauth2.client.client-authentication-scheme = form
security.oauth2.client.authentication-scheme = header
security.oauth2.client.grant-type = authorization_code
security.oauth2.client.access-token-uri =
security.oauth2.client.user-authorization-uri =
security.oauth2.resource.user-info-uri =
security.oauth2.client.client-id = YOUR_SALESFORCE_CONNECTED_APP_CLIENT_ID
security.oauth2.client.client-secret = YOUR_SALESFORCE_CONNECTED_APP_CLIENT_SECRET

I put all of the settings except the client id and secret in a src/main/resources/ file. For the other settings you can use environment variables or config settings on Heroku. Spring Boot automatically will look for the client id and secret in environment variables named SECURITY_OAUTH2_CLIENT_CLIENT_ID and SECURITY_OAUTH2_CLIENT_CLIENT_SECRET.

Next we need a Spring component that will handle the REST communication with Salesforce including the query for Accounts and deserialization from JSON. Here is my src/main/java/com/example/ code:

package com.example;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Force {
    private static final String REST_VERSION = "35.0";
    private OAuth2RestTemplate oAuth2RestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
        return new OAuth2RestTemplate(resource, context);
    private OAuth2RestTemplate restTemplate;
    private static String restUrl(OAuth2Authentication principal) {
        HashMap<String, Object> details = (HashMap<String, Object>) principal.getUserAuthentication().getDetails();
        HashMap<String, String> urls = (HashMap<String, String>) details.get("urls");
        return urls.get("rest").replace("{version}", REST_VERSION);
    public List<Account> accounts(OAuth2Authentication principal) {
        String url = restUrl(principal) + "query/?q={q}";
        Map<String, String> params = new HashMap<>();
        params.put("q", "SELECT Id, Name, Type, Industry, Rating FROM Account");
        return restTemplate.getForObject(url, QueryResultAccount.class, params).records;
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Account {
        public String Id;
        public String Name;
        public String Industry;
        public String Rating;
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class QueryResult<T> {
        public List<T> records;
    private static class QueryResultAccount extends QueryResult<Account> {}

There is some plumbing to setup the Spring REST Template which makes it easy to make the REST requests. The accounts method takes an OAuth2Authentication so that the URL can be determined. Finally there are some classes to represent the results from the query and the Account, which are created from the JSON data returned from the REST API.

For Spring Boot we need an application which will be run on the web server (or local machine for development). In this example the application will also contain our REST API implementation which will be used by a JavaScript UI. Here is the code for the src/main/java/com/example/ file:

package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
public class SpringSalesforceApplication {
    private Force force;
    public List<Force.Account> accounts(OAuth2Authentication principal) {
        return force.accounts(principal);
    public static void main(String[] args) {, args);

This does all the magic to create a Spring Boot web application which uses the Spring Security OAuth stuff, the Force component, and a REST controller. There is a single REST controller method in this application that handles requests to /accounts, does the query to Salesforce using the Force component, deserializes the results, then reserializes them as JSON. In this little example we aren’t seeing why we’d want to proxy the Salesforce REST API in this way since we are not doing any aggregation or transformation of data. But that would be straightforward to do if needed.

The final piece of this application is a web UI that uses the Spring Boot app’s /accounts REST method to get and then display the accounts. In this case I’m using jQuery to do that. Here is the code for the src/main/resources/static/index.html file:

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Hello Spring Salesforce</title>
    <link rel="stylesheet" type="text/css" href="webjars/salesforce-lightning-design-system/2.1.4/assets/styles/salesforce-lightning-design-system.min.css"/>
    <script type="text/javascript" src="webjars/jquery/3.1.1/jquery.min.js"></script>
        $(function() {
          $.get("/accounts", function(data) {
            $.each(data, function(i, account) {
              var tr = $("<tr>");
    <header class="slds-global-header_container">
        <div class="slds-global-header slds-grid slds-grid--align-spread">
            <div class="slds-global-header__item">
                <div class="slds-text-heading--large">Hello Spring Salesforce</div>
    <div class="slds-container--center slds-container--medium" style="margin-top: 60px;">
        <div class="slds-text-heading--medium">Salesforce Accounts</div>
        <table class="slds-table slds-table--bordered slds-table--cell-buffer">
                <tr class="slds-text-title--caps">
                    <th scope="col">
                        <div class="slds-truncate" title="Id">Id</div>
                    <th scope="col">
                        <div class="slds-truncate" title="Id">Name</div>
                    <th scope="col">
                        <div class="slds-truncate" title="Id">Industry</div>
                    <th scope="col">
                        <div class="slds-truncate" title="Id">Rating</div>

With this application running locally when I visit http://localhost:8080 in my browser, Spring Security notices that I don’t yet have an access token so it walks through the OAuth Web Server Flow with Salesforce and once complete renders the index.html page. The JavaScript on that page makes the REST request to /accounts which does the query to the Salesforce REST APIs and then returns the JSON back to the browser. Finally, the data is rendered in the table on the web page. Here is what it looks like:

In total there were only five pretty small files needed to have an end-to-end Salesforce REST API integration with a web application. Hopefully that gets you started! For full instructions on Heroku deployment of this application or to get the app running locally, check out the complete project on GitHub.

Let me know how it goes!


    Hi James,
    I tried deploying the code in my local. I was getting 400 error with following cause
    Caused by: org.springframework.web.client.HttpClientErrorException: 400 TLS 1.1 or higher required
    I neither made changes on gradle config nor code. Do you know what I need to do to fix this issue ?


      I got it figured. I was using JDK 1.7. I upgraded to JDK 8 and it resolved the issue

  • Ram

    Hi I have a question here. Is there anyway to skip that page asking allow/denay and directly show the accounts upon hitting the url. .?
    because i want to hide the app-salesforce interaction from the user UI. (willing to default it to Allow or use my custom page instead) .. please let me know how to achieve it .. Thank you

    • The OAuth workflow is useful when your users are Salesforce users. It sounds like you want to use a single integration user for all of the users of your app instead. In this case you can use a machine-to-machine integration with the OAuth username and password flow. Here is an example app for that:

      Alternatively you can use Heroku Connect.

  • That exciting post, to put into practice, exists so much to do …. greetings cordial …

  • PA

    I am getting the below error

    java.lang.NoSuchMethodError: org.springframework.jndi.JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()Z
    at org.springframework.core.env.AbstractEnvironment.(
    at org.springframework.core.env.StandardEnvironment.(
    at org.springframework.web.servlet.HttpServletBean.createEnvironment(
    at org.springframework.web.servlet.HttpServletBean.getEnvironment(
    at org.springframework.web.servlet.HttpServletBean.init(
    at javax.servlet.GenericServlet.init(
    at org.apache.catalina.core.StandardWrapper.initServlet(
    at org.apache.catalina.core.StandardWrapper.loadServlet(
    at org.apache.catalina.core.StandardWrapper.load(
    at org.apache.catalina.core.StandardContext.loadOnStartup(
    at org.apache.catalina.core.StandardContext.startInternal(
    at org.apache.catalina.util.LifecycleBase.start(
    at org.apache.catalina.core.ContainerBase$
    at org.apache.catalina.core.ContainerBase$
    at Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$ Source)
    at Source)

    • Hmm… What are the steps you took to get this?

      • PA

        Hey, I just compiled the code and deployed it to tomcat. While deploying I got the error shown above.

        • Ah, I did see some reports on StackOverflow of that. Can you just use the containerless Spring Boot instead of deploying in Tomcat?

          • PA

            I don’t see any main method to kick off the run. Could you please confirm ?

  • Venkata R Sabbella

    Hello James, I am running in to the below error. I configured the connected app and got the client Id and client secret and set the call back URL to http://localhost:8080. I keep getting this error when I visit http://localhost:8080 in my browser.
    Not sure what is going wrong.
    error=redirect_uri_mismatch&error_description=redirect_uri%20must%20match%20configuration. Thanks for the post and looking forward for any inputs.

  • Szymon Tosik

    Hey, how should I configure my connected app in order to make it works ? I keep getting exception when hitting up localhost:8080/login locally, I set up OAuth2 authentication in my connected app along with cliend id and client-secret and set them up in I’m getting
    [= is not a valid HTTP URL

    which probably is because of wrong configuration of my connected app, especially callback url which i set to

    • Szymon Tosik

      the problem was with additional =, although I’m getting another error ;( My org is located in custom domain and once i specify it through login interface I get 500 error code with message that Authentication Failed: Could not obtain access token

      • In your try to uncomment the logging line and see if that provides any additional details.

  • Shreyas Dhond

    How do you serialize query with relationship fields into an object? eg. SELECT Id, Name, Type, Owner.Name FROM Account. What would the object look like static class Account {
    public String Id
    public String Name
    public String Industry
    public String Rating
    public Owner__r.Name

    • I think you’d want a child object named Owner and a field named owner__r on Account.

  • chaker

    Hello James, how can I set the proxy?
    tImeout = connect

    • Which proxy are you referring to?

      • chaker

        I’m sitting behind a company proxy. Can we set proxy from salesforce to my localhost?

  • chaker

    Hi James,
    Can we use OAuth2RestTemplate for login, and Metadata API for reading the metadata at the same time?

    • Yeah, that should work but I haven’t tried it.

  • Adarsh Burma

    Hey James I did setup connected app on salesforce I deployed spring boot app on a kubernetes cluster I’m not sure if I’m missing any config on salesforce I always have to use /login which is a callback url configured on salesforce before I can request my endpoint to get data for Soql example /accounts

    • It sounds like something isn’t quite right. Maybe the cookies aren’t getting stored properly. Can you use your browser debugging to see what is happening with the cookies?