Monday, June 10, 2024

Pulling data in from external systems using DataLicense

 One of the mechanisms to pull data in from other systems is to go for a Product called Salesforce Data Pipeline. It is its own SKU so you need to review licensing requirements with your CSM.


It's a simple tool to connect to any external Data Store and pull data in using the Analytics Data Manager. YOu need to create a recipe to pull data in. It's super easy and lot convenient if you have many needs to get data from external systems.


You can pull data in and store it in a Staging table and process it from there. 

Friday, March 4, 2022

 All about Platform Events

Platform Events are used to deliver secure, scalable, and customizable notification within Salesforce or external app. Platform Event is based on Event-Driven Architecture. This is built in real time integration patterns in the Salesforce Platform which helps to reduce point-to-point integration.

Publishing platform event: 

We can publish the platform events in 3 ways:

  1. Publish Events Messaging using APEX.
  2. Publish Events Messaging using Declarative tools (Process Builder or Cloud Flow Designer Tool / Visual Work flow).
  3. Publish Events Messaging using Salesforce API from external app.

Not supported in Platform event: 

  1. The allOrNoneHeader API header is ignored when you publish platform events through the API.
  2. The Apex setSavepoint() and rollback() Database methods aren’t supported with platform events.

Subscription in Platform Event: 

  1. Apex triggers receive event notifications.
  2. write an “after insert” Apex trigger on the event object to subscribe to incoming events.
  3. Triggers receive event notifications from various sources—whether they’re published through Apex or APIs.
  4. Visualforce and Lightning component apps receive events through CometD.
  5. CometD is a scalable HTTP-based event routing bus that uses an AJAX push technology pattern known as Comet.
  6. In an external app, you subscribe to events using CometD as well.

Defining Objects and fields in Platform Events: 

Platform events can be created just like the custom objects. The biggest difference between Platform events and Custom object is suffix name for the api name. In Platform events, its api name suffix with __e where the custom object appends __c suffix to create api name. Unlike with custom objects, we cannot update or delete event record, or view event records in Salesforce User Interface.

Platform Events support only following custom fields type,

  1. Checkbox
  2. Date
  3. Data/Time
  4. Number
  5. Text
  6. Text Area (Long)

Tuesday, March 1, 2022

 All about Outbound Messaging


Pros

  • Outbound Message has in-built retry mechanism. 
  • Messages will be queued locally. A separate background process performs the actual sending, to preserve message reliability
  • If the endpoint is unavailable, messages will stay in the queue until sent successfully, or until they are 24 hours old. After 24 hours, messages are dropped from the queue.
  • If a message cannot be delivered, the interval between retries increases exponentially, up to a maximum of two hours between retries.
  • Messages are retried independent of their order in the queue. This may result in messages being delivered out of order.
  • Source object may change after a notification is queued but before it is sent, so the endpoint will only receive the latest data, not any intermediate changes. Because a message may be delivered more than once, your listener client should check the notification IDs delivered in the notification before processing.
Security Considerations
  • All Outbound messages are sent from Salesforce IP address. Make sure that Salesforce IP addresses are white listed in external system.
  • Using SSL/TLS provides confidentiality while data is transported across the internet.
  • You can pass user session Id in outbound messages so that external system can callback and update data back in salesforce.
  • The organization Id is included in each message. Your client application should validate that messages contain your organization Id.
If your application (endpoint) server's SSL/TLS may be configured to require client certificates (two-way SSL/TLS), in order to validate the identity of the Salesforce server when it takes the role of client to your server. If this is the case, you can download the Salesforce client certificate from the Salesforce application user interface. This is the client certificate that Salesforce sends with each outbound message for authentication.
  • From Setup, enter API in the Quick Find box, then select API.
  • On the API WSDL page, click Manage API Client Certificate.
  • On the Certificate and Key Management page, in the API Client Certificate section, click the API Client Certificate.
  • On the Certificates page, click Download Certificate. The .crt file is saved in the download location specified in your browser.
