The Currency data type may display values as 2 decimal places, but the actual value stored in Salesforce database can have more decimal places.
If data is uploaded via data loader or similar tool values could be uploaded with more decimal places.
You may see the value in Salesforce with 2 decimal places, but if you perform a soql the value will have multiple decimal places.
Search
Thursday, 9 February 2012
Sunday, 22 January 2012
Why Is Continuous Integration Important
Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily. Each integration is verified by an automated build to detect integration errors as quickly as possible.
Most teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly. By doing this teams have found that fewer errors occur in their live environment, so users get more confident in their IT department, trust is a very valuable commodity, not easily bought but easily sold and lost.
Developers get to understand quickly where their code may break someone else's, so development does become quicker, but only after the pain is endured to get your codebase to an understandably coherent state.
Continuous Integration cannot be practised in isolation, it must be accompanied with requirements gathering, proper development life cycle to ensure quality of code produced, tested and documented.
If requirements gathering isn't done correctly, its like building a house with no foundations, building code on something that is not properly understood. Also once the code is made the testers should test specifically on what the requirements were, plus regression testing.
If code isn't quality checked, the most efficient way of coding won't be created and understanding of your codebase shared amongst your team, if code isn't tested well: well it's obvious that the code won't match the requirements gathered, who should test: well do you get your butcher to give you legal advice, no, so you should have qualified testers who understand quality testing, testing can be a thwart relationship between developer and tester, testers understand this and manage the relationship, isn't documented creates a situation whereby future development doesn't understand why previous development was done, so the developer changes the code to what should be best practices only to realise that he has affected another part of the system; this wastes time and causes the users to have less faith in the IT department, only because documentation wasn't done correctly.
This is the minimum, there is more, such as source control.
Yes all of this slows down development, which affects the time to roll-out new projects, but it means that the code being developed is quality and is managed correctly. If the above isn't done developers won't understand and know what is in their live system, so how do you know what is important and what isn't and changing anything can and will have knock-on-effects to other related undocumented parts of the system.
The lesson is, if you aren't doing the above now don't wait until things go wrong, don't be a reactive development department, become proactive and solve the problems now before they do cause problems.
Most teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly. By doing this teams have found that fewer errors occur in their live environment, so users get more confident in their IT department, trust is a very valuable commodity, not easily bought but easily sold and lost.
Developers get to understand quickly where their code may break someone else's, so development does become quicker, but only after the pain is endured to get your codebase to an understandably coherent state.
Continuous Integration cannot be practised in isolation, it must be accompanied with requirements gathering, proper development life cycle to ensure quality of code produced, tested and documented.
If requirements gathering isn't done correctly, its like building a house with no foundations, building code on something that is not properly understood. Also once the code is made the testers should test specifically on what the requirements were, plus regression testing.
If code isn't quality checked, the most efficient way of coding won't be created and understanding of your codebase shared amongst your team, if code isn't tested well: well it's obvious that the code won't match the requirements gathered, who should test: well do you get your butcher to give you legal advice, no, so you should have qualified testers who understand quality testing, testing can be a thwart relationship between developer and tester, testers understand this and manage the relationship, isn't documented creates a situation whereby future development doesn't understand why previous development was done, so the developer changes the code to what should be best practices only to realise that he has affected another part of the system; this wastes time and causes the users to have less faith in the IT department, only because documentation wasn't done correctly.
This is the minimum, there is more, such as source control.
Yes all of this slows down development, which affects the time to roll-out new projects, but it means that the code being developed is quality and is managed correctly. If the above isn't done developers won't understand and know what is in their live system, so how do you know what is important and what isn't and changing anything can and will have knock-on-effects to other related undocumented parts of the system.
The lesson is, if you aren't doing the above now don't wait until things go wrong, don't be a reactive development department, become proactive and solve the problems now before they do cause problems.
Get Prepared For AppExchange
http://wiki.developerforce.com/page/Security_Review
This page covers things like costs of submitting to AppExchange and important links to test your code to get it ready for the AppExchange
Free testing tools to check your code is written well
http://security.force.com/webappscanner
http://security.force.com/sourcescanner
Of course you can use these tools not just for preapration for the AppExchange but for all your projects
I'm currently working on an App to allow you to document the class references made throughout your codebase so that a class structure diagram can be produced from the output, and for a deployment procedure to be automatically produced by selecting your classes, objects and pages that you want to deploy.
If you would like to have this please contact me.
This page covers things like costs of submitting to AppExchange and important links to test your code to get it ready for the AppExchange
Free testing tools to check your code is written well
http://security.force.com/webappscanner
http://security.force.com/sourcescanner
Of course you can use these tools not just for preapration for the AppExchange but for all your projects
I'm currently working on an App to allow you to document the class references made throughout your codebase so that a class structure diagram can be produced from the output, and for a deployment procedure to be automatically produced by selecting your classes, objects and pages that you want to deploy.
If you would like to have this please contact me.
Friday, 18 November 2011
Serialize Batch Apex
In Force.com you cannot call a batch Apex class from another batch Apex class because batch Apex is a future call. However, you can use Database.Stateful and the finish() method to mimic serialization of batch processes.
After batch 1 is complete in the finish() method this calls startNewBatch() in GeneralUtils which fires the newbacth batch class
However, running this you will see an error
Database.executeBatch cannot be called from a batch or future method.
}
public class GeneralUtils{
public static void startNewBatch(){
newbacth batchable = new newbacth();
Id newbacthID = Database.executeBatch(batchable);
}
}
After batch 1 is complete in the finish() method this calls startNewBatch() in GeneralUtils which fires the newbacth batch class
However, running this you will see an error
Database.executeBatch cannot be called from a batch or future method.
global class batch l implements Database.Batchable<sObject>, Database.Stateful{
global Database.QueryLocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC,
List<sObject> scope){
}
global void finish(Database.BatchableContext BC){
GeneralUtils.startNewBatch();
}
public class GeneralUtils{
public static void startNewBatch(){
newbacth batchable = new newbacth();
Id newbacthID = Database.executeBatch(batchable);
}
}
Tuesday, 4 October 2011
This Is The Strangest Thing Ive Seen In Salesforce
So do we all agree that there's no problem if you want to insert a record on 1 object and after that has inserted correctly, no problem, you
immediately want to insert another record on a different object.
Wrong! You must be joking right. I do this all the time. Well there are certain times when this is not possible
I was making a unit test in a Sandbox and I was populating a custom setting with data. Then immediately after I was trying to insert
an Account record. Now I'd setup my test data I then performed my unit tests and ran the unit test in Eclipse. The unit test passed. Perfect.
Then later that day I was running All Tests in the same sandbox and to my surprise my new unit test failed. I knew there hadn't been any changes to code, meta data, data, or anything
on my sandbox. So after some investigation I came across this article
http://stackoverflow.com/questions/2387475/how-to-avoid-mixed-dml-operation-error-in-salesforce-tests-that-create-users
I also looked at
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm
From this information I wrapped System.runas around the insert statement that created the custom setting record to run this code as System Administrator, as shown below. The result was the unit test passed in both Eclipse and in the browser when I logged into Salesforce.
Profile systProfileID = [Select id From Profile where Name Like 'System Administrator' LIMIT 1];
list<User> us1 = [Select id From User where ProfileID=: systProfileID.id and IsActive=true limit 1];
if (us1.size() > 0){
System.runAs(us1[0]){
//insert custom setting record
}
}
//now you can safely insert any standard object record
This certainly qualifies as 1 of the most strangest bugs I've come across in Salesforce. Be aware!
immediately want to insert another record on a different object.
Wrong! You must be joking right. I do this all the time. Well there are certain times when this is not possible
I was making a unit test in a Sandbox and I was populating a custom setting with data. Then immediately after I was trying to insert
an Account record. Now I'd setup my test data I then performed my unit tests and ran the unit test in Eclipse. The unit test passed. Perfect.
Then later that day I was running All Tests in the same sandbox and to my surprise my new unit test failed. I knew there hadn't been any changes to code, meta data, data, or anything
on my sandbox. So after some investigation I came across this article
http://stackoverflow.com/questions/2387475/how-to-avoid-mixed-dml-operation-error-in-salesforce-tests-that-create-users
I also looked at
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm
From this information I wrapped System.runas around the insert statement that created the custom setting record to run this code as System Administrator, as shown below. The result was the unit test passed in both Eclipse and in the browser when I logged into Salesforce.
Profile systProfileID = [Select id From Profile where Name Like 'System Administrator' LIMIT 1];
list<User> us1 = [Select id From User where ProfileID=: systProfileID.id and IsActive=true limit 1];
if (us1.size() > 0){
System.runAs(us1[0]){
//insert custom setting record
}
}
//now you can safely insert any standard object record
This certainly qualifies as 1 of the most strangest bugs I've come across in Salesforce. Be aware!
Using The Builder Pattern
If you have a class which has specific methods, variables, properties which always need to be set and run and possibly not on the construction of the class, using the Builder Pattern is a very useful way to do this.
The Builder Pattern is a clearer and more efficient way of setting up the environment of a class.
If you were to set and run methods, variables, properties on construction of the class you might as well do this in the class's constructor method.
But if you wanted to set specific environment setting a bit later then builder methods are ideal
Here is the code of a class that uses the Builder Pattern
public class ThisClass{
private String HerName;
private String HerJob;
private String Herotherjob;
public ThisClass setName(String passName){
HerName=passName;
return this;
}
public ThisClass setJob(String passJob,String otherjob){
HerJob=passJob;
Herotherjob= otherjob;
return this;
}
public ThisClass setJob(String passJob){
HerJob=passJob;
return this;
}
}
This invokes the Builder Pattern class above and uses the Builder Pattern on lines 2 and 3. As you can see all the work was done on just 1 line.
1. ThisClass cls = new ThisClass();
2. cls.setName('Liz').setJob('Secret Agent','Window Cleaner'); //This uses the 1st variety of setJob
3. cls.setName('Liz').setJob('Secret Agent'); //This uses the 2nd variety of setJob
For more information and a useful example on the Builder Pattern see http://developer.force.com/cookbook/recipe/email-utility-class
The Builder Pattern is a clearer and more efficient way of setting up the environment of a class.
If you were to set and run methods, variables, properties on construction of the class you might as well do this in the class's constructor method.
But if you wanted to set specific environment setting a bit later then builder methods are ideal
Here is the code of a class that uses the Builder Pattern
public class ThisClass{
private String HerName;
private String HerJob;
private String Herotherjob;
public ThisClass setName(String passName){
HerName=passName;
return this;
}
public ThisClass setJob(String passJob,String otherjob){
HerJob=passJob;
Herotherjob= otherjob;
return this;
}
public ThisClass setJob(String passJob){
HerJob=passJob;
return this;
}
}
This invokes the Builder Pattern class above and uses the Builder Pattern on lines 2 and 3. As you can see all the work was done on just 1 line.
1. ThisClass cls = new ThisClass();
2. cls.setName('Liz').setJob('Secret Agent','Window Cleaner'); //This uses the 1st variety of setJob
3. cls.setName('Liz').setJob('Secret Agent'); //This uses the 2nd variety of setJob
For more information and a useful example on the Builder Pattern see http://developer.force.com/cookbook/recipe/email-utility-class
Setting Up Salesforce To Salesforce
Note: not all records of objects can be shared using Salesforce To Salesforce
First of all lets get the basics out of the way. Follow the steps in
http://wiki.developerforce.com/index.php/An_Introduction_to_Salesforce_to_Salesforce
Now for some of the things that Salesforce don't tell you, or it is difficult to find information on.
Regarding the manual sharing records using "Forward to connection" button. Well I've never personally found this button so if anyone does see this anywhere please tell me.
Sharing Accounts and Attachments Using Code
If you want to share attachments make sure that Setup > Security > 'HTML Documents and Attachments Settings' is not ticked otherwise you won't be able to share certain file types.
Attachments need to have a record associated with it, such as an Account record. You need first of all share the Account record with the other Salesforce orgs first before you can share any Attachments. So of course the donor needs to have Account set up in Connection > Published Objects
Here is some code which will allow you to share the Account and then the Attachment.
List<PartnerNetworkConnection> connMap = new List<PartnerNetworkConnection>();
connMap=[select Id, ConnectionStatus, ConnectionName from PartnerNetworkConnection where ConnectionStatus = 'Accepted'] ;
Account acc =[Select id From Account where id = '<<Account ID>>'];
for(PartnerNetworkConnection network : connMap) {
PartnerNetworkRecordConnection newrecord = new PartnerNetworkRecordConnection();
newrecord.ConnectionId = network.Id;
newrecord.LocalRecordId = acc.id;
newrecord.SendClosedTasks = true;
newrecord.SendOpenTasks = true;
newrecord.SendEmails = true;
insert newrecord;
}
First of all lets get the basics out of the way. Follow the steps in
http://wiki.developerforce.com/index.php/An_Introduction_to_Salesforce_to_Salesforce
Now for some of the things that Salesforce don't tell you, or it is difficult to find information on.
Regarding the manual sharing records using "Forward to connection" button. Well I've never personally found this button so if anyone does see this anywhere please tell me.
Sharing Accounts and Attachments Using Code
If you want to share attachments make sure that Setup > Security > 'HTML Documents and Attachments Settings' is not ticked otherwise you won't be able to share certain file types.
Attachments need to have a record associated with it, such as an Account record. You need first of all share the Account record with the other Salesforce orgs first before you can share any Attachments. So of course the donor needs to have Account set up in Connection > Published Objects
Here is some code which will allow you to share the Account and then the Attachment.
List<PartnerNetworkConnection> connMap = new List<PartnerNetworkConnection>();
connMap=[select Id, ConnectionStatus, ConnectionName from PartnerNetworkConnection where ConnectionStatus = 'Accepted'] ;
Account acc =[Select id From Account where id = '<<Account ID>>'];
for(PartnerNetworkConnection network : connMap) {
PartnerNetworkRecordConnection newrecord = new PartnerNetworkRecordConnection();
newrecord.ConnectionId = network.Id;
newrecord.LocalRecordId = acc.id;
newrecord.SendClosedTasks = true;
newrecord.SendOpenTasks = true;
newrecord.SendEmails = true;
insert newrecord;
}
Now that the Account has been shared you can share the Attachment.
Attachment att =[Select id,IsPartnerShared From Attachment where Parentid='<<Account ID>>'];
att.IsPartnerShared =true;
update att;
If you want to share Attachments manually once the Account has been shared, click edit on the Attachment and a 'Share with Connections' tick box will now be available, tick this and the Attachment will now be shared.
You can setup the recipients to automatically accept shared records. If you do the records will become live automatically in the recipient org, otherwise you need to go to the Account tab, scroll down to 'Accounts from Connections' section, press Go will display any shared Accounts which you can now accept.
Subscribe to:
Posts (Atom)