May 24

OpportunityAccessLevel field not writable in Apex

Recently, I was working on an assignment, where I had to create Opportunity Team Member records in a trigger on some user action. But when I started to write the code and tried saving it, I got the error “Field is not writeable: OpportunityTeamMember.OpportunityAccessLevel“. Uuuhhh.. I got stuck! According to the documentation this field is writable, then why not for me. Below is the code that I tried, and came to know, that OpportunityAccessLevel field not writable in Apex.

 


OpportunityTeamMember OppTeamMember = new OpportunityTeamMember();
OppTeamMember.UserId = UserInfo.getUserId();
OppTeamMember.OpportunityId = opp.Id;
OppTeamMember.OpportunityAccessLevel='Edit';
OppTeamMember.TeamMemberRole = 'Opportunity Team Member';

The above code gave me the error:

Field is not writeable: OpportunityTeamMember.OpportunityAccessLevel

 

This error doesn’t occur when you create opportunity team member by going to the related list on the opportunity. You can give any access level from there.

Opportunity Team Member Manually

Adding Opportunity Team Member manually

 

After spending some time, I figured out and came to know, that: If Opportunity sharing settings are set to Private, then you can not write this field OpportunityAccessLevel. This field will be set to Read Only by default.

 

But my requirement was to give “Edit” access to opportunity team member while creating. So the workaround I opted was:

  1. Create opportunity team member record first, Salesforce will give READ permission by default.
  2. Then, give edit access using the OpportunityShare object because as soon as you create an OpportunityTeamMember record, Salesforce creates an entry in sharing records for that opportunity and user.
  3. Query the sharing record that Salesforce created just now, and update the access level to EDIT.

 

Here is the code:


OpportunityTeamMember OppTeamMember = new OpportunityTeamMember();
OppTeamMember.UserId = UserInfo.getUserId();
OppTeamMember.OpportunityId = opp.Id;
//OppTeamMember.OpportunityAccessLevel='Edit';
OppTeamMember.TeamMemberRole = 'Opportunity Team Member';
insert OppTeamMember;

//get all of the sharing records which Salesforce created right now. rowCause is Sales Team.
List<OpportunityShare> oppShareRecords = [select Id, OpportunityAccessLevel, RowCause from OpportunityShare where OpportunityId =: opp.Id and RowCause = 'Sales Team'];

// set all team members access to read/write
for (OpportunityShare OppShare : oppShareRecords){
OppShare.OpportunityAccessLevel = 'Edit';

}

update oppShareRecords;

 

Good Luck and Happy Coding !!

 

 

 

Permanent link to this article: http://www.sfdcpoint.com/salesforce/opportunityaccesslevel-field-not-writable-in-apex/

May 02

Pagination using StandardSetController with wrapper class

Pagination using StandardSetController with wrapper class without losing data during pagination

Click here for Demo – Pagination with wrapper

Very often, we need pagination in our visualforce page, and we use wrapper class to show the records with checkboxes in pageBlockTable. We use the standardSetController for pagination, display checkboxes for each record BUT while paginating, the value of the selected checkboxes are gone, it doesn’t retain during paginating.

This is because the list that we use to display records on page, is getting refreshed everytime, and not retaining the values. So, to hold or retain the values during pagination, we will see how we can use Pagination using StandardSetController with wrapper class without losing data during pagination/ paginating (moving next or previous).

 

PaginationImage,Pagination using StandardSetController with wrapper class

Contact pagination – Wrapper Class – With checkboxes

 

So, to overcome this, we will not use the direct list from standardSetController, instead of that we’ll use a map to show the values on page. This map will always contain the correct values of checkboxes (for retaining purpose), we will use map on visualforce page pageBlockTable. Whenever user clicks on next or previous, first or last, we store the copy of records with checkbox value in map, so that even if the wrapper list is refreshed with next set of records, we can store the checkbox values for previous set of records.

Below is the code snippet you can look at, and we have a demo link as well, just to give you an idea how it works.

Visualforce Page Code:


