• inbox outbox 7
  • NEWBIE
  • 180 Points
  • Member since 2021

  • Chatter
    Feed
  • 0
    Best Answers
  • 2
    Likes Received
  • 0
    Likes Given
  • 61
    Questions
  • 17
    Replies
Please tell me different approaches of dealing with this issue. 

If the callout is from UI (button) or a flow (external service), the response data is invalid and there is a valdation rule on that field (response data), same transaction and user is expecting to see the result on UI.
I can have custom object which stores the failed data, but how about saving the record in this instance since validation rule doesn't let us?

I am looking for approaches to save the record when we have a validation rule instead of using code.

I can think of two ways to save the record: 
1. In the validation rule: which lets the record to be saved if the field is blank. For example having CONTAINS OR BEGINS functions in the formula. 
2. Instead of a validation rule, no code, we can do the callout from apex and have the validation there, if there is invalid or failed validation, to manipulate the data to allow the record to be saved. 



 
I can save the failed data/invalid data  in a custom object, and later on find a way to use it as per the requirement. 
Kindly tell me different approaches as to how we can handle this failed validation data in the object?
Server down, network issue etc. 
Could you please specifiy the issues we would have during a callout?
All the issues please. 
Let's say: batch class and a callout, what issues would we have?
@future method and a callout: what issues would we face?
Callout from a flow: salesforce connect, external objects, record triggered flow (asynchronous path), outbound message?

 
What if we get invalid data, how do we deal with that?
 

Under reliable message service => apex callouts
The above line is from this paragraph:
Salesforce doesn’t provide explicit support for reliable messaging protocols (for example, WS-ReliableMessaging). We recommend that the remote endpoint receiving the Salesforce message implement a reliable messaging system, like JMS or MQ. This system ensures full end-to-end guaranteed delivery to the remote system that ultimately processes the message. However, this system doesn’t ensure guaranteed delivery from Salesforce to the remote endpoint that it calls.

https://developer.salesforce.com/docs/atlas.en-us.integration_patterns_and_practices.meta/integration_patterns_and_practices/integ_pat_remote_process_invocation_fire_forget.htm
Let's say we have process integration, the order is created in a backend system, we send the order details and the user gets the order status and order number and some other field called field_c, this field_c has to be validated before being updated in saleforce. 
Can we do that?
 
Callbacks in outbound messages provide a way to mitigate the impacts of out-of-sequence messaging. 
1. What is out-of-sequence messaging? could someone give me an example to better understand?
== 
Retrieving more data—A single outbound message can send data only for a single object. A callback can be used to retrieve data from other related records, such as related lists associated with the parent object.
2. Could someone give me an example of pulling related lists in the callback with an example? 

Thank you
When using middleware, outbound messaging becomes a “first-mile” guarantee of delivery.
What does that mean? Can someone explain with a scenario?
If so, could you please provide me a scenario or an example?
 
We can make a callout by adding CSP site, and use fetch() in the js file. 
We can also make a HTTP request from the apex controller.
I can only think of one thing:
If we are just making a GET request to show some data on LWC, we use fetch api.
If we are doing a process integration, where the response has to updated in to the salesforce and the component has to be re-rendered we use apex controller class. Is that right?
Can someone explain the difference?

Number of synchronous concurrent transactions for long-running transactions that last longer than 5 seconds for each org.2 is 10. 

If more transactions are started while the 10 long-running transactions are still running, they’re denied. HTTP callout processing time isn’t included when calculating this limit.

What is HTTP callout processing time?
I need an example with the code. 
I just need to know how we send the Unique Message ID or 
Unique Record ID in the request.

Please provide me a code
. Process Integration: Asynchronous: 
Workflow - outbound message: Is the remote system able to participate in a contract-first integration in which Salesforce specifies the contract? In some solution variants (for example,
 outbound messaging), Salesforce specifies a contract that the remote system endpoint implements.
What is contract-first integration?


https://developer.salesforce.com/docs/atlas.en-us.integration_patterns_and_practices.meta/integration_patterns_and_practices/integ_pat_remote_process_invocation_fire_forget.htm
 1. Can we do a SOAP or REST callout from an apex controller class?
If so, how can we do it? Is it from within the @AuraEnabled method?

