2

First of all, i've read most other posts about this error. The problem i have here is the code that was written in my org is using an UPSERT so don't see the spot where i can use the FOR UPDATE to avoid this. Error:

Exception: Upsert failed. First exception on row 0; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record: [] Stack Trace: Class.TransactionWS.insertTransaction: line 165, column 1

Line 165 :

upsert listTransactionInsert Reference__c;

This call is done in a WS @httpPost function which i copy here:

@HttpPost
global static UtilsWS.JSONResponseList insertTransaction(){    
    String error;
    Boolean res;
    String message;
    UtilsWS.ProcessedData processedData = new UtilsWS.ProcessedData();

    try{
        // Check if the WS is enabled
        UtilsWS.checkWSEnabled('TransactionWS');

        // Get request data and deserialize Json
        String bodyString   = RestContext.request.requestBody.toString();
        List<JsonTransaction> listReq = (List<JsonTransaction>) JSON.deserialize(bodyString, List<JsonTransaction>.class); 

        // Check record amount limits 
        if(listReq.size() > 500){
            throw new UtilsWS.wsException('The max amount of records is 500');
        } 
        if(listReq.size() < 1){
            throw new UtilsWS.wsException('There is not records to insert');
        }               

        // Get and map the RecordTypeIds for all transactions
        for(RecordType rt : [SELECT id, developerName FROM RecordType WHERE sObjectType = 'Transaction__c']){
            if(rt.developerName == 'Order'){
                TransactionWS.mapTypeRecordTypeId.put('Order', rt.Id);
            }else if(rt.developerName == 'Trading'){
                TransactionWS.mapTypeRecordTypeId.put('Trade', rt.Id);
            }else if(rt.developerName == 'Invoicing'){
                TransactionWS.mapTypeRecordTypeId.put('Invoice', rt.Id);
            }else if(rt.developerName == 'Clearing'){
                TransactionWS.mapTypeRecordTypeId.put('Clearing', rt.Id);
            }  
        }

        Map<String,JsonTransaction> mapTransactionProvidersBeneficiary = new Map<String, JsonTransaction>();
        Map<String,JsonTransaction> transactionProvidersBeneficiary = new Map<String, JsonTransaction>();
        List<String> listClients = new List<String>();

        Set<String> companies = new Set<String>(),
                    names = new Set<String>(),
                    salespersons = new Set<String>();

        for(JsonTransaction a: listReq){
            listClients.add(a.company_id);
            salespersons.add(a.salesperson_reference);
            if (a.record_type == 'Trade'){
                listClients.add(a.counter_company_uid);
                if (a.beneficiary_type == 'provider'){
                    // We will use the the email to map their transactions. It email field is empty we will use a composed company+lastName as key
                    if(!String.isBlank(a.email)){
                        mapTransactionProvidersBeneficiary.put(a.email.toLowerCase().trim(), a);
                    }else{
                        if(!transactionProvidersBeneficiary.containsKey(TransactionWS.generateKey(a))){
                            transactionProvidersBeneficiary.put(TransactionWS.generateKey(a),a);
                        } 
                        if(!companies.contains(a.beneficiary_name)){
                            companies.add(a.beneficiary_name);
                        }  
                        if(!names.contains(a.provider_contact_name)){
                            names.add(a.provider_contact_name);
                        } 
                    }
                } 
            }               
        }

        // We map the myorg User Id with the SFDC Id for all Users involved
        UtilsWS.getUsersMap(salespersons); 

        // Mapping of myorg Account Id with the Account Ids.
        for (Account a : [SELECT Id, myorg_Account_ID__c, Name FROM Account WHERE myorg_Account_ID__c IN :listClients]){
            TransactionWS.mapCompanyAccountId.put(a.myorg_Account_ID__c, a);
        }

        // If there isn't any account in our DB with these myorg Account Id
        if(mapCompanyAccountId.size()<= 0){
            throw new UtilsWS.wsException('The clients should exists on Salesforce. Client list: '+listClients);
        }        

        List<Transaction__c> listTransactionInsert = new List<Transaction__c>();
        for(JsonTransaction a: listReq){
            listTransactionInsert.add(a.setSFTransaction(new Transaction__c()));
        }

        /** Process to create leads from providers begins**/
        List<Lead> listLeadInsert = new List<Lead>();
        List<Task> listTaskInsertNewLeads = new List<Task>();

        // If already exists an account with the provider's email we remove it from the list.
        for (Account a : [SELECT Id, Company_Email__c FROM Account WHERE Company_Email__c in :mapTransactionProvidersBeneficiary.keySet()]){
            JsonTransaction jt = mapTransactionProvidersBeneficiary.remove(a.Company_Email__c);
        }

        // If already exists a contact with that email it's removed too. 
        for(Contact c : [SELECT Id, Email FROM Contact WHERE Email in :mapTransactionProvidersBeneficiary.keySet()]){
            mapTransactionProvidersBeneficiary.remove(c.Email);
        }

        // If already exists a lead with that email or from that company, we create a new task for the existing email.
        for (Lead l : [SELECT Id, LastName, Company, Email FROM Lead WHERE Email in :mapTransactionProvidersBeneficiary.keySet() OR (LastName in :names AND Company in :companies)]){
            if( !String.isBlank(l.Email) && mapTransactionProvidersBeneficiary.containsKey(l.Email)){
                JsonTransaction jt = mapTransactionProvidersBeneficiary.remove(l.Email);
            }else if(transactionProvidersBeneficiary.containsKey(generateKey(l))){
                transactionProvidersBeneficiary.remove(generateKey(l));
            }
        }

        // If we didn't find any Lead, Contact or Account, we create a new Lead.
        for (JsonTransaction jt : mapTransactionProvidersBeneficiary.values()){
            Lead l = new Lead(
                    lastName = jt.provider_contact_name,
                    Email = jt.email,
                    Company = jt.beneficiary_name,
                    CountryCode = jt.beneficiary_country,
                    Bank_Name__c = jt.beneficiary_bank,
                    Bank_Iban__c = jt.beneficiary_iban,
                    Type__c = jt.beneficiary_type,
                    Description = 'Currency Received: '+jt.buy_currency,
                    OwnerId= UtilsWS.getUserId(jt.salesperson_reference),
                    Source_Spec__c = SOURCE_SPEC,    
                    LeadSource = PROVIDERS_SOURCE);
            if(TransactionWS.mapCompanyAccountId.containsKey(jt.company_id)){
                l.Description = 'This Lead is a provider of ' + TransactionWS.mapCompanyAccountId.get(jt.company_id).Name + '\n' +l.Description;
            } 
            listLeadInsert.add(l);
        }

        for(JsonTransaction jt : transactionProvidersBeneficiary.values()){
                    Lead l = new Lead(
                    lastName = jt.provider_contact_name,
                    Company = jt.beneficiary_name,
                    CountryCode = jt.beneficiary_country,
                    Bank_Name__c = jt.beneficiary_bank,
                    Bank_Iban__c = jt.beneficiary_iban,
                    Description = 'Currency Received: '+jt.buy_currency,
                    Type__c = jt.beneficiary_type,
                    OwnerId= UtilsWS.getUserId(jt.salesperson_reference),
                    Source_Spec__c = SOURCE_SPEC,    
                    LeadSource = PROVIDERS_SOURCE);
            if(TransactionWS.mapCompanyAccountId.containsKey(jt.company_id)){
                l.Description = 'This Lead is a provider of ' + TransactionWS.mapCompanyAccountId.get(jt.company_id).Name + '\n' +l.Description;
            } 
            listLeadInsert.add(l);
        }
        if (listTransactionInsert.size()>0){
            upsert listTransactionInsert Reference__c;             
        }  
        if(listLeadInsert.size()>0){
            insert listLeadInsert;
            // We create a task for Sales to check the new leads created. We can disable it using the custom settings.
            if( ControlEnabled__c.getValues('ProviderTasks')!=null && ControlEnabled__c.getValues('ProviderTasks').Enabled__c){
                String taskSubject = label.ProvidersSubject;
                String taskDescription = 'Hello\nA new provider has been created as Lead as it is beneficiary of a Trade. Please contact with them for follow up\nRegards\nmyorg';              
                for (Lead l : listLeadInsert){
                    JsonTransaction jt = mapTransactionProvidersBeneficiary.remove(l.Email);
                    Task t = new Task (Subject = taskSubject, 
                                       Description = taskDescription, 
                                       WhoId = l.Id, 
                                       Type  = 'Record Assignment', 
                                       OwnerId = l.OwnerId);
                    listTaskInsertNewLeads.add(t);
                }               
            }
        }
        if (listTaskInsertNewLeads.size()>0){
            insert listTaskInsertNewLeads;
        } 
        if(processedData.errors.size()>0){
            UtilsWS.generateRESTErrorLog(bodyString, FOLDER_ID,processedData.errors);
            message = 'KO';
        }
        else{
            message ='OK';
        }    
        res = true;
    } 
    catch(Exception e){
        res = false;
        message = e.getMessage();
        processedData = null; 
        Util.sendExceptionEmail('TransactionWS Exception',e);
        UtilsWS.generateRESTExceptionLog(RestContext.request.requestBody.toString(), FOLDER_ID, e);         
    }
    return new UtilsWS.JSONResponseList(res,message,processedData );
 }

I actually don't see how to avoid getting the UNABLE TO BLOCK ROW error, i get it once in a while but we could lose some important transactions on the way.

Maybe it's a silly question, but i actually don't see how to merge all what I've seen about this problem and what I have at the moment, so i would be very grateful if someone could point out if i'm missing something.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.