<apex:page controller="contactPaginationController" docType="html-5.0" tabStyle="Contact">
   <apex:sectionHeader title="Contact" subtitle="Contact Pagination" />
    <apex:form id="theForm">
      <apex:pageBlock title="All Contacts" rendered="{!wrapperRecordList.size!=0}" id="pbId" >
        <apex:pageBlockTable value="{!wrapperRecordList}" var="cont">
           <apex:column headerValue="Select">
             <apex:inputCheckbox value="{!cont.isSelected}"/>
           </apex:column>
           <apex:column headerValue="Name">
             <apex:outputField value="{!cont.contactRecord.name}"/>
           </apex:column>
           <apex:column headerValue="Email">
             <apex:outputField value="{!cont.contactRecord.Email}"/>
           </apex:column>
           <apex:column headerValue="Phone">
            <apex:outputField value="{!cont.contactRecord.Phone}"/>
           </apex:column>
       </apex:pageBlockTable>

 <!-- Action Buttons visible on bottom of page for pagination -->
       <apex:outputPanel style="text-align:center;" layout="block">
          <apex:commandButton value="First" reRender="pbId" action="{!first}" disabled="{!NOT(hasPrevious)}" status="paginationStatus"/>
          <apex:commandButton value="Previous" rerender="pbId" action="{!previous}" disabled="{!NOT(hasPrevious)}" status="paginationStatus"/>&nbsp;Page {!pageNumber} of {!totalPages}&nbsp;
          <apex:commandButton value="Next" rerender="pbId" action="{!next}" disabled="{!NOT(hasNext)}" status="paginationStatus"/>
          <apex:commandButton value="Last" rerender="pbId" action="{!last}" disabled="{!NOT(hasNext)}" status="paginationStatus"/>
          <apex:actionStatus id="paginationStatus">
             <apex:facet name="start">
                 Please wait...<img src="/img/loading32.gif" style="width: 18px;"/>
             </apex:facet>
          </apex:actionStatus>
       </apex:outputPanel>
 </apex:pageBlock>
 </apex:form>
</apex:page>

Apex Controller:


public class contactPaginationController{

 //variable used in page.
 Public Integer size{get;set;}
 Public Integer noOfRecords{get; set;}
 public List<SelectOption> paginationSizeOptions{get;set;}
 public static final Integer QUERY_LIMIT = 10000;
 public static final Integer PAGE_SIZE = 5;

 public List <WrapperClass> wrapperRecordList{get;set;}
 Map<Id, WrapperClass> mapHoldingSelectedRecords{get;set;}

 //constructor calling init method.
 public contactPaginationController(){
   mapHoldingSelectedRecords = new Map<Id, WrapperClass>();
   init();

 }

//Init method which queries the records from standard set controller.
 public void init() {
 wrapperRecordList = new List<WrapperClass>();
 for (Contact cont : (List<Contact>)setCon.getRecords()) {
 if(mapHoldingSelectedRecords != null && mapHoldingSelectedRecords.containsKey(cont.id)){
 wrapperRecordList.add(mapHoldingSelectedRecords.get(cont.id));

 }
 else{
   wrapperRecordList.add(new WrapperClass(cont, false));
 }
 }
 }

 /** Instantiate the StandardSetController from a query locater*/
 public ApexPages.StandardSetController setCon {
 get {
 if(setCon == null) {
   setCon = new ApexPages.StandardSetController(Database.getQueryLocator([SELECT Id,Name, Email, Phone FROM Contact LIMIT : QUERY_LIMIT ]));

   // sets the number of records to show in each page view
   setCon.setPageSize(PAGE_SIZE);
 }
   return setCon;
 }
 set;
 }

 /** indicates whether there are more records after the current page set.*/
 public Boolean hasNext {
 get {
   return setCon.getHasNext();
 }
 set;
 }

 /** indicates whether there are more records before the current page set.*/
 public Boolean hasPrevious {
 get {
   return setCon.getHasPrevious();
 }
 set;
 }

 /** returns the page number of the current page set*/
 public Integer pageNumber {
 get {
   return setCon.getPageNumber();
 }
 set;
 }

