Monday, 29 February 2016

How to avoid this error while running test class "FIELD_CUSTOM_VALIDATION_EXCEPTION, Attempt to de-reference a null object: []"

This post is all about how efficiently custom settings can be used in the class so that we can avoid null pointer exception while running test class with seealldata is false.

As per the best practice concern, we should not use SeeAlldata is true in all the test class.If we wont use that attribute then we need to create all the test data(custom setting record and object record ) in the test class. We might not aware of all the custom setting which will be required to be inserted because they will be refereed in the trigger of some other object which is not really required to be executed.

Normally we use custom setting like below 

 Boolean ischecked = customsettingname__c.getInstance('RecordName').IsChecked__c ;

If we wont insert record name as "RecordName" in the custom setting customsettingname__c in test class , then we will come across this issue   FIELD_CUSTOM_VALIDATION_EXCEPTION, Attempt to de-reference a null object: []"

To avoid such issue we need to use custom setting like below 

Map<String, customsettingname__c> mcs = customsettingname__c.getAll();
System.debug('Printing--'+mcs );

if(mcs.keyset().size()>0 && mcs.containskey('RecordName'))
{
Boolean ischecked = customsettingname__c.getInstance('RecordName').IsChecked__c;
System.debug('Printing--'+ischecked);
}

How to create portal user in apex class?

I think we must have faced difficulty to create portal user in apex class. 

Below are the errors we might have faced. 

System.SObjectException: Field is not writeable: User.IsPortalEnabled 
System.SObjectException: Field is not writeable: User.Contact 

This post is just to tell how to create portal user. We already know that first we need to create Contact and Account , ensure the Account is a partner account, then create a user that points to the contact.

Still same error will come. 

Solution-
To make a partner portal account, we need to ensure the account's owner has the correct values in the UserRoleId and ProfileId fields.
To make a partner user, any user is ok. Simply ensure the user's profile is a Portal User profile. Then you can specify a value for its ContactId field.

Below is the code 

//Create portal account owner
UserRole portalRole = [Select Id From UserRole Where PortalType = 'None' Limit 1];
Profile profile1 = [Select Id from Profile where name = 'System Administrator'];
User portalAccountOwner1 = new User(
UserRoleId = portalRole.Id,
ProfileId = profile1.Id,
Username = System.now().millisecond() + 'test2@test.com',
    Alias = 'batman',
Email='bruce.wayne@wayneenterprises.com',
EmailEncodingKey='UTF-8',
Firstname='Bruce',
Lastname='Wayne',
LanguageLocaleKey='en_US',
LocaleSidKey='en_US',
TimeZoneSidKey='America/Chicago'
);
Database.insert(portalAccountOwner1);

//Create account
Account portalAccount1 = new Account(
Name = 'TestAccount',
OwnerId = portalAccountOwner1.Id
);
Database.insert(portalAccount1);
   
//Create contact
Contact contact1 = new Contact(
    FirstName = 'Test',
    Lastname = 'McTesty',
AccountId = portalAccount1.Id,
    Email = System.now().millisecond() + 'test@test.com'
);
Database.insert(contact1);
   
//Create user
Profile portalProfile = [SELECT Id FROM Profile WHERE Name LIKE '%Portal User%' Limit 1];
User user1 = new User(
Username = System.now().millisecond() + 'test12345@test.com',
ContactId = contact1.Id,
ProfileId = portalProfile.Id,
Alias = 'test123',
Email = 'test12345@test.com',
EmailEncodingKey = 'UTF-8',
LastName = 'McTesty',
CommunityNickname = 'test12345',
TimeZoneSidKey = 'America/Los_Angeles',
LocaleSidKey = 'en_US',
LanguageLocaleKey = 'en_US'
);
Database.insert(user1);

Thursday, 18 February 2016

How to split a string into a multiple parts from a common character ?

We may need to split a string into multiple parts from common characters to store it in a set which can be used later for comparison. 

I came across one scenario  like ,I was getting some string which was containing three parts separated by ":"  and I had to compare with custom settings record, I was not sure which part of the string will be match with custom settings record. So I split the string and stored in the set.

Below is some sample code:-

String s = 'Another Person : ChildLine Volunteer Administrator : None';
String s2;
set<String> set_string = new set<String>();
while(s.contains(':')){
s2 = s.substring(0,s.indexof(':')+1);
set_string.add(s2.substring(0,s2.length()-1));
s = s.remove(s2);
}
set_string.add(s);
System.debug('Printing---set_string '+set_string);


