Monday, June 18, 2018

Search Content on Box from Salesforce Using Content Search API

In this blog, I am going to share the code snippet which can be used to do callout from Apex in order to search content on Box. You need to have access token in order to perform this callout.

To learn how to get access token from box, please refer Box and Salesforce Integration

Box provide content search API through which you can search for files and folders present in Box.
I have created a wrapper class in apex which will be used to parse the JSON response from Box.

Below is code snippet:

You can call this static method and pass the parameters to get results.

Hope this will help!!

Friday, June 1, 2018

Alternatives to OnClick Javascript buttons : Way to replace OnClick Javascript buttons across all objects with Single VF page

We always prefer onclick javascript button to perform different operations like updating fields on same records or on other records with single click by user. In order to do this, we either use ajax toolkit to either perform logic or to call apex method.

We can also perform these operation even by redirecting user to VF page on click of button and call apex method on VF page load (by specifying action attribute on <apex:page>) and redirecting User back to record details page.

Developers usually not use this approach as they do not want to create new VF page every time for these kind of requirements.

After the launch of lightning, onclick javascript buttons are not recommended and everyone is finding alternative for onclick javascript buttons functionality but sometime these alternative results in more than 1 click for end user.

Through this blog, I just to share one approach through which we can utilize single VF for all custom buttons. We just need to pass recordId and apex class name which contains your logic for operation in URL. This approach also involves single click from user and user will get notified about success and failure of operation (in onclick javascript we user alert to notify).

Different steps involved for this approach:
  • Create a VF page and controller. Create wrapper in this controller to store redirect url (to redirect user after performing operation), success and failure message which you want to display to user.
  • Create an Interface with method name executeLogic (return type will be wrapper of VF controller).
  • Create a new apex class which implements interface and will contain logic in executeLogic method.
  • Create a custom button and specify URL. pass recordid and apex class name where you have written your logic.

Sample Requirement:

I need to create a custom button on Account. When user click on that, I need to check if billing country and billing postalcode in not blank, then change the type field to 'Prospect'.

Traditional Approach:

Create a onclick Javascript button and call apex method from that to perform operation. Dispaly success/error message using alerts.

New Approach:

Below are code related to new approach:

Now create custom button on Account as mentioned in below image

URL will be like:

/apex/OnClickJSUtilityVF?rid={!Account.Id}&cname=AccountUtility

here "AccountUtility" is apex class name which contain logic.

If we use this approach then, going forward we just need to create apex class with method and implement the interface.

If we consider the both approaches, the amount of code that we need to write for any new custom button functionality will remain same.

Demo snapshots:

When I click on Change to Prospect button with billing country and billing postal code as blank, getting below message:

When clicking on Change to Prospect button after specifying values for billing country and postal code, getting below message:

These success and error message are specified in apex method in apex class. So you can specify different message based on different requirements.

Also you can specify the redirect URL in apex method where user will navigate after performing the requested action.

You can style your VF page as per your org need and all users will have same user experience.

Hope this will help!!!

Looking forward for everyone comments and suggestions.

Sunday, May 20, 2018

Adding button and sorting columns in Lightning DataTable

Salesforce has launched Lightning:Datatable tag to display list of records in lightning components.

In this blog, I will share the code through which we can add a button in column and call javascript controller function on click of that button. Also I will share the code required to enable sorting on columns for datatable.

Use case: Display list of account records along with view button and onclick of that button call javascript controller function. Once the javascript controller function is invoked, you can open any other component or redirect user to account detail page as per requirement.

In order to add button, you have to specify input type as button and provide type attributes while specifying the columns.

{
label: 'Action',
type: 'button',
typeAttributes: {
iconName: 'utility:view',
label: 'View Record',
name: 'viewRecord',
disabled: false,
value: 'viewBtn'
}
}

you can use onrowaction event on lightning:datatable to call javascript controller function.

Below is sample code which includes sorting as well as button in one of the columns:


Below is snapshot:

Click here for  Lightning DataTable Demo .

Hope this will help!!!


Sunday, April 15, 2018

Data Architecture and Management Designer : Things to consider before appearing for this exam

Today is very special day for me as I have completed my Application Architect exam by completing second exam (Data Architecture and Management Designer) on Architect journey and this is my 100th blog on Salesforce.

I would like say big thanks to Salesforce community who motivated for this and provided their support to achieve this.



Through this blog, I am going share my preparation experience and tips for everyone who all are planning for this.
  • For self study, please refer Resource Guide for Data architecture and management designer, which contains all the study material links for different topics. If you complete this, then you are ready for this exam. 
  • Development knowledge is not necessary for this exam but if you have development experience then you can easily understand Large Data Volume considerations easily.
  • Exam contains lot of scenario based question. Most of question are like which decision or step you will take for given problem being Data Architect.
  • Different ways of maintaining data quality.

Below are different topics which you need to cover for exam. Also I have accumulated below information from different source in place for quick overview.
  • Duplicate Management