 /** return total number of pages for page set*/
   Public Integer getTotalPages(){
     Decimal totalSize = setCon.getResultSize();
     Decimal pageSize = setCon.getPageSize();
     Decimal pages = totalSize/pageSize;
     return (Integer)pages.round(System.RoundingMode.CEILING);
 }

 /** returns the first page of the page set*/
 public void first() {
   updateSearchItemsMap();
   setCon.first();
   init();
 }

 /** returns the last page of the page set*/
 public void last() {
   updateSearchItemsMap();
   setCon.last();
   init();
 }

 /** returns the previous page of the page set*/
 public void previous() {
   updateSearchItemsMap();
   setCon.previous();
   init();
 }

 /** returns the next page of the page set*/
 public void next() {
   updateSearchItemsMap();
   setCon.next();
   init();
 }

 //This is the method which manages to remove the deselected records, and keep the records which are selected in map.
 private void updateSearchItemsMap() {
 for(WrapperClass wrp : wrapperRecordList){
  if(wrp.isSelected){
     mapHoldingSelectedRecords.put(wrp.contactRecord.id, wrp);
  }
  if(wrp.isSelected == false && mapHoldingSelectedRecords.containsKey(wrp.contactRecord.id)){
     mapHoldingSelectedRecords.remove(wrp.contactRecord.id);
  }
 }
 }

 //wrapper class being used for checkbox showing.
 public class WrapperClass {
 public Boolean isSelected {get;set;}
 public Contact contactRecord {get;set;}
 public WrapperClass(Contact contactRecord, Boolean isSelected) {
    this.contactRecord = contactRecord;
    this.isSelected = isSelected;
 }
 }

}

Click here for Demo – Pagination with wrapper

This is just an example we are taking here (i.e. display contacts with checkboxes), there can be several other scenarios as well, where you might have some inputField in one column of the pageBlockTable, and you need to retain the values of inputfield during pagination.

There also you can use this concept of Pagination using StandardSetController with wrapper class without losing data during pagination.

This is also very important because this kind of scenario is included for sure in Advanced Developer certification exam exercise, where you have to do pagination with either checkboxes or inputField in pageBlockTable.

Hope this post will give you a better idea about pagination and that too with wrapper classes.

Happy coding !! :)

Permanent link to this article: http://www.sfdcpoint.com/salesforce/pagination-using-standardsetcontroller-with-wrapper-class/

Apr 27

Only Aggregate Expressions Use Field Aliasing – SOQL Error

Only Aggregate Expressions Use Field Aliasing – SOQL Error

Out of many other errors we encounter, this is one with the SOQL. Many times, when writing SOQL, we face the error – “Only Aggregate Expressions Use Field Aliasing” and we are stuck that what’s happening, everything seems all right to me.

You must be missing a comma in the SOQL between two fields before FROM keyword. 

Aliasing is when you want to give some different name to the column in any SOQL result, but you can only do so in aggregate queries of Salesforce, where you use some aggregate functions like sum(Custom_Field__c), count(Id) or any other similar aggregate function.

Below is a valid SOQL using aggregate function with aliasing. We are trying to give “amountTotal” name to Sum(Amount) column.


[Select Sum(Amount) amountTotal, AccountId from Opportunity group by AccountId];

BUT, because aliasing is not allowed in normal SOQL, that is why below SOQL is considered faulty, and will encounter the error “Only Aggregate Expressions Use Field Aliasing”.


[select id, Name Amount from Opportunity];

You might notice we are missing a comma between Name & Amount field, which is why Salesforce thinks that we are trying to give a different label to Name column in SOQL result but that is not allowed.

If you ever encounter this error in future, look for missing comma between two fields in your SOQL.

Happy coding !! :)

Permanent link to this article: http://www.sfdcpoint.com/salesforce/only-aggregate-expressions-use-field-aliasing-soql-error/

Apr 24

TestSetUp method in apex test classes

Test classes – an important part of overall SDLC in Salesforce. We as a developer have to write the test classes very often, and we need to create the test data as well, to have our test class executed successfully. We’ll cover a new concept introduced in salesforce test classes i.e TestSetUp method in apex test classes.

