Monday, July 10, 2017

List of Annotations in Salesforce Apex

Usually Annotation means which will specifies the behavior or modifies the way how the particular class or method behaves in salesforce. Based on annotations the functionality or behavior and usage of particular class or method we can simply identify.

  • Each annotation will starts with '@' symbol and followed by name of the annotation
  • To declare a method/class with annotations it must be declared immediately before method/class  
Method with Annotation Example

public class UserHistoryProcessor
{
   @InvocableMethod 
  public static void updateUserHistory(List<Id> userIds)
  {
    //related code here
  }
 
}

List of Available Annotations in Apex
  • @isTest
  • @InvocableMethod
  • @InvocableVariable
  • @future
  • @AuraEnabled
  • @ReadOnly
  • @RemoteAction
  • @TestSetup
  • @TestVisible
  • @Deprecated
Apex REST annotations:
  • @RestResource(urlMapping='/yourUrl')
  • @HttpDelete
  • @HttpGet
  • @HttpPatch
  • @HttpPost
  • @HttpPut
we will discuss about each and every annotations with examples in next post please keep following the blog for latest updates

System.QueryException: List has no rows for assignment to SObject

Usually we will come across this type issue in many places and in many situations also .In the same way I have come across the same issue in one of the my class and I have done some work around it to fix this issue.I will explain this one with an example which may brings you an complete understanding about the issue.

Scenario:
I have 3 objects called Time_Track__c,Expert__c and User.Expert__c and User having a lookup relationship where User (Sforce_User__c) is acting as parent for Expert object and Time_Track__c and Expert__c also having lookup relationship where Time_Track__c is acting as child for Expert (Expert_Name__c) object .I have an visual force page which is using Time_Track__c  as a Standard Controller and I am having some extension class on same page .In the constructor of the extension class I am trying to query on Expert__c object based on logged in user to assign this expert to new time track as shown below

Source Code:
public class TrackExtn {
  public Time_Track__c timeTrack{get;set;} 

  public TrackExtn(ApexPages.StandardController controller) {
    timeTrack = new Time_Track__c();        
    timeTrack= (Time_Track__c)controller.getRecord();
       
    if(controller.getId()==null)
    {
       Expert__c exp = new Expert__c();
       //In below line you will receive List has no rows for assignment to SObject
       exp = [Select id from Expert__c where Sforce_User__c=:UserInfo.getUserId() limit 1];
       timeTrack.Expert_Name__c = exp!=null?exp.id:null;
           
    }

    }
}

Error:

When you execute the above code at run time if your having at least one matching Expert__c record for logged in user it will work very smoothly .If there is no matching Expert__c record for logged in user will end up with System.QueryException: List has no rows for assignment to SObject . Even if the matching record is not there it should continue fir the next lines with out throwing any error but here it's failing and terminating the complete execution. To handle this we need to follow below work around solution.


Workaround Solution:

We need to convert the Query result holder from SObject type to List<SObject> type that will resolve the issue .Please look at the below code for the work around solution
public class TrackExtn {
  public Time_Track__c timeTrack{get;set;} 

  public TrackExtn(ApexPages.StandardController controller) {
    timeTrack = new Time_Track__c();        
    timeTrack= (Time_Track__c)controller.getRecord();
      
    if(controller.getId()==null)
    {
        //Convert Sobject type to List<Sobject> type to store query result
        List<Expert__c> listexp =new List<Expert__c>();
        listexp = [Select id from Expert__c where Sforce_User__c =:UserInfo.getUserId() limit 1];
        System.debug('loggedinTech ..'+listexp );
        td.Technician__c = listexp.isEmpty()?null:listexp[0].id;
           
    }

    }
}

How to set Createddate Field value for Test Record in Salesforce Test class

(Note: The feature we are discussing here is as per the Salesforce Spring 16 preview release notes,So this feature is available from Spring 16 release of Salesforce, but features may or may not be available after the Spring 16 go to live )

Before Spring 16 if you are inserting let assume 20 test records in salesforce test class for all those 20 test records the created date is same .If you are working any scenario like to fetch only latest records 20 you will be getting all that 20 records with same created date because all records are inserted with same date so you can't guaranty that in which order they are coming even if you are using order by created date.

From Spring 16 release releasing this great feature to set the created date by the developer for the test records in salesforce test classes (It may or may not be released in Spring as per the note above).

The new Test class method called Test.setCreatedDate(RecordId,DateTime) which allows to set the created date for the test records in salesforce test class.

How to use:
1 . Create a test record in test class.
2.  Pass that record Id along with date time that you want set to Test.setCreatedDate(Id,DateTime).
 @isTest   
 private class SetCreatedDateTest {  
   static testMethod void testSetCreatedDate() {  
     Account a = new Account(name='Test Account');  
     insert a;  
     Test.setCreatedDate(a.Id, DateTime.newInstance(2012,12,12));  
     Test.startTest();  
     Account myAccount = [SELECT Id, Name, CreatedDate FROM Account   
                WHERE Name ='Test Account' limit 1];  
     System.assertEquals(myAccount.CreatedDate, DateTime.newInstance(2012,12,12));  
     Test.stopTest();  
   }  
 }  

Key points:
1.All database changes are rolled back at the end of a test. You can’t use this method on records that existed before your test executed.
2.You also can’t use setCreatedDate in methods annotated with @isTest(SeeAllData=true), because those methods have access to all data in your org.
3.This method takes two parameters—an sObject ID and a Datetime value—neither of which can be null.
4. You can see the doc related to this setCreatedDate at Reference Doc for SetCreatedDate.

I think now everyone is eagerly waiting for this new feature.Enjoy....!


How to Delete the Records Permanently from the Recycle Bin in Salesforce


Basically in salesforce when you have deleted any record from an object, it will not be deleted permanently and it will be stored in Recycle bin till 15 days from the deletion date.The number of records stored in recycle bin depends on Number of Licenses your organisation has pursed and multiply it with 5000 records.
If the number of records in recycle bin crosses this limit salesforce automatically deletes the old records from Recycle Bin which are at least in recycle bin for 2 hours.If you want to delete the records permanently from recycle bin before salesforce deletes it you can emptyRecylebin() method.


     EmptyRecycleBinResult[] = DataBase.emptyRecyclebin(List of Ids)

Example:

    1. Account Acc = new Account(Id='0016000000I549m');
        Database.emptyRecycleBin(Acc);


Notes:

1. Maximum number of records per call that we can pass is 200
2. Using this function records deleted can not be undeleted again.
3. Theses deleted records from recycle bin can be accessed using the DataBase.queryAll() for some time typically that would be with in 24 hours or may shorter or longer.