Import the downloaded certificate into your application server, and configure your application server to request the client certificate. The application server then checks that the certificate used in the SSL/TLS handshake matches the one you downloaded.

Tuesday, June 29, 2021

DevConsole NonFunctional

 From time to time; if you are a DevConsole user the devconsole becomes console, in my case a "Communication Failure" was being returned.


Well. to restore your DevConsole

Developer Console menu may become non-functional sometimes, because of the workspace being in a bad state. To restore the functionality, follow the following steps. Fix 1: 1. Login and open Developer Console by Chrome 2. Open Developer tools and select Network 3. Reload on Developer Console Fix 2: 1. Login to Workbench and go to REST Explorer 2. Use the following query in Workbench to get the IDEWorkspace /services/data/v31.0/tooling/query/?q=SELECT id, name from IDEWorkspace ID of IDEWorkspace is "1dexxxxxxxxxxxxxx". 3. Do GET operation for the found id with following query "/services/data/v29.0/tooling/sobjects/IDEWorkspace/1de1a0000014sEWAAY" 4. You will see the content of IDEWorkspace 5. Do DELETE operation on found record. 6. Re-open Developer Console. 7. Developer Console will work fine. As we created a new workspace and the old workspace has been deleted. And the slowness will also be removed. I also had multiple WorkSpaces

Wednesday, March 25, 2020

Failed: InvalidBatch : Failed to process query: FUNCTIONALITY_NOT_ENABLED: Selecting compound data not supported in Bulk Query

Recently, while trying to extract data from WorkBench, I ran into this error.

I had selected all the fields on the Lead object and the error was not obvious enough for me

Failed: InvalidBatch : Failed to process query: FUNCTIONALITY_NOT_ENABLED: Selecting compound data not supported in Bulk Query


After some trial and error what I found is you need to elliminate compond fields from your BulkAPI query like Addresss.

Once I eliminated Address as a field from the file, I was able to extract the file successfully.

Thursday, December 19, 2019

Architect: Investigating Static Resources

Per Org, Salesforce allocates upto 250MB storage space. If you happen to run into a situation where you want to find how much storage space is being used then you could use the following 2 queries
and take action appropriately.

Following 
select id,bodylength,cachecontrol,contenttype,createdby.alias,createddate,description, lastmodifieddate from staticresource
will give you a list of all the static resources and the space it consumes

and the 
select sum(bodylength) from staticresource gives you the total storage space consumed

You might run into this issue if you have many installed packages in your system or you are using 3rd party tools like Skuid which masks Salesforce UI but allowing you to use custom UI but in the form of static resources

Enjoy !!!

Tuesday, October 8, 2019

Deleting Debug logs

If you have had to take over a system with little to KT and you have been running debug logs then you can attest to the pain points of deleting the logs by clicking Delete All..

There is a way out using Tooling API.

Delete logs are found from workBench using the following query

SELECT Id, StartTime, LogUserId, LogLength, Location FROM ApexLog

  1. Open Developer Console.
  2. At the bottom of the console, select the Query Editor tab.
  3. Select Use Tooling API.
  4. Enter this SOQL query:
    SELECT Id, StartTime, LogUserId, LogLength, Location FROM ApexLog
  5. Click Execute.
  6. Select the logs you want to delete. To sort by a column, click its header. To select individual logs, press Ctrl (Windows or Linux) or Command (macOS). To select a block of logs, press Shift.

Query to find fields being History tracked in Salesforce

Use the following query to find fields being history tracked

SELECT QualifiedApiName FROM FieldDefinition WHERE EntityDefinition.QualifiedApiName = 'Account' AND IsFieldHistoryTracked = true

You could always put this in a loop and get list of fields tracked for all objects

Monday, February 25, 2019

Executing classes from APEX Classes and APEX Test Execution....Analyzing the results....

Every few months, critical updates are released by Salesforce. As an architect, I needed to review and make sure that these updates won't have an adverse impact to our system.