Initially, we had to create test data in every test method, because every test method is considered a different transaction with its own governor limits. But Salesforce has introduced @TestSetUp annotation for test class method. You can write a method in test class, with @TestSetUp annotation applied, and create all your common test data in this method.

Few key points about TestSetUp methods:

  1. Method marked with @TestSetUp annotation executes before any testMethod.
  2. Data created in this method doesn’t need to be created again and again, and it is by default available for all test methods.
  3. There can be only one setup method per test class.
  4. Test setup methods are supported only with the default data isolation mode for a test class. If the test class or a test method has access to organization data by using the @isTest(SeeAllData=true) annotation, test setup methods aren’t supported in this class. 
  5. Test setup methods are available for 24.0 or later versions only.
  6. Every test method will get unchanged version of the test data created in setup method, doesn’t matter if any other test method has modified the data. We will show this in testMethod2 of below example.

 

Below is a sample code, which will show how the test data is available in every test method.


@isTest
private class TestSetupMethodExample {
    //Below is a method with @testsetup annotation, the name can be anything like setup(), oneTimeData(), etc.
    @testSetup static void setup() {
        // Create common test accounts
        List<Account> testAccts = new List<Account>();
        for(Integer i=0;i<2;i++) {
            testAccts.add(new Account(Name = 'TestAcct'+i));
        }
        insert testAccts;
    }

    @isTest static void testMethod1() {
        // Here, we will see if test data created in setup method is available or not, Get the first test account by using a SOQL query
        Account acct = [SELECT Id FROM Account WHERE Name='TestAcct0' LIMIT 1];
        // Modify first account
        acct.Phone = '555-1212';
        // This update is local to this test method only.
        update acct;

        // Delete second account
        Account acct2 = [SELECT Id FROM Account WHERE Name='TestAcct1' LIMIT 1];
        // This deletion is local to this test method only.
        delete acct2;

        // Perform some testing
    }

    @isTest static void testMethod2() {
        // The changes made by testMethod1() are rolled back and
        // are not visible to this test method.
        // Get the first account by using a SOQL query
        Account acct = [SELECT Phone FROM Account WHERE Name='TestAcct0' LIMIT 1];
        // Verify that test account created by test setup method is unaltered.
        System.assertEquals(null, acct.Phone);

        // Get the second account by using a SOQL query
        Account acct2 = [SELECT Id FROM Account WHERE Name='TestAcct1' LIMIT 1];
        // Verify test account created by test setup method is unaltered.
        System.assertNotEquals(null, acct2);

        // Perform some testing
    }

}

Because, test data created is less in number, that’s why rolling back of records at the end of test class takes less time. This actually ends up in improving the performance and reducing the time take to run the test class.

Best of luck with your test class and test data !! Happy coding :)

Permanent link to this article: http://www.sfdcpoint.com/salesforce/testsetup-method-in-apex-test-classes/

Apr 20

Compare old and new field values in trigger

Compare old and new field values in trigger Salesforce

Sometimes we have requirement that our trigger should run only when some field value is changed on a record. So we need to compare value of that field between old version of record and new version of record to make sure that trigger will not run every time when record is changed/edited. For example, we may have requirement that send an email to VP of company or do some task when an opportunity status is changed to Closed Won. So, we have to compare old and new field values in trigger to make it sure.

Salesforce provides Trigger.OldMap where records with older version (last version of record committed in database) are stored in map with key as their Salesforce record Id’s.

Trigger.OldMap = Map<Id, OldVersionOfRecord>();

I have put an example below to show that how can we use Trigger.OldMap and Trigger.New context variables to compare the field values, because the Id of the record is common in both Trigger.OldMap and Trigger.New, that’s why we can use the record Id to get older and newer version of any record from these maps.

Here in this example, trigger compares the account number field’s old value with the new value. That is, trigger checks if the account number was changed.

If the account number is changed the trigger assigns the Type field value as “prospect” else it assigns it a value as “Other“.