Please go through matching rules and Duplicate rules and how to configure them
Different option which you configure when duplicate detected(Alert, Block, reporting etc)
  • Data Archiving and Purging
There were many question on for specific scenarios how to implement data archiving. Also cover on which case, we should use ETL tools.

Different points to remember:
    1. Aggregate info on parent object and delete child object if reporting is required only in parent info.
    2. Always plan for data archiving and purging as data keeps on increasing with time.
    3. Records in recycle bin also affects query performance so if you don't want records, then perform hard delete.
  • MDM Solution
When you have different application and different data stored in different application for customers, then implement MDM solution to have single source of truth for records. 
  • PK Chunking
You can use PK Chunking with most standard objects and all custom objects.

To enable the feature you specify the header ‘Sforce-Enable-PKChunking‘ on the job request for your Bulk API query.

                           Sforce-Enable-PKChunking: 

By default the Bulk API will split the query into 100,000 record chunks – you can use the ‘chunkSize‘header field to configure smaller chunks or larger ones up to 250,000. Larger chunk sizes will use up fewer Bulk API batches, but may not perform as well. For each object you are extracting, you might need to experiment a bit to determine the optimal chunk size.

                       Sforce-Enable-PKChunking: chunkSize=250000;

You can perform filtering while using PK Chunking by simply including a WHERE clause in the Bulk API query. In this case, there may be fewer records returned for a chunk than the number you have specified in ‘chunkSize‘. 

If an object is supported, you can also use PK Chunking to query the object’s sharing table. In this case, determining the chunks is more efficient if the boundaries are defined on the parent object record IDs, rather than the share table record IDs. To take advantage of this, you should set the value of the Parent header field to the name of the parent object. For example, when querying OpportunityShare, set Parent to Opportunity.

For example:
Customer is planning a security audit and wants to identify all the manual shares that exist on their Account records. To execute this, they can perform a bulk query on AccountShare, using the filter WHERE rowCause=Manual, with a header like this: 

                   Sforce-Enable-PKChunking: chunkSize=250000; parent=Account 
  • Data Governance & Data Stewardship
Data governance includes what type of information is required, who can create it and update it and specify quality rules(data  integrity, usability and security)

Data Stewardship includes how to maintain data and its distribution to its users.
  • Skinny Tables
You can refer this blog for Skinny Tables Overview
  • Bulk API
Cover different scenario on when to use parallel mode or serial mode for Bulk API.
If you are getting lock contention errors, then load child records order by parent record Id.
If you getting group membership locks, then use serial mode for Bulk API.
Lock contention errors may occur if you have master detail, lookup relationship and roll up summary fields defined.
Avoid full relaod operations as it will consume more resource. Try to perform incremental upload.

Please refer LDV Best practices link. It covers most of the topics for this exam.

Problem Statements

Slow report on a large object 
  • Document your org’s indexed fields.
  • Learn index selectivity rules.
  • Build reports that use indexes.
  • Don’t use formula fields (returning non-deterministic values) in filter as they are calculated on fly which will reduced the performance
 
Slow bulk data load 
  • Cleanse and transform data pre-load.
  • Disable triggers, validations, assignment rules,and workflow rules pre-load.
  • Use the Bulk API.
  • Keep a Full Queue : The Force.com platform cannot process what it doesn’t have the opportunity to process, and slowly feeding batches and jobs to Salesforce causes platform threads to sit idle when they could be processing batches. Always try to keep at least 20 batches on the queue at any given time. 

Lock contention problems while data load
  • Pre-sorting the child records by parent Id in CSV file to lessen the chance of parent record lock contention among parallel load batches
  • By deferring the org’s sharing calculations until data load finish, could significantly increase both the load and sharing calculation performance.
  • For optional lookup fields, you can avoid the locks by setting the Clear the value of this field option, which does more than just tell Salesforce what to do if your lookup record is deleted. When you set this option, whenever a record that has a lookup field to this lookup record is inserted or updated, Salesforce doesn't lock the lookup records; instead it only validates that the lookup values exist.
  • Roll Up Summary Fields : Salesforce locks those master records so it can update the appropriate roll-up summary field values. If detail records that look up to the same master record are updated simultaneously in separate batches, and those updates affect roll-up summary fields on the master record, there is a high risk that these updates will cause lock exceptions.
  • Disable triggers and Workflow rules to improve performance. Whenever trigger perform DML on other records of object then salesforce lock those records which may cause lock contention errors in parallel load. When workflow update fields then it lock the records which can result in lock contention errors.
  • Group Membership Locks: For a few special operations, Salesforce uses organization-wide group membership locks. To avoid lock exceptions when performing the following operations, you must use serial processing for your data load. 
    1. Adding users who are assigned to roles 
    2. Changing users’ roles 
    3. Adding a role to the role hierarchy or a territory to the territory hierarchy 
    4. Changing the structure of the role hierarchy or the territory hierarchy 
    5. Adding or removing members from public or personal groups, roles, territories, or queues 
    6. Changing the owner of an account that has at least one community role or portal role associated with it to a new owner who is assigned to a different role than the original owner
