avatar(ELTOROIT) Andres Perez

Summary

The article outlines the process of retrieving Data Cloud information using Apex callouts in a Salesforce CRM org different from the Data Cloud org and displaying it using Lightning Web Components (LWC).

Abstract

This article, the third in a series on Data Cloud development, details the steps for developers to access and display Data Cloud data within a separate CRM Salesforce org. It builds upon the knowledge from previous chapters, emphasizing the use of Apex callouts to retrieve data and LWC to present it in the CRM org. The process involves obtaining an access token from the Data Cloud org, exchanging it for a Data Cloud Server access token, executing an SQL query to fetch the desired data, and finally, displaying the results in an LWC component, such as a <lightning-datatable>. The article also acknowledges the security concerns of hard-coding credentials and promises to address this in the next chapter with safer authentication methods.

Opinions

  • The author assumes familiarity with the previous chapters and does not reiterate the information, expecting the reader to be well-versed with the concepts discussed earlier.
  • The article emphasizes the practicality of the demonstrated techniques for developers working with Data Cloud and CRM data in separate orgs.
  • There is an acknowledgment of the potential risks associated with using the username-password OAuth authentication flow, with a commitment to explore more secure methods in subsequent content.
  • The author provides a teaser for the next chapter, hinting at the use of Named Credentials, External Name Credentials, and Auth. Provider to enhance security.
  • The article is part of a larger educational series aimed at developers, suggesting a structured approach to learning Data Cloud development within the Salesforce ecosystem.
  • The author endorses an AI service, ZAI.chat, as a cost-effective alternative to ChatGPT Plus (GPT-4), indicating a preference or partnership.

Data Cloud For Developers — Chapter 3: LWC & Apex In CRM Cloud Org (Different Org)

TL;DR; This article describes how to get data from Data Cloud using Apex callouts from a different org, and displaying that data using LWC, but they are in separate orgs. The steps are based on the concepts discussed in previous chapters. This is the third chapter of a series of articles for Developers working with Data Cloud

This is the third chapter of a series of articles for developers who want to develop with Data Cloud. Check out the previous articles here:

Today we are going to build an LWC component that will display the Data Cloud information retrieved via Apex callouts, and we’ll place such a component in the CRM org.

The concepts we will be learning here are very handy if you have configured Data Cloud and CRM data in different orgs because you will be able to build components for records like account, contact, cases, etc. in the CRM org, and have those LWC display information (like unified records for example) from the Data Cloud Org.

Steps To Query Remote Data:

In this article, we are going to perform these steps to retrieve the Data Cloud data from a different Salesforce CRM org:

  • Get Data Cloud Org access token using unsafe username-password flow
  • Swap Data Cloud Org access token for Data Cloud Server access token
  • Perform SQL query in Data Cloud Server
  • Display results in a <lightning-datatable/> LWC component

Remember…

Remember that we can either configure Data Cloud in the CRM org, or we can have configure them in separate orgs. This article deals with putting the Apex/LWC code on different orgs. If you want to know how the Apex/LWC can be placed in the Data Cloud Org (Same Org) please visit the first chapter in this series: Chapter 1: LWC & Apex In Data Cloud Org (Same Org)

Please make sure you have read chapters 1 and 2 since we are building this article on top of the knowledge acquired in those chapters. At least you should be familiar with:

Chapter 1: LWC & Apex In Data Cloud Org (Same Org):

You should be familiar with the concepts covered in this chapter:

  • Extracting the SQL from the Data Cloud’s Data Explorer
  • Validating the SQL extracted using Code Builder or VS Code
  • Understand the ConnectAPI.CdpQuery.queryAnsiSqlV2() Apex method, and in particular how the results are returned
  • Parse in LWC the results from the query (we’ll use the same component)

Chapter 2: Accessing Data Cloud Data Via Api (Postman):

You should be familiar with the concepts covered in this chapter:

  • Pulling data from Data Cloud using APIs
  • Create a connected app particularly built for Data Cloud APIs
  • Using the OAuth the username-password flow
  • Obtaining an OAuth access token from Data Cloud Org
  • Swapping for the Data Cloud Server access token, since they are different.
  • Querying the Data Cloud Server using it’s own access token

Warning: A lot of information on those chapters is required to be able to understand this article, I am not going to repeat myself here or this article would be gigantic. I will assume you have read those chapters and I will not repeat the same information here.

In the article Salesforce’s Data Cloud Segmentation, we configured two orgs, one is a CRM org based on a Trailhead Playground and the other is a Data Cloud org. I am going to use those orgs for the demos, but any Data Cloud Org could be used.

Enough introductions… Let’s begin.

Get Data Cloud CRM Access Token

I always like to start my projects with something simple and basic and then build on top of that. We kind of already started by setting up the calls using Postman in Chapter 2, we just need to code them in Apex.