If your system has a lot of custom code/development and lot of Installed Packages then you need to make sure that the system works correctly even after the updates are auto activated.


Go to APEX classes and hit the Run All test classes, this executes tests from Managed Packages as well.

The other option is to go to APEX test execution and selectively execute classes by specifying the namespace.

The critical thing after this steps is to be able to dissect the results generated as a result of the run.

Here are some queries to execute from WorkBench in BULK CSV mode.

SELECT AsyncApexJobId,Status,UserId FROM ApexTestRunResult
   SELECT ApexClassId,ApexLogId,ApexTestRunResultId,AsyncApexJobId,Id,Message,MethodName,Outcome,QueueItemId,RunTime,StackTrace,SystemModstamp,TestTimestamp FROM ApexTestResult where Outcome='Fail'
   SELECT ApexClassId,ApexLogId,ApexTestRunResultId,AsyncApexJobId,Id,Message,MethodName,Outcome,QueueItemId,RunTime,StackTrace,SystemModstamp,TestTimestamp FROM ApexTestResult where Outcome='Fail' and
   AsyncApexJobId='707S000000qe6mZIAQ'
   SELECT count(Id) FROM ApexTestResult where 
   AsyncApexJobId='707S000000qQmb7IAC' group by outcome
 
   SELECT count(Id) FROM ApexTestResult where 
   AsyncApexJobId=' ' group by outcome


When the tests are executed, an entry is created in APEX Test history indicating a TestRunID.
Drill down on the link and on the right you can see the Classes that have failed/passed.
Limitation is you can only view few at a time and can't see the details.

To get details, copy the RunID from the left and use it in the queries above, download the generated file from WorkBench and analyse the report.

I do multiple runs to make sure before/after update activation scenarios.

Tooling API

For most part I have used metadata API but never had the need to explore Tooling API aspect of Salesforce.  If you need to develop tools on metadata information from Salesforce this is the API to use.

We had a vendor move a lot of development to Production, the code coverage thru the Salesforce tools only indicated 22% code coverage while the vendor claimed to have 85% coverage.

I wondered if there was a way to crosscheck without to do a RunAll and that's where Tooling API came in handy.

Limitations: You can't use the queries in the normal sense from developer workbench; you have to go thru the RestExplorer approach.

However, you can use it in Developer console but then you can't export the data without having to do some hacks/

The Tooling API link is https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/intro_api_tooling.htm

Here are 2 situations where I needed to use:
a) Find code coverage when Salesforce and vendor claims were different
b) After a RunAll what is the code coverage for every single class in your system.

For a) run the following from WorkBench--utilities--RestExlorer

/services/data/v44.0/tooling/query/?q="SELECT+ApexClassOrTrigger.Name+NumLinesCovered+ NumLinesUncovered+FROM+ApexCodeCoverageAggregate"

Ther results will be in JSON format.
Take the response and paste in a JSON translator and you should be able to view and download the
revised output for a better understanding

OR

from developer console run the query, pasted a sample below.

SELECT ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverageAggregate 
WHERE ApexClassOrTrigger.Name = <Name>

SELECT PercentCovered 
FROM ApexOrgWideCoverage

SELECT NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverage 
WHERE ApexClassOrTriggerId = <ID>

SELECT ApexClassOrTriggerId, ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverageAggregate 
WHERE ApexClassOrTriggerId != NULL AND ApexClassOrTrigger.Name != NULL 
AND (NumLinesCovered &gt; 0 OR NumLinesUncovered &gt; 0) AND NumLinesCovered != NULL 
AND NumLinesUncovered != NULL ORDER BY ApexClassOrTrigger.Name

SELECT ApexClassOrTriggerId, ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered 
FROM ApexCodeCoverageAggregate 
ORDER BY ApexClassOrTrigger.Name

Thursday, January 24, 2019

DemandTools and Salesforce....Login Setup Isses

Got ready to use a new tool called DemandTool but could not get past the Login page.

It had 2 option a) API login and b) OAuth login.