trigger Compare_OldandNewvalues on Account (before update) {

//Here we will iterate on trigger.new list, which already holds the new values of all records.
for (Account acc: Trigger.new) {
//Here we use the account id, to get the older version of record.
Account oldAccount = Trigger.oldMap.get(acc.ID);

//once we get the older version, we can get any field's value from older version to compare.
if(acc.AccountNumber != oldAccount.AccountNumber) {

//Here is some logic being performed on a condition basis.
System.debug('--*Account Number is changed*--');
System.debug('**Old Account Number :'+oldAccount.AccountNumber);
System.debug('**New Account Number :'+acc.AccountNumber);
acc.Type = 'Prospect';
}
else{
System.debug('--**Account Number has not been Updated**--');
acc.Type = 'Other';
}
}
}

Also, please note that the Trigger.oldMap is only available in update and delete events and cannot be accessed in insert event triggers. Please take care of this point when writing your trigger code.

Happy coding !! :)

 

Permanent link to this article: http://www.sfdcpoint.com/salesforce/compare-old-and-new-field-values-in-trigger/

Apr 11

Use static resource in Visualforce

Use static resource in Visualforce – Salesforce

Force.com platform provides us a facility to upload, manage and use the content that is static (not changing) for your organization, and it can be stored under “Static Resources“. It can be a Javascript file, CSS file, an image or even a zip file containing all the files required in one zip file. Today we’ll see how to use static resource in Visualforce – Salesforce.

Below are the ways to use the static resources in our visualforce pages:

Suppose there is a single file like any single image or standalone css file, that you need to refer in your VF page, then you can directly use the “$Resource.resourceName” to refer the static resource where ‘$Resource‘ is a global variable to use any static resource within visualforce page. You need not to hard code the path of the static resource in VF page code. Below are some examples of the same.

Suppose you have an image file uploaded in static resource with name “Z_test” as shown below in the screenshot.

Static resource

You can refer this image in your code using expression {$Resource.Z_Test}. Below are some other examples as well:


<!-- An image can be referenced like this -->
<img src="<strong>{!$Resource.Z_Test}</strong>"/>

<!-- Similarly any CSS file can be referenced like below -->
<apex:stylesheet value="<strong>{!$Resource.sampleCss}</strong>"/>

You need to remember only the keyword “$Resource” and the name of the static resource and not the name of actual file.

Similarly when we have the bundle of files, uploaded as a zip file in static resources section, then along with the name of static resource, you have to give the path to the file within the context of the archived zip.

Suppose below is the directory structure of the zip file with the name “bootstrap” that you have uploaded, in which you have three different folders for storing CSS, images, and JS files respectively.

Static resource archive structure
So, to reference a particular file at a given location, you need to give the path of the file in context of the zip, along with the name of static resource while referencing in Visualforce page code. For this we have to use a function called “URLFOR(nameOfStaticResource, RelativePathOfFile)”. Below code snippets shows you how to refer the particular files.


<meta charset="utf-8" />Force.com Developer<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<!-- Static Resources for CSS -->
<apex:styleSheet value="{!URLFOR($Resource.bootstrap, 'bootstrap/css/bootstrap.css')}"/>
<apex:styleSheet value="{!URLFOR($Resource.bootstrap, 'bootstrap/css/bootstrap-responsive.css')}"/>

<!-- Static Resource for individual imag -->
<image src="{!URLFOR($Resource.bootstrap, 'img/glyphicons-halflings.png')}"/>

Above we explained the two ways of using the static resources in visualforce page, one for single file, another for the files within a zipped static resources file.

Hope this will help you in your coding.

Happy coding !! Good Luck :)

Permanent link to this article: http://www.sfdcpoint.com/salesforce/use-static-resource-in-visualforce/

Apr 07

apex:pageMessage and apex:pageMessages – Salesforce

apex:pageMessage and apex:pageMessages – Salesforce

Most of the times we are confused between these two visualforce components i.e. apex:pageMessage and apex:pageMessages. A small different of ‘s’. Let’s see the difference between apex:pageMessage and apex:pageMessages – Salesforce.

