Tuesday, October 13, 2015

Reducing Salesforce SOQL queries by using static variables

public static List myObjectList {
     get {
          if (myObjectList == null) {
               myObjectList = [
                    select Name
                    from MyObject__c
               ];
          }

          return myObjectList;
     }
     set;
}

Thursday, September 17, 2015

Editing Multiple Lines

Highlight the lines and use CTRL, Shift, L (CMD, Shift, L on Mac). You can then move the cursor to your heart's content and edit all lines at once.

It's also called 'Split into Lines' in the 'Selection' menu

Wednesday, July 22, 2015

WSDL Import Errors

This is from http://www.fishofprey.com/2011/03/consuming-aspnet-web-service-from.html Great tips.

Salesforces wsdl2apex can be a bit basic in what is supports (see Supported WSDL Features).
Steps for consuming an ASP.NET web service from Apex.
  1. Add the Web service host to the Remote Sites.
    Adminitraction Setup > Security Controls > Remote Site Settings
    Skipping this step will result in a "System.CalloutException: IO Exception: Unauthorized endpoint, please check Setup->Security->Remote site settings. endpoint ="...
  2. Export the WSDL from the ASP.NET web service
  3. Optionally, you might like to sort the WSDL. The idea is to ensure wsdl2apex produces the same elements in the same order for future code comparisons.
  4. Import the WSDL into Salesforce
    Develop > Apex Classes > Generate from WSDL*
  5. Define a Apex class name
  6. Test the new Apex class using Execute Anonymous in Eclipse. With a ASP.NET generated web service I found the class I defined in the previous step had a nested class corresponding to the binding name from the uploaded WSDL. The nested class had a method that corresponded to the web method (the operation in the WSDL).
  7. Optionally, search the generated class for calls to WebServiceCallout.invoke(...). This will currently cause test cases to abort silently (except for a log message) and you may not notice. Sprinkle the code with a liberal amount of Test.isRunningTest().