Going with the API Login, tried using my UID/PWD and just could not get thru.

I found that the URL needs to be the URL found in the salesforce Partner WSDL file.

To generate the Partner WSDL file go to Salesforce Setup/API --Generate Partner WSDL.
Open the file and look for section which has soap:address location.

Copy the URL.

Thursday, January 17, 2019

Migrating Chatter data from one Org to Another....

Had a requirement to migrate Chatter data since we are migrating our Backlog Tool to Agile Accelerator in Org B from a Salesforce based vendor tool which resided in Org A.

Typically, for custom objects, if feed tracking is on, <object>_feed will be the object under which feed related records will be found.
Standard Objects have the feed in objects like AccountFeed, CaseFeed and so on.

Data can be exported using Dataloader.

To import, for custom objects, you need to import it back into an object called FeedItem and that should allow you to see the imported records.

For standard objects, you can import it back into it's own object i.e. AccountFeed, CaseFeed and so on.

Wednesday, January 16, 2019

Reporting Errors...

Team ran into the following issue while building reports:

a) Error: This report can no longer be edited or run. Your administrator has disabled all reports for the custom object, or its relationships have changed.

b) The filter logic references an undefined filter

On reviewing the setup, it was found that users were not having read access to the object, once the read access was provided that resolved error a.

The second error b) was resolved by providing field access to all the fields on the report.



Wednesday, January 2, 2019

SSO Integration: Salesforce Azure setup-Writing UserRegistration Class

There are 2 ways of integrating Salesforece and Azure.

One way seems to be from the Azure side, please see link below

https://docs.microsoft.com/en-us/azure/active-directory/saas-apps/salesforce-tutorial

This also does automatic user provisioning.

The other way is from the Salesforce side, please see link below for the steps:

https://help.salesforce.com/articleView?id=sso_provider_azure.htm

One of the steps is to write a user registration class. Follow the steps to create a sample class, once the sample class is created you need to modify it per your needs and depending on the data provided by the SSO provider in this case Azure.

//TODO:This autogenerated class includes the basics for a Registration
//Handler class. You will need to customize it to ensure it meets your needs and
//the data provided by the third party.


global class AzureSSOUsrCheck implements Auth.RegistrationHandler{
 
       static global boolean canCreateUser(Auth.UserData data) {
         system.debug('canCreateUser');
          system.debug('canCreateUser-identifier' + data.identifier);
           system.debug('canCreateUser-username' + data.Username);
     
              //Check if User exists - if not then create user else update user
              List<User> U = [SELECT Id, Username FROM User where Email=:data.email and IsActive=true LIMIT 1];
               if (U.size() > 0 ){
                   system.debug('canCreateUser-false');
                   return false;
               }
            system.debug('canCreateUser-true');
                   return true;
           
             
         }
 
   static global User createUser(Id portalId, Auth.UserData data){
            system.debug('createUser-data.email' + data.email );
            system.debug('createUser-data.firstName' + data.lastName + data.firstName );
            system.debug('createUser-data.username' + data.username );
            if(!canCreateUser(data)) {
    //Returning null or throwing an exception fails the SSO flow
    system.debug('Returning NULL from createUser' );
                User u1 = [select Id from User where email=:data.email and IsActive=true LIMIT 1];
     return u1;
  }

     
        //User u = new User();
            //Profile p = [SELECT Id FROM profile WHERE name='Standard User'];
            //u.username = data.username + '@hexagon.com' + '.slsmktg';
            //u.email = data.email;
            //u.username = 'deepak.balur@hexagon.com.slsmktg';

        List<User> UsrVal = [select Id from User where email=:data.email and IsActive=true LIMIT 1];
     
           if (UsrVal.size() > 0){
               return UsrVal[0];
           } else {
               return null;
           }
         

        }

       static global void updateUser(Id userId, Id portalId, Auth.UserData data){
    system.debug('updateUser-data.username' + data.username + data.email );
            system.debug('updateUser-data.firstName' + data.lastName + data.firstName );
            system.debug('updateUser-data.username' + data.username );
         
            User u = new User(id=userId);
            //u.username = data.username + '@hexagon.com';
            u.email = data.email;
            u.lastName = data.lastName;
            u.firstName = data.firstName;
            String alias = data.username;

            update(u);
        }
}