We are confused that which one should we use, and in which case. There is a small difference between these two. Let me explain the same:

We should use apex:pageMessage when we want to have individual message on the visualforce page and you provide the message to be displayed in the attributes of this tag. This is a kind of static message which you will write in visualforce itself, and can put some conditions in rendered attribute to display the message. The strength attribute of the tag controls the size of the message box displayed on the page. No need to have any controller code for adding the message on the page, because message has been written in visualforce page itself.


<apex:page controller="theController">
<apex:pageMessage severity="Error" summary="First Error message on page" strength="1"/>
<apex:pageMessage severity="Error" detail="Second Error message on page" strength="2"/>
</apex:page>

apex:pageMessage and apex:pageMessages - Salesforce

apex:pageMessage

This can be used to display any custom message that you always want to appear on the screen. There may be a case that whenever a user is on a form you may want a warning to appear to display important information to them.

You can also use this to conditionally display a message, based on some condition that you put in the rendered attribute of this component.

Now Let’s talk about apex:pageMessages:

apex:pageMessages is used to display more than one message on a visualforce page. It will display Salesforce generated messages(probably some exception or error) as well as custom messages that you have added to the ApexPages class in your controller code.

Below is the sample code. All the messages added in apex code using ApexPages class are shown in one box only unlike the previous tag apex:pageMessage where all the messages are shown in different boxes as they are put on page. Below is one example:

<apex:page controller="theController">
<apex:pageMessage severity="Error" summary="First Error message on page" strength="1"></apex:pageMessage>
<apex:pageMessage severity="Error" detail="Second Error message on page" strength="2"></apex:pageMessage>
<apex:pageMessages ></apex:pageMessages>

</apex:page>

The controller code for the same below:


public class theController {

public theController(){

ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, 'First Error Message added from apex'));
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, 'Second Error Message added from apex'));

}
}

apex:pageMessage and apex:pageMessages - Salesforce

apex:pageMessages

Noticed that, how a single instance of the apex:pageMessages handles all of the errors on the page. The use case for this object is to capture all errors on the page including the error or exception messages generated by salesforce, and the messages added in ApexClass as well. It should be used on most custom Visualforce page as a catch all to let users know what errors occured (if no other messaging is used).

Best practice is to always keep apex:pageMessages on your page, because sometimes Salesforce generates some exception or error (may be because of some trigger or workflow), but because of non-availablitiy of this tag on your page, those messages are not displayed and you are confused why my page or functionality is not processing and not going further.

So I would suggest always keep apex:pageMessages tag on your visualforce page.

Good Luck !!

Permanent link to this article: http://www.sfdcpoint.com/salesforce/apexpagemessage-and-apexpagemessages-salesforce/

Apr 07

Relationship Query in Apex – Salesforce

Relationship Query in Apex – Salesforce

Most of the times, we have relationships between the objects(master-detail OR lookup) and often we need to fetch the list of all child records related to parent record in SOQL. This can be achieved using relationship query.

We can also say it as a Inner Query (query inside query).

For using relationship query, most important is, to know the Name of relationship between the two objects. You can get this relationship name by going to the Look-up OR Master-detail field on child object. Here is the screen that you will see after clicking on the look-up/Master-detail field name that is present on child object.

Here are two examples.

1.First one is for Account(Parent) – Contact (Child) relationship. Below screen, we have opened the Lookup field present on contact(child object).

Child Relationship name2. The second one is for some custom object. When we create a custom relationship field on any object, we get an option to choose the name of relationship, while creating the look-up or Master-Detail relationship field. Below you can see the same, and then the same name is used in relationship queries.

How to create relationship name

Then this relationship name reflects on the custom field as shown below:

Child Relationship name - 2

 

So, in case of relationship between standard objects, relationship name is fixed already, and you can not change, but in case you are creating the relationship on your own, then you get the option of choosing the relationship name.

Now you have got the relationship name. We’ll see, how to construct the query required for our problem i.e. to get all the child records related to one parent record in a single query.

Here is a significant difference while making relationship queries for standard relationships(already defined by salesforce) and custom relationships(defined by user – b/w two custom objects OR b/w custom & standard object).