Full Database Backups are Slow
  • Perform incremental data backups–only backing up the data that is new or updated since the previous incremental backup. When doing this, use queries that filter records using SystemModstamp (a standard field in all objects that has an index) rather than LastModifiedDate field (not indexed).
When to use serial load option rather than parallel?
  • When you insert group members or users who are assigned to roles—or perform any other data load that requires group membership operations—Salesforce uses organization-wide group membership locks to ensure data integrity and security.
  • If you are not able to manage or avoid lock contention errors then switch to serial mode for data load.

What are Strategies for Addressing Lags in Search Indexing?

Depending on the current load and utilization of indexing servers, asynchronous text index updates may lag behind actual transactions. This lag means that stale search indexes can lead to search results not entirely representative of the current database records.

The amount of time necessary to update search indexes is directly related to the amount of text data that such loads modify, and can be quite lengthy in some cases.
So how can you architect acceptable solutions that address inevitable lags in search indexing after data loads? Here are a couple of things to consider.
  1. Disable full-text search indexing for custom objects (especially large ones) that don’t need to be searchable. 
  2. Instead of relying on the full-text search engine and SOSL, implement your application’s search feature using SOQL. Because SOQL queries target the transactional database, they’ll always return results that correspond to the latest set of committed records.

Hope this will help!!!

Sunday, April 8, 2018

Comparable Interface : Way to perform sorting on wrapper class (non-primitive type that is Lists of user-defined types)

Apex provides comparable interface with compareTo method which can be used sort wrapper class.

You can write your comparison logic in compareTo method to sort wrapper.

Below is sample wrapper class, user-defined data type which implements comparable interface.


Below is sample code which you can run in developer console in execute anonymous block.

List<SK_sortUtilityTestWrapper> wrapperList= new List<SK_sortUtilityTestWrapper>();
wrapperList.add(new SK_sortUtilityTestWrapper('D',50.6));
wrapperList.add(new SK_sortUtilityTestWrapper('A',40));
wrapperList.add(new SK_sortUtilityTestWrapper('B',44.2));
system.debug('****wrapperlist before sorting:'+wrapperList);
wrapperList.sort();
system.debug('****wrapperlist after sorting:'+wrapperList);


Logs:


Hope this will help!!!


Monday, April 2, 2018

Sorting Wrapper List in ASC or DESC order based on Wrapper Property

We get these kind of scenarios in which we have List of wrapper available and want to sort it either in ASC or DESC order based on any member variable wrapper class.

Suppose we have wrapper class as mentioned below:

public class SK_sortUtilityTestWrapper {
public string category{get;set;}
        public decimal count{get;set;}
    public SK_sortUtilityTestWrapper(string ss,decimal sk){
             this.category=ss;
             this.count=sk;
    }
}

Now imagine if we have list<SK_sortUtilityTestWrapper>  and want to sort list based on count value then we can do that by using below code.
I have added a static method which can be called from developer console to see the output for reference.



From developer console execute below script:

SK_WrapperSortUtility.testWrapperListSorting();

You will see below output in debug logs:


 Hope this will help!!!!


Monday, March 26, 2018

Skinny Tables- When/Why to use?

Skinny tables are helpful when you have Large Data Volumes (more than millions of records in object). These tables improves the ready only operations like reports, SOQL query performances. Below are pointers which explain everything about Skinny Tables:

  1. Skinny tables are custom tables (read only) created by Salesforce if enabled by customer support. These tables contains important fields information instead of storing all fields information which is present in actual object.
  2. Skinny tables can be created for Account, Contact, Opportunity, Lead, Case, and custom objects.
  3. The Force.com platform automatically synchronizes the rows between skinny table and the base object,so the data is always kept current. 
  4. Soft delete records ((i.e records in the Recycle Bin with isDeleted = true) are not present in Skinny tables which improves query output.
  5. Custom indexes are also copied if present in base table.
  6. Skinny tables support only few data types(Checkbox,Date,Date and time,Email,Number,Percent,Phone,Picklist (multi-select),Text,Text area,Text area (long),URL).
  7. The Force.com platform determines at query runtime when it would make sense to use skinny tables, so you don’t have to modify your reports or develop any Apex code or API calls
  8. You need to contact salesforce customer support in order to enable this.

Things which needs to be considered before implementing Skinny tables:

  1. Skinny tables can contain maximum of 100 fields. There are also limitation on data type as mentioned above.
  2. After creating Skinny table, if you decide to add one more field in Skinny table, then you have to contact customer support. They will delete existing skinny table and will recreate new one.
  3. If you change the data type of any field which is used in Skinny table, then Skinny table becomes invalid (unusable) and you need to contact customer support to again recreate it.
  4. Skinny tables can not refer fields from another object.
  5. Skinny tables get copied to full copy sandbox after refresh but not on other sandbox. in order copy it for other sandbox, contact customer support.
  6. Skinny tables can increase the query performance of SOQL queries not SOSL queries as SOSL search based on flat file search whereas SOQL is based on database search.