To give you guys more context, I have some more information below:
Salesforce Lightning—Lightning component or page initiates a synchronous Apex SOAP or REST callout.
Salesforce Classic—A custom Visualforce page or button initiates a synchronous Apex SOAP callout.

A user-initiated action on a Visualforce page or Lightning page then calls an Apex controller action that then executes this proxy Apex class to perform the remote call.


This is a followup question:
2. What about fetch API and fetch() method of Javascript, can't we do a request and response from the client side controller (JS file) itself instead of calling a proxy apex class?
 
I can only think of a button or a quick action. 
Any other options please?

 
What I am trying to achieve is to ensure CRUD and FLS using Security class method stripInaccessible()/ DescribeFieldResult. Also after doing that I am updating the fields which are inaccessbile to user with NULL. 

I have trouble when it is a relationship query. 
Basically what I am trying to understand is how can we return in this scenario when you have query on a MAP


SECURITY.STRIPINACCESSIBLE
public with sharing class practController {
    @AuraEnabled(cacheable = true)
    public static List<Temple__c> getRecordsMethod(){  
        try {
            SObjectAccessDecision securityDecision = Security.stripInaccessible(AccessType.Readable, [SELECT Name, 
                                      (SELECT Name, OwnerId, Type__c FROM ChildObjects__r )     
                                                                                                 FROM Temple__c ]);
            Map<String, Boolean> childMap = New Map<String, Boolean>();
            List<ChildObject__c> childObjectList = securityDecision.getRecords();
            Set<String> removedFilds = securityDecision.getRemovedFields().get('ChildObject__c'); 
            for(ChildObject__c child: childObjectList ){
                for(String fieldName: removedFilds){
                        childMap.put(fieldName, NULL);
                }
            }                
            return $$$$$$$$$$$       
        return securityDecision.getRecords();   ??????      
            }catch (Exception e) {
            throw new AuraHandledException('The error code is' + e.getMessage()  + ', the line is' + e.getLineNumber() + ', error type is ' + e.getTypeName() + '& the stackTraceString is' + e.getStackTraceString() + '.');
        }
    }
}
DESCRIBEFIELDRESULT CLASS METHODS:
public with sharing class practController {
    @AuraEnabled(cacheable = true)
    public static List<Temple__c> getRecordsMethod(){  
        try {
                    
           Map<String, ChildObject__c> childMap = New Map<String, ChildObject__c>([SELECT Name, (SELECT Name, OwnerId, Type__c FROM ChildObjects__r )     
                                                                               FROM Temple__c ]);
           Map<String, Schema.SObjectField> fieldMap = Schema.SObjectType.ChildObject__c.fields.getMap();
            Map<String, Boolean> fieldToAccessibility = New Map<String, Boolean>();
            For(ChildObject__c child: childMap.values()){
                    Set<String> populatedFields = child.getPopulatedFieldsAsMap().keySet();
                    for(String fieldName: populatedFields){
                        Boolean isAccessible = fieldToAccessibility.get(fieldName);
                        if(isAccessible == NULL){
                            isAccessible = fieldMap.get(fieldName).getDescribe().isAccessible();
                            fieldToAccessibility.put(fieldName, isAccessible);
                        }
                        if(!isAccessible){
                            fieldToAccessibility.put(fieldName, NULL);
                        }
                    }
                }
            }
        return ????????
             
            }catch (Exception e) {
            throw new AuraHandledException('The error code is' + e.getMessage()  + ', the line is' + e.getLineNumber() + 
                                            ', error type is ' + e.getTypeName() + '& the stackTraceString is' + e.getStackTraceString() + '.');
        }
    }
}


 
Below code is not following the best practices, governor limits, readability and also maintainability. Also I don't have complete requirement details. 

Please help. 

I have two methods below. 

1st Method: 
 This method is meant to find Contacts associated with the Institution (Account) on an Event record, then create Support Staff and/or Primary Support Staff records to link those Contacts to the Event
 