We already have a Connected App, security key, and secret, and we have tested that in Postman (See Chapter 2), we are ready to code that in Apex using the OAuth username-password flow with this code:

private static Map<String, String> loginOrgUNPW() {
  Map<String, String> orgCredentials;

  // Make body
  body = '';
  body += 'grant_type=password';
  body += '&client_id=3M...zA';
  body += '&client_secret=581...C3';
  body += '&[email protected]';
  body += '&password=A...Z';

  // Make callout
  req = new HttpRequest();
  req.setEndpoint('https://login.salesforce.com/services/oauth2/token');
  req.setMethod('POST');
  req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
  req.setBody(body);
  res = h.send(req);

  // Process results
  System.assertEquals(200, res.getStatusCode());
  orgCredentials = (Map<String, String>) JSON.deserialize(res.getBody(), Map<String, String>.class);
  System.debug('Login Org UNPW');
  for (String key : orgCredentials.keySet()) {
    System.debug(key + ': ' + orgCredentials.get(key));
  }
  return orgCredentials;
}

You may be getting this error:

Unauthorized endpoint, please check Setup->Security->Remote site settings.
endpoint = https://login.salesforce.com/services/oauth2/token

That’s because we have not set the Remote Site Settings, so let’s do that. You must create a Remote Site Setting in Setup > Security > Remote Site Settings for the URL https://login.salesforce.com.

Configure Remote Site Settings for https://login.salesforce.com

If we use Code Builder to retrieve the log, and then use grep, we can filter the log items to show only the debug log entries:

System.debug() generated these lines

Swap Access Tokens

Following the same calls we did in Chapter 2 using Postman, we are going to swap the Data Cloud CRM access token for the Data Cloud Server access token. Here is the code:

private static Map<String, String> swapOrgForDcTokens(Map<String, String> orgCredentials) {
  Map<String, String> dcCredentials;

  // Make body
  body = '';
  body += 'grant_type=urn:salesforce:grant-type:external:cdp';
  body += '&subject_token=' + orgCredentials.get('access_token');
  body += '&subject_token_type=urn:ietf:params:oauth:token-type:access_token';

  // Make callout
  req = new HttpRequest();
  req.setEndpoint(orgCredentials.get('instance_url') + '/services/a360/token');
  req.setMethod('POST');
  req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
  req.setBody(body);
  res = h.send(req);

  // Process results
  System.assertEquals(200, res.getStatusCode());
  dcCredentials = (Map<String, String>) JSON.deserialize(res.getBody(), Map<String, String>.class);

  System.debug('Tokens swapped');
  for (String key : dcCredentials.keySet()) {
    System.debug(key + ': ' + dcCredentials.get(key));
  }

  return dcCredentials;
}

Since we are making a call to the instance_url domain, we need to set the Remote Site Settings for this domain too.

Remote site settings configuration for Data Cloud Org

Last, let’s review the debug logs for this call

The red box highlights the System.debug() entries for the swap

Query Data

Now that we have the access_token and the new URL for the Data Cloud Sever, we are ready to perform the query using this code:

private static Map<String, Object> dcQuery(Map<String, String> dcCredentials, String sql) {
  // Make body
  Map<String, String> mapBody = new Map<String, String>();
  mapBody.put('sql', sql);
  body = JSON.serialize(mapBody);

  // Make callout
  req = new HttpRequest();
  req.setEndpoint('https://' + dcCredentials.get('instance_url') + '/api/v2/query');
  req.setMethod('POST');
  req.setHeader('Content-Type', 'application/json');
  req.setHeader('Authorization', 'Bearer ' + dcCredentials.get('access_token'));
  req.setBody(body);
  res = h.send(req);

  // Process results
  System.assertEquals(200, res.getStatusCode());
  return (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
}

We also need the Remote Site Settings for the Data Cloud Server, so let’s set that up:

Remote site settings for Data Cloud Server

This is the debug log that was generated

The red box highlights the SQL query results

We can re-use the same LWC component that was used in Chapter 1, we do not need to make changes because the JSON structure from the ConnectAPI is the same as the data format returned via the API. This is the output of that component:

We can reuse the same LWC we discussed in Chapter 1: LWC & Apex In Data Cloud Org (Same Org)

And with that, we have completed the process of getting Data Cloud data in a different org using Apex and LWC.

[READER] Excuse me, but I think we are not done. Did you forget we are hard-coding the username and password in the Apex code? Are you sure that’s fine?

[ELTORO] You are right, we are going to have to fix that. But let’s leave that for the next chapter, where we will use Named Credentials, External Name Credentials, Auth. Provider to replace unsafe username-password flow for the safe Web Server flow.

Salesforce
Salesforce Data Cloud
Apex
Lwc
Recommended from ReadMedium
avatarHanovconsulting
LWC Events

Home » LWC Events

7 min read