For example, for account and contacts relationship(already defined by salesforce), the query will be like:

List<Account> accList = [select id,name,(select name, id, email from contacts) from account];

Here you can see in the phrase (select name, id, email from contacts ), we have used the relationship name as it is mentioned on the field detail page as shown below:

Child Relationship name

But in case of custom relationship the query will be like:

List<Account> accList = [select id, (select id, name from tests__r) from account];

Here we have used __r with the relationship name. We have to use __r suffix after the relationship name shown on the field detail page as shown below:

Child Relationship name - 2

This relationship query returns all the accounts with all the child test records associated to each account record. You can use the query result as shown below:


//Perform the query on Account.

List<Account> accList = [select id, (select id, name from tests__r) from account];

//Iterate over the account with.
for(Account a : accList){

//For each account object, get the child records using tests__r and iterate over each child records.
for(test__c test : a.tests__r){

System.debug('The test name is:::::' + test.name);

}

}

Limitation of Relationship Query:

  • In each specified relationship, only one level of parent-to-child relationship can be specified in a query. For example, if the FROM clause specified Account, the SELECT clause could only specify the Contact or other objects at that level. It could not specify a child object of Contact.
  • No more than 20 relationships can be specified in a single query.
  • In each specified relationship, no more than five levels can be specified in a child-to-parent relationship. For example, Contact.Account.Owner.FirstName (three levels).

Good Luck !! :)



Permanent link to this article: http://www.sfdcpoint.com/salesforce/relationship-query-apex-salesforce/

Apr 06

Transient Keyword – View State – Visualforce – Salesforce

Transient Keyword – View State – Visualforce – Salesforce

We can use transient keyword with apex class’s instance variables when we want that values of those variables should not be transferred as part of the view state of visualforce page. This helps us reducing the view state of visualforce page. As we all know that, there is a limit of 135KB of view state and many times this “Transient” keyword helps us to reduce the view state.

There are certain points that we should consider while using the transient keyword:

  1. The value of transient variable is only transferred from controller to visualforce page but not as part of view state. As the value is not part of view state, the changed value of that variable is not transferred back from visualforce page to controller when a new request is made by clicking a button or link.
  2. We should use the transient keyword mostly in case where we have read only Visualforce page and data doesn’t need to be sent back to controller in further requests. A common use case for the transient keyword is a field on a Visualforce page that is needed only for the duration of a page request, but should not be part of the page’s view state and would use too many system resources to be recomputed many times during a request.

Here is a very common and excellent example to help understand the concept of transient variable:

Visualforce page:


<apex:page controller="ExampleController">
Time1: {!t1} <br/><br/>
Time-Transient: {!t2} <br/><br/>
<apex:form >
<apex:commandLink value="Refresh"/>
</apex:form>
</apex:page>

Below is the controller for the same, where we have transient variable declared:


public class ExampleController {

DateTime t1;
transient DateTime t2; //declare

public String getT1() {
if (t1 == null)
 t1 = System.now();

return '' + t1;
}

public String getT2() {
if (t2 == null)
 t2 = System.now();

return '' + t2;
}
}

Click for Demo

In the above example and demo, you can see that clicking the refresh button on the page causes the transient date T2 to be updated every time, because it is being recreated each time the page is refreshed. The non-transient date continues to have its original value, which has been de-serialized from the view state, so it remains the same.

Going into more details, we can understand it like, when user made first request that means; when this page was accessed first time, at that time both the values were null, and getter method of both the variables checked for null and assigned the value of “System.now()” to the variables and values got displayed on visualforce page. But When visualforce was displayed for the first time, in the view state, there was only the value of non-transient variable which is T1 and not the transient one T2.

So, when user clicks on refresh, a new request is made. The getter methods again tries to check for null. Because the view state has the value of non-transient variable available, the value is taken from view state and as it is not null, system does not refresh the value with latest “System.now()” value.

BUT, for transient variable, since the view state does not hold the previous value, the getter method could not find any value and considering it null again, the getter method assigns the latest value of “System.now()” to the variable. That is why the value of transient variable gets refreshed.