public static void AddPrimaryContacts(Map<Id, Event__c> oldTrgMap, Map<Id, Event__c> newTrgMap) {
        Map<Id,Event__c> eventsMap = new Map<Id,Event__c>();
        List<Support_Staff__c> SSList = new List<Support_Staff__c> ();
        List<Support_Staff__c> SSListFinal = new List<Support_Staff__c> ();
        for (Event__c e : newTrgMap.values()) {
            if (e.Institution__c != '' && e.Institution__c != oldTrgMap.get(e.Id).Institution__c) {
                eventsMap.put(e.Institution__c, e);
            }
        }
        if (!eventsMap.isEmpty()) {
            List<Contact> PrimaryContactsList = [
                SELECT Id, hed__Primary_Organization__c
                FROM Contact
                WHERE hed__Primary_Organization__c IN :eventsMap.keySet()
            ];
            for (Contact c : PrimaryContactsList) {
                Event__c e = eventsMap.get(c.hed__Primary_Organization__c);
                if (e != null) {
                    Support_Staff__c SS = new Support_Staff__c(
                        Contact__c = c.Id,
                        Event__c = e.Id,
                        RecordTypeId = ExternalRecordtypeId
                    );
                    SSlist.add(SS);
                }
            }
            for (Support_Staff__c staff : SSlist) {
                Boolean aloneSS = true;
                for (Support_Staff__c SS1 : SSlist) {
                    if (staff.Event__c == SS1.Event__c) {
                        aloneSS = false;
                    }
                }
                if (!aloneSS) {
                    staff.Primary__c = true;
                    SSListFinal.add(staff);
                } else {
                    SSListFinal.add(staff);
                }
            }
            try {
                insert(SSListFinal);
            } catch (Exception ex) {
                System.debug(' :: UBC_EventTriggerHelper - AddPrimaryContacts :: ' + ex.getMessage() + ' Trace ' + 
                             ex.getStackTraceString());
            }
        }
    }

Second Method:
  This method checks that a user has registered for a parent Event prior to registering for a child Event. If they have not, an error is returned on the child Event Registration record.
public static void ValidateParentRegBreakout(List<Event_Registration__c> newTrgLst, Map< ID , Event_Registration__c> newTrgMap){
        Id BreakoutSessionRID = UBC_Utility.getRecordTypeMap(EVENT_OBJ).get(EVENT_RT_BRE_SES).Id;
        list<Event_Registration__c> ParentEventsRegList = new list<Event_Registration__c>();
        list<id> ParentEventsList = new list<id>();
        list<id> ContactsList = new list<id>();
        
        List<Event_Registration__c> EventsRegList0 = [
            Select id, Contact__c, Contact__r.id, Event__c, Event__r.Parent_Event__c, Event__r.RecordTypeId 
            from Event_Registration__c 
            where Event__r.RecordTypeId =: BreakoutSessionRID and Id in :newTrgLst
        ];
        
        for (Event_Registration__c er : EventsRegList0){
            ParentEventslist.add(er.Event__r.Parent_Event__c);
            Contactslist.add(er.Contact__r.id);
        }
        
        if (EventsRegList0!=null && !EventsRegList0.isEmpty()){
            for (Event_Registration__c er : [
                Select id, Contact__c, Contact__r.id, Event__c, Event__r.Parent_Event__c, Event__r.RecordTypeId 
                from Event_Registration__c 
                where Event__r.RecordTypeId =: BreakoutSessionRID and Id in :newTrgLst])
            {
                boolean error=True;
                for (Event_Registration__c er2 : [
                    Select Id, Event__c, Contact__c 
                    from Event_Registration__c 
                    where Contact__c in:Contactslist 
                    and Event__c in :ParentEventslist])
                {
                    if (er.Event__r.Parent_Event__c == er2.Event__c && er.Contact__c == er2.Contact__c){
                        error=False;
                    }
                }
                if (error==True){
                    newTrgMap.get(er.id).Event__c.adderror('Please register at the Parent Event of this Event.');
                }
            }
        }
    }
}

Please help, it is urgent. 
@isTest