Execution Flow:

When the instance URL is typed in user is presented with the option of logging in via Azure SSO credentials, once the credentials are entered the createUser method is executed.
If the user does not exist then an error is returned to the user.

If the user exists then the updateUser will be executed and fields updated as specified in the method.

Please note; the requirement was not to create users on the fly and hence the createUser method only looks if the user exists or not.

Auth.UserData is a salesforce provided class; it contains the following fields
String identifier, String firstName, String lastName, String fullName, String email, String link,String userName, String locale, String provider, String siteLoginUrl, Map<String,String> attributeMap

When the interaction happens with Azure these fields can be passed from Azure.
For this integration, I was not the Azure Admin.

Hope this helps.

Thursday, November 1, 2018

Salesforce DevOps.....

I led the effort to build a DevOps pipeline for continuous delivery with increasing velocity to business.

Please use the following link, flow was done in Draw

https://drive.google.com/drive/folders/1fKOk5fsLYdDiUI49KIk6DqQm6FlmhUS9?usp=sharing

DedUp reference tools

If you need to know about Salesforce deduping tools refer to the following link:

https://www.classy.org/blog/salesforce-duplicate-management-nonprofit-guide/

Tuesday, July 19, 2016

Developer: Cannot have more than 10 chunks in a single operation. Please rearrange the data to reduce chunking.

Recently while trying to solve a "Too many DML rows.." error, I ran into the following
error "Cannot have more than 10 chunks in a single operation. Please rearrange the data to reduce chunking."

This error occurs when sObject contains more then 10  object types or combinations.

Basically, to work around the "Too many DML rows" error, I had created a @future method with a single delete DML statement on an sObject which had different objects in it.

To work around this chunking error, I had to create seperate @future calls from the same method based on specific Object Type. This resolved the erorr.

Wednesday, July 13, 2016

Developer: Salesforce Order of Execution of things...

Every once in a while you run into a issue which does not make sense.

I created a simple WF rule which would not fire at all. After careful evaluation, I realized that the one of the fields that I was checking for was being set thru an Approval process. Prior to this, 3 other fields on the same object were being updated, the After Update trigger on the concerned object would fire but the workflow would not.

I did the usual checks on moving the rule to execute on "Created and Edited" and found that my conditions were good.

On checking the Approval Process, I found that the Re-Evalute WF rules on update was unchecked.
On checking this flag, everytime the field was updated thru the Workflow Process was getting evaluated and executed.


Friday, June 24, 2016

Developer: “Compiled formula is too big to execute (xxxxx characters). Maximum size is 5,000 characters,”

If you have ever hit this error “Compiled formula is too big to execute (xxxxx characters). Maximum size is 5,000 characters,” then it means that is it time to revisit the implemented formula
and refine it.

This does not in the literal sense mean that you have 5000 chars in your formula, it just means that there are either: too many nested IF's, formulas referring other formulas etc.

Following are some of the approaches that you can take to resolve this error:


  • Use CASE Instead Of Nested IFs--Implementing this has usually worked for me
  • Use Workflow Field Update--the formula field here has a larger capacity and hence might
       accomodate your formula but be careful to ensure that this update is executed only as needed
  • Use an Apex Trigger
Thanks

Friday, June 17, 2016

Administrator: No Portal available error....

I was trying to setup Partner Portal on my local and getting this error. Basically, you need to create


  • Account and Enable as Partner Account.
  • Create a Contact and associate it to the Partner Account.
  • Create a User record and associate the Contact record to the Partner User.

From Setup---Portal Settings; Identify the right profile that needs to be associated to the Portal and then associate this Profile to the User record.

You should now be able to login to Partner Portal on your local.