*Common WSDL parsing errors:
  1. If the Parse WSDL button produces Error: Failed to parse wsdl: Found more than one wsdl:binding. WSDL with multiple binding not supported Deleting the second <wsdl:binding> element what contains soap12 elements and the corresponding port definition under <wsdl:wervice>.
  2. wsdl:import
    Error: Failed to parse wsdl: Unknown element: import
    Locate the import elements in the current WSDL. E.g. . Pull that WSDL down and merge its contents into the parent WSDL.
  3. xsd:import
    Failed to parse wsdl: Found schema import from location http://example.com/WebService.svc?xsd=xsd0. External schema import not supported
    These will typically appear under <wsdl:types>. Copy the contents of the import under <wsdl:types> and remove the<xsd:schema>. See also: Force.com Discussion Forum: Referencing external schemas in a WSDL
  4. Error: Failed to parse wsdl: Failed to parse WSDL: Unable to find binding {http://tempuri.org/}BasicHttpBinding_IWebService. Found BasicHttpBinding_IWebService instead.
    The <wsdl:definitions> had the attribute xmlns:i0="http://tempuri.org/"i0: was being used as the namespace for the binding. Switching it to tns: resolved the issue.
  5. Error: Failed to parse wsdl: schema:targetNamespace can not be null
    In this case I needed to add a targetNamespace attribute and value to the element. E.g. <xsd:schema> becomes <xsd:schema targetNamespace="http://www.example.com/api/Imports">
  6. Apex Generation Failed:
    Unable to find schema for element; {http://schemas.microsoft.com/2003/10/Serialization/Arrays}ArrayOfstring
     and
    Unable to find schema for element; {http://schemas.microsoft.com/2003/10/Serialization/Arrays}ArrayOflong
    In this case I'd initially made a mistake when pulling in the xsd for these complex types. I corrected it by putting the complex type definitions within a <xsd:schema targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays">element in wsdl:type section.
  7. Error: wwwExampleComApi
    Error: Identifier name is reserved: long at 191:23

    This error was caused by the ArrayOflong type generating the following Apex:
    1. public class ArrayOflong {  
    2.     public Long[] long;  
    3.     private String[] long_type_info = new String[]{'long','http://www.w3.org/2001/XMLSchema','long','0','-1','false'};  
    4.     private String[] apex_schema_type_info = new String[]{'http://www.Example.com/api','false','false'};  
    5.     private String[] field_order_type_info = new String[]{'long'};  
    6. }  
    Possible fix:
    1. public class ArrayOflong {  
    2.     public Long[] long_x; // Note the _x suffix to avoid the conflict  
    3.     // The first parameter here is what will appear in the SOAP message as the element name  
    4.     private String[] long_type_info = new String[]{'long','http://www.w3.org/2001/XMLSchema','long','0','-1','false'};  
    5.     private String[] apex_schema_type_info = new String[]{'http://www.Example.com/api','false','false'};  
    6.     private String[] field_order_type_info = new String[]{'long_x'};  
    7. }  
  8. Error: Failed to parse wsdl: Unsupported Schema element found http://www.w3.org/2001/XMLSchema:attribute. At: 1866:57
    The WSDL had three "attribute" elements:
    • <xs:attribute name="FactoryType" type="xs:QName"/>
    • <xs:attribute name="Id" type="xs:ID"/>
    • <xs:attribute name="Ref" type="xs:IDREF"/>
    Commenting these out of the WSDL allowed into to be used with wsdl2apex. I'm not sure what adverse effects resulted from removing them.
  9. The use of <xsd:extension base="foo"> in a complex type won't result in the base class fields appearing in generated Apex class.
    Try copying the fields from Apex class that was being extended into the sub class.

Friday, July 17, 2015

Fields and Page Layout Lengths

Question length: 40 Characters
Help mouseover length: 255 Characters

Section title length: 80 Characters

Thursday, July 9, 2015

Code coverage report.

Need to use the Tooling API.
  • Go to Aside.IO
  • Login to production
  • Click the “<“ button on the top right and select “Test”
  • Click "Coverage Report”
  • Finally click the “Click Here to Download Report"

SELECT Id, ApexClassOrTriggerId, ApexClassOrTrigger.Name,
       NumLinesCovered, NumLinesUncovered 
  FROM ApexCodeCoverageAggregate

Tuesday, July 7, 2015

Custom Attributes on Standard Apex Compnents

html-data-tooltip="Testing testing"
becomes
data-tooltip="Testing testing"

Tuesday, June 30, 2015

Email to Case

There is a strange issue, then if you haven't verified your email routing email address, then Case Settings don't get set and the default values for that record type is used.

Also note,  workflows, assignment rules, etc. don't have access to related records from the Case when you do email to case.

Auto start PIA on OpenELEC

Automatically start your PIA VPN ON KODI Raspberry 2 Model B

# /usr/bin/connmanctl services
*R aname                vpn_a_name_vpn
[...]
# /usr/bin/connmanctl config vpn_a_name_vpn --autoconnect yes
# /usr/bin/connmanctl services
*AR aname                vpn_a_name_vpn
[...]

Install the Maintenance Tool to double check the IP address.

Friday, June 5, 2015

Export Report Functionality

First id is the report ID.
pv0: passed parameter for the filters (optional)
xf: is either csv or xls
enc: UTF-8 or SO-8859-1
{communityname}: replace if the user is accessing the report export from a community/portal and note the users need the "Export Reports" permission on their profile/permission set and also access to the report folder/report.

CSV
https://na1.salesforce.com/00O600000041iBL?pv0=aBA600000004DRF&export=1&enc=UTF-8&xf=csv
https://na1.salesforce.com/{communityurlname}/00O600000041iBL?pv0=aBA600000004DRF&export=1&enc=UTF-8&xf=csv

HTML/Excel
https://na1.salesforce.com/00O600000041iBL?pv0=aBA600000004DRF&export=1&enc=UTF-8&xf=xls
https://na1.salesforce.com/{communityurlname}/00O600000041iBL?pv0=aBA600000004DRF&export=1&enc=UTF-8&xf=xls 

This can can be used in javascript (buttons/links) on page layouts, apex, and visualforce page.

Friday, May 22, 2015

Check for recursive triggers.

public class Utilities {   
  public static Boolean isOppyTrgExecuting = false;
}
            
if(Utilities.isOliTrgExecuting == false) {
  Utilities.isOliTrgExecuting = true;
  // Do stuff
}

Get fields of object.

public static String GetObjectFields(String strSObjectName) {

  // Get the field names
  SObjectType sot = Schema.getGlobalDescribe().get(strSObjectName);

  if (sot == null) 
    return null;

  String theFields = '';
  List lstFields = sot.getDescribe().fields.getMap().values();

  for(Schema.SObjectField s : lstFields) {
    String theName = s.getDescribe().LocalName;
    theFields += theName + ',';
  }

  // Trim last comma
  theFields = theFields.subString(0, theFields.length() - 1);
  return theFields;
}

Test for person account.

We basically just need to grab the correct account type record id and assign it to the account and you of course need person accounts enabled on your org.

String RecordTypeId = [SELECT Id FROM RecordType WHERE (Name = 'Person Account') AND (sObjectType = 'Account')].Id;
Account a = new Account(
RecordTypeID = RecordTypeId,
LastName = System.now().millisecond() + 'Testing Lastname'
);
insert a;

Test for products without @isAllTestData

@isTest
private class TrgOpportunityTest {

  @isTest static void test_method_one() {

    Account a = new Account();
    a.Name = 'Wallyu';
    insert a;

    Opportunity o = new Opportunity(
      Name = 'Merchandisebo',
      Autorenew__c = 'Yes',
      Account = a,
      StageName = 'Contract',
      CloseDate = DateTime.Now().Date(),
      Term_2_License_Start_Date__c = DateTime.Now().Date(),
      Term_2_License_End_Date__c = DateTime.Now().Date().addYears(1),
      HasBeenRenewed__c = false,
      Bill_When__c = 'In Arrears');
    insert o;

    System.debug(LoggingLevel.WARN, '@@@TrgOpportunityTest.o : ' + o);

    Product2 p2 = new Product2(Name='Test Productrrrr',isActive=true);
    insert p2;

    Id pricebookId = Test.getStandardPricebookId();
    PricebookEntry pbe = new PricebookEntry(Pricebook2Id=pricebookId, Product2Id=p2.Id, UnitPrice=99, isActive=true);
    insert pbe;

    OpportunityLineItem oli = new OpportunityLineItem(PriceBookEntryId=pbe.Id, OpportunityId=o.Id, Quantity=1, TotalPrice=99,Description='sdfsdfsdf');
    List  olilist=new List{oli};
    insert (olilist);

    Test.startTest();
    o.StageName = 'Purchased';
    upsert o;
    System.debug(LoggingLevel.WARN, '@@@TrgOpportunityTest.o AFTER UPSERT : ' + o);
    Test.stopTest();
  }
}

Simple wrapper class example.

public class Checkbox_Class 
{
    List accountList = new List();
    List selectedAccounts = new List();
        
    public List getAccounts()
    {
        for(Account a : [select Id, Name, AccountNumber, Phone from Account limit 5])
        accountList.add(new accountwrapper(a));
        return accountList;
    }
    
      
    public class accountwrapper
    {
        public Account acc{get; set;}
        public Boolean selected {get; set;}
        public accountwrapper(Account a)
        {
            acc = a;
            selected = false;
        }
    }
}

Missing Reset My Security Token

Instead of messing around trying to figure out the IP ranges and security settings you can use this URL hack:

{your domain}/_ui/system/security/ResetApiTokenEdit?retURL=%2Fui%2Fsetup%2FSetup%3Fsetupid%3DPersonalInfo&setupid=ResetApiToken