private static void testIsAccessible() {
   Map<String, User> users = New Map<String, User>();
     List<Contact> wsContacts;
      System.runAs(users.get('William Shattner')) {
        wsContacts = [SELECT Name, Phone, MailingStreet FROM Contact];
        Map<String, Schema.SObjectField> fieldMap = Schema.SObjectType.Contact.fields.getMap();
        Map<String, Boolean> fieldToAccessibility = new Map<String, Boolean>();
        for (Contact contact : wsContacts) {
            Set<String> populatedFields = contact.getPopulatedFieldsAsMap().keySet();
            for (String fieldName : populatedFields) {
                Boolean isAccessible = fieldToAccessibility.get(fieldName);
                if (isAccessible == null) {
                    isAccessible = fieldMap.get(fieldName).getDescribe().isAccessible();                  fieldToAccessibility.put(fieldName,isAccessible);
                }
                if (!isAccessible) {
                    contact.put(fieldName, null);
                }
            }
        }
     }
     System.debug(wsContacts);

The code which needs to be corrected is in bold letters. 
I have trouble quering inside a map. 


Thank you
  Map<String, Schema.SObjectField> fieldMap = Schema.SObjectType.Prasadam__c.fields.getMap();


'SObjectField' would be fieldName.
What about the string here? 
Kindly help me understand, this code. Thank you. Code is good, I am just trying to understand here. 

For your reference below is the rest of the code. 
@isTest

private static void testIsAccessible() {
    Map<String, User> users = getUsers();
    List<Contact> wsContacts;
    System.runAs(users.get('William Shattner')) {
        wsContacts = [SELECT Name, Phone, MailingStreet FROM Contact];
        Map<String, Schema.SObjectField> fieldMap = Schema.SObjectType.Contact.fields.getMap();
        Map<String, Boolean> fieldToAccessibility = new Map<String, Boolean>();
        for (Contact contact : wsContacts) {
            Set<String> populatedFields = contact.getPopulatedFieldsAsMap().keySet();
            for (String fieldName : populatedFields) {
                Boolean isAccessible = fieldToAccessibility.get(fieldName);
                if (isAccessible == null) {
                    isAccessible = fieldMap.get(fieldName).getDescribe().isAccessible();                  fieldToAccessibility.put(fieldName,isAccessible);
                }
                if (!isAccessible) {
                    contact.put(fieldName, null);
                }
            }
        }
     }
     System.debug(wsContacts);

 
I never came across this scenario and I need your input. 

You have a class with sharing, you have another class without sharing, without sharing class is callig a method in with sharing class, how does the sharing context work?


 
I am looking for a scenario as to, when we use apex sharing over declarative ways. 
 
Thank you!
What if we get invalid data, how do we deal with that?
 
Let's say we have process integration, the order is created in a backend system, we send the order details and the user gets the order status and order number and some other field called field_c, this field_c has to be validated before being updated in saleforce. 
Can we do that?
 
When using middleware, outbound messaging becomes a “first-mile” guarantee of delivery.
What does that mean? Can someone explain with a scenario?
I can only think of a button or a quick action. 
Any other options please?

 
Whenever a contact is inserted, if that contact is associated with an account, then update that account name from this  newly inserting contact name. It has to be bulkified.  If the contact name is "John", then the associated account's name should also be "John:

public Contact trigger updateAccount (AFTER INSERT){

Map<Id, Account> accountList = New Map<Id, Account> ();


for(Contact con: Trigger.New){

   if(con.AccountId){

    Account acc = New Account();
    acc.Name = con.LastName;
    acc.Id = con.AccountId;
    accountList.put(acc.Id, acc);

   }
}
UPDATE accountList.values();
}

I would like to know why we would get an error if we use LIST in production and that we have to use either MAP or SET.
What is designing exactly? Like job responsiblities involved in designing?
When I say design (analysis, design, implementation etc?

I only can think of designing how the template looks (lwc template)?
Is there anything else that I am missing. 

Please advice. 



Thank you. 
1. Batch class can work on upto 50k records using Iterator. Is that right?
2. If you use an iterable, the governor limit for the total number of records retrieved by SOQL queries is still enforced. For more information on using iterables for batch jobs
3.  If the start method of the batch class returns an iterable, the scope parameter value has no upper limit. However, if you use a high number, you can run into other limits. The optimal scope size is a factor of 2000, for example, 100, 200, 400 and so on.

I am bit confused with these limits. Please explain. 
 

Map<Id,List<Opportunity>> addOppurnitieswithaccount = new Map<Id,List<Opportunity>>();

Roll up summary kind of thing.

I am just lost. 



Map<Id,List<Account>> acctsWithOpps = new Map<Id,List<Account>>();
System.debug(acctsWithOpps.values());
List<Opportunity> oppl = [SELECT Account.Name, Name FROM Opportunity WHERE Id =: acctsWithOpps.values()];
for(Opportunity opp: acctsWithOpps.values()){
    system.debug(opp.Name);
}.

Please advice. 
 
I am looking for only lightning-input not a combobox, or select/option tags or bullets, an input field (account search).

anyone?
I am looking for a scenario as to, when we use apex sharing over declarative ways. 
 
Thank you!
Hi all, 
Happy New Year!


Could you guys tell me the scenarios as to when we use callouts in batch apex?
I would like to point out that I am looking for input on the scenarios that you guys faced or know/read about. 
I am inclined more towards when than the how part of this. 

 
Below is the code:
Test class doesn't cover the bold part of the code. 
@httpGet
    global static accountWrapper accountInformation(){
        RestRequest req= Restcontext.request;
      // String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        String requestURI= req.requestURI;
        String accountId= requestURI.substringAfterLast('/');
        List<Account> accList= [SELECT ID, Name, Rating, Description, Industry, Phone, Fax
                                FROM Account WHERE ID =: accountId];
        
        List<Contact> conList= [SELECT ID, Name, FirstName, LastName, Email, Phone 
                                FROM Contact WHERE accountId IN: accList ];
        
        List<Case> caseList= [SELECT Id, CaseNumber, Subject, Description, Status, Owner.Name
                              FROM Case WHERE accountId IN: accList];
        
        accountWrapper wrapper= new accountWrapper();
        if(!accList.isEmpty()){
            wrapper.accountRecord= accList.get(0);
            wrapper.conList= conList;
            wrapper.caseList= caseList;
        }
        
        return wrapper;
    }

  global class accountWrapper{
        global Account accountRecord;
        global List<Contact> conList;
        global List<Case> caseList;
    }
Test class:
@isTest
    public static void deleteAccountTest(){
        String recordId= createTestRecord();
        String url= '/services/apexrest/v1/Account'+recordId;
            
        RestRequest req= New RestRequest();
        req.httpMethod= 'DELETE';
        req.requestURI= url;
        
        RestContext.request= req;
        
        try{
        Test.startTest();
        AccountManager.deleteAccount(	);
        Test.stopTest();
        }catch(system.Exception ex){
            system.assertNotEquals(null, ex.getMessage());
        }
    }


    static Id createTestRecord(){
        Account testAcc= New Account();
        testAcc.Name= 'testAccount';
        INSERT testAcc;
        
        Contact testCon= New Contact();
        testCon.LastName= 'test contact';
        testCon.AccountId= testAcc.Id;
        INSERT testCon;
        
        return testAcc.Id;
        
    }



 
========================== CLASS====================

@httpDelete
    global static String deleteAccount(){
        RestRequest req= Restcontext.request;
        String requestURI= req.requestURI ;
        String accountId= requestURI.substringAfterLast('/');
        List<Account> accList= [SELECT ID, Name, Rating, Description, Industry, Phone, Fax
                                FROM Account WHERE ID =: accountId];
        if(accList != null && accList.size() >0 ){
            try{
               DELETE accList; 
               return '{"message": "Account deleted"}';
            }Catch(system.Exception ex){
                String errorMessage= ex.getMessage();
                return '{"message":"'+errorMessage+'"}';
            }
        }else{
            return '{"message": "No record found"}';
        }
    }

====================TEST CLASS===================
 @isTest
    public static void deleteAccountTest(){
        String recordId= createTestRecord();
        String url= '/services/apexrest/v1/Account'+recordId;
            
        RestRequest req= New RestRequest();
        req.httpMethod= 'DELETE';
        req.requestURI= url;
        
        RestContext.request= req;
       
        Test.startTest();
        AccountManager.deleteAccount(	);
        Test.stopTest();
    }

 static Id createTestRecord(){
        Account testAcc= New Account();
        testAcc.Name= 'testAccount';
        INSERT testAcc;
        
        Contact testCon= New Contact();
        testCon.LastName= 'test contact';
        testCon.AccountId= testAcc.Id;
        INSERT testCon;
        
        return testAcc.Id;
        
    }
I have trouble with the try catch block.