Keep learning and sharing...

How contains key method works ? Does it allow partial matches or exact matches ?

This might be very simple, Even I was also thinking as the method name is "containskey" then it should return true if partial matches, unfortunately it is not like that. "Containskey" method will return true only if key is exact match.

It is also case sensitive. Below is some code snippet

map<string,string> test = new map<string,string>();
test.put('abc123','GM');
system.debug('Exact matches -abc123 -'+test.ContainsKey('abc123'));---- True
system.debug('Partial matches-123--'+test.ContainsKey('123')); --- False
system.debug('Partial matches-abc--'+test.ContainsKey('abc')); --- False
system.debug('Case sensitive matches-ABC123-- '+test.ContainsKey('ABC123')); --- False




Friday, 12 February 2016

COMPILE ERROR: Invalid initial type List for Map

As we already know map will be very useful while writing code.

How will we create map<Id,Account> ?

Usually we will do using put method of map

map<Id,Account> map_Account = new map<Id,Account>();
for(Account acc:[Select id,name from account]){
    map_Account.put(acc.id,acc);


Instead of iteration we also can do other way for batter performance.
map<id,Account> account_map = new map<Id,Account>([select id,name from account]);
system.debug('printing-----'+account_map );

Now lets go for little advance, instead of static query what if want to use dynamic query like below

map<id,Account> account_map = new map<Id,Account>(database.query(sQuerry));
system.debug('printing-----'+account_map );

we will get an error message like "COMPILE ERROR: Invalid initial type List<SObject> for Map<Id,Account>"



To address above error we can use like 

map<id,sObject> account_map = new map<Id,sObject>(database.query(sQuerry));

Whenever we have to get some value from map we have to type cast to account that's all.

if(account_map.contains('Accountid') ){
Account acc = (Account)account_map.get(Accountid);
}

Keep exploring and sharing...

Thursday, 11 February 2016

How to show help text in a vf Page?

Below is code to show 

 <apex:outputPanel id="msgBelowHeader" Styleclass="container_12 clearfix" rendered="{!isPreDistributorVisible}">
                <div style="padding-left: 50px;">
                <b>Your Preffered Distiributor is {!con.account.Preferred_Distributor__c} </b>
                <apex:outputPanel rendered="{!HelpInstructions !=null}">
                <span class="helpButton" id="example-_help">
                <img src="/s.gif" class="helpOrb" style="position: initial;"/>         
                   <script>sfdcPage.setHelp('example','{!HelpInstructions}');</script>
                </span>  
                </apex:outputPanel>
                </div>
            </apex:outputPanel>

Declare a variable HelpInstructions in the class to populate help text to make dynamic also we can add html style sheet to that variable.

KEEP EXPLORING ... 

Tuesday, 2 February 2016

How to Invoke approval process from a custom button

In some scenario we have to decided approver as dynamically. Say who will be the first approver and who is the second. 

In that case create create lookup field (First_Approver__c, Second_Approver__c)to user as approver and those field will be used on creating approval steps of approval process . 

Aprroval process 

Approval Steps 




Now the question is how first_approval__c field will be populated ? 

We need to populate those field as instantly I mean just before going to approval process.

Approach - We created a custom button (Content source is java script) and from button code called a method which will update all the approvers and returns true for successful update, Then we are calling approval process.

Class - 
global class YourClass { 

webservice static Boolean MethodForSettingApprover(Id recordId){
       Boolean isUpdated = false;
  try{
//Update the approvers 
isUpdated = true;
  }
  Catch(Exception ex){
System.debug('Printing exception===='+ex.getmessage());
  }
  return isUpdated;
}
}

Button Code - 
{!REQUIRESCRIPT("/soap/ajax/24.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")} 
function SubmitForApproval() 
var confirmed=confirm("Do you want to continue submitting for approval?"); 

if (confirmed==true) 
var resAppclass = sforce.apex.execute("YourClass","MethodForSettingApprover",{recordId"{!YourObject.Id}"});
var approval;
var processRes;
if(resAppclass == 'true'){
approval = new sforce.ProcessSubmitRequest();
approval.objectId = "{!YourObject.Id}";
processRes = sforce.connection.process([approval]);
}

alert('ProcessRes' + processRes); 
}