Understanding the above example can give you a fair idea of where and why to use the transient keyword.

So, if you want the value of your variable on visualforce page only once, don’t need the value in further requests to controller, then use transient keyword, to make your page lighter with less size of view state.

Good Luck !! :)

Permanent link to this article: http://www.sfdcpoint.com/salesforce/transient-keyword-view-state-visualforce/

Apr 06

Test class with example in salesforce

Test class with example in Salesforce

Testing is an important part of SDLC. So, before deploying our code to production environment, Salesforce requires at least 75% of your code to be covered by our test classes whic. Salesforce has done that to make sure that our code doesn’t break in any situation in Production. Today we’ll see how we write the test class with example in Salesforce.

Some points regarding the test classes in Salesforce, which you have to know for sure:

  1. At least 75% of your Apex code must be covered by unit tests, and all of those tests must complete successfully. But this should not be our focus. We should aim for 100% code coverage, which ensures that you cover each positive and negative use case of your code to cover and test each and every branch of your code.
  2. Calls to System.debug are not counted as part of Apex code coverage.
  3. Test methods and test classes are not counted as part of Apex code limit. So, no worries about writing long test class with more methods just to make sure that all your code branches are covered.
  4. Every trigger you are trying to deploy should have at least 1% coverage, but yes overall coverage of your production org after getting your code deployed should be 75%, otherwise Salesforce won’t let you deploy your code.
  5. Class can be deployed on 0% coverage as well, but as I told in last point, that overall coverage of your production org after getting your code deployed should be 75%, otherwise Salesforce won’t let you deploy your code.

In the example below, we will learn how to write a very simple test class:

Apex Trigger:


trigger HelloWorldTrigger on Book__c (before insert) {

Book__c[] books = Trigger.new;

MyHelloWorld.applyDiscount(books);
}

Trigger Helper Class:


public class MyHelloWorld {
 public static void applyDiscount(Book__c[] books) {
 for (Book__c b :books){
 b.Price__c *= 0.9;
 }
 }
}

Test Class Code:


@isTest
private class HelloWorldTestClass {
 static testMethod void validateHelloWorld() {
 Book__c b = new Book__c(Name='Behind the Cloud', Price__c=100);
 System.debug('Price before inserting new book: ' + b.Price__c);

 Test.startTest();
 // Insert book
 insert b;

 Test.stopTest();

 // Retrieve the new book
 b = [SELECT Price__c FROM Book__c WHERE Id =:b.Id];
 System.debug('Price after trigger fired: ' + b.Price__c);

 // Test that the trigger correctly updated the price
 System.assertEquals(90, b.Price__c);
 }
}

The key points while writing a test class are:

  1. You have to start your class with @isTest annotation, then only Salesforce will consider this class as test class.
  2. Keep your class as Private, and the best practice is to name your test class as your original Class or trigger Name + ‘Test’.
  3. Methods of your test class have to be static, void and testMethod keyword has to be used.
  4. Prepare your test data which needs to be existing before your actual test runs. There are multiple techniques of creating test data now a days, for example, setup() method, static resources etc. Will cover in more details in other article. Stay tuned !!
  5. Use Test.startTest() and Test.stopTest() to make sure that the actual testing of your code happens with the fresh set of governer limits. These methods help you to reset your governor limits just before your actual code of testing get executed.
  6. Once your test code runs between Test.startTest() and Test.stopTest(), you must use assert statements to test whether your actual code is executing correctly and giving the results as expected. In our case, we are test whether book’s price has been set to 90 or not. If this assert statement returns false, then your test class will fail, and will let you know, that something is not correct in your code, and you need to fix your original code.
  7. Because we are testing a simple trigger, we could not show the testing using negative use cases, but in an ideal world, you should write multiple methods in your test class, few should test your positive use cases, and other should test your negative test cases.

Good luck with your test classes!! :)

Permanent link to this article: http://www.sfdcpoint.com/salesforce/test-class-with-example-salesforce/

Older posts «