Salesforce Stateful Batch Apex
Batch Apex is stateless by default. That means for each execution of your execute method, you receive a fresh copy of your object. All fields of the class are initialized, static and instance. If your batch process needs information that is shared across transactions, one approach is to make the Batch Apex class itself
stateful by implementing the Database.Stateful
interface. Here is an example of stateful batch apex. In below example I want to count the “Customer – Direct” account records processed by the batch class.
Batch Apex:
global class AccountBatchApex implements Database.Batchable<sObject>, Database.Stateful{ global integer numberofDirectCustomers = 0; global Database.QueryLocator start(Database.BatchableContext bc){ String soqlQuery = 'SELECT Name, AccountNumber, Type From Account'; return Database.getQueryLocator(soqlQuery); } global void execute(Database.BatchableContext bc, List<Account> scope){ for (Account acc : scope){ if(acc.Type.equals('Customer - Direct')){ numberofDirectCustomers++; } } } global void finish(Database.BatchableContext bc){ } }
Salesforce Unsupported Metadata Types in Change Set
In Salesforce some customization are not available in Metadata API. You have to made them manually in all your Organization. The following components can’t be retrieved and deployed with Metadata API.
-
- Account Teams
- Activity Button Overrides
- Analytic Settings
- Automated Case User Settings
- Auto-number on Customizable Standard Fields
- Campaign Influences
- Case Contact Roles
- Case Feed Layouts
- Case Team Roles
- Console Layouts
- Multiline layout fields for contract line items
- Currency Exchange Rates
- Data Category Visibility Settings
- Delegated Administration
- Divisions
- Fiscal Year
- File Upload and Download Security Settings
- Lead Settings
- Live Agent chats routed with Omni-Channel
- Mail Merge Templates
- Mobile Administration
- Mobile Users and Devices
- Multiline layout fields for opportunity teams
- Offline Briefcase Configurations
- Opportunity Big Deal Alerts
- Opportunity Update Reminders
- Organization Wide Email Addresses
- Outlook Configurations
- Partner Management
- The following standard picklists: IdeaTheme.Categories, Order.Status, Question.Origin. (All other standard picklists are supported.)
- Predefined Case Teams
- Product Schedule Setup
- Public and Resource Calendars
- Quote Templates
- Salesforce to Salesforce
- Self-Service Portal Font and Colors
- Self-Service Portal Settings
- Self-Service Portal Users
- Self-Service Public Solutions
- Self-Service Web-to-Case
- Service report templates
- Site.com
- Social Account/Contact Settings
- Social Business Rules
- Social Customer Service Settings
- SoftPhone Layout
- Solution Categories
- Solution Settings
- Standard fields that aren’t customizable, such as autonumber fields or system fields
- Tag Settings
- Territory Assignment Rules
- User Interface Settings (except calendar features, which are supported in ActivitiesSettings)
- Web Links on Person Account Page Layouts
- Web-to-Lead
Convert Salesforce sObject Record To JSON
Apex Class:
public class ConvertsObjectToJSON { //Return the JSON string from record Id public static string getJsonFromSObject(Id recordId) { String jsonData = ''; try{ if(String.isNotBlank(recordId)) { String sObjectFields = ''; //Get sObject Name String objName = recordId.getSObjectType().getDescribe().getName(); //Getting the fields information Map<String, Schema.sObjectField> sObjectFieldMap = Schema.getGlobalDescribe().get(objName).getDescribe().fields.getMap(); //Map key is the field API name and value is the field data type. Map<String, String> fieldMap = new Map<String, String>(); for(Schema.SObjectField sfield: sObjectFieldMap.Values()){ Schema.DescribeFieldResult fieldDesc = sfield.getDescribe(); fieldMap.put(fieldDesc.getName(), fieldDesc.getType().name()); } //Create query with all fields for(String field: fieldMap.keySet()){ sObjectFields += field+','; } sObjectFields = sObjectFields.removeEnd(','); //Dynamic SOQL Query with all fields String soqlQuery = 'SELECT '+ sObjectFields +' FROM '+objName+' WHERE Id =: recordId'; //Execute the SOQL query sObject sObj = Database.Query(soqlQuery); //Create JSON JSONGenerator gen = JSON.createGenerator(true); gen.writeStartArray(); gen.writeStartObject(); gen.writeFieldName('attributes'); gen.writeStartObject(); gen.writeStringField('type', objName); gen.writeEndObject(); gen.writeFieldName('fields'); gen.writeStartObject(); for(String field: fieldMap.keySet()){ if(sObj.get(field) != null){ gen.writeStringField(field, String.ValueOf(sObj.get(field))); } else{ gen.writeStringField(field, ''); } } gen.writeEndObject(); gen.writeEndObject(); gen.writeEndArray(); //Getting the JSON String Data jsonData = gen.getAsString(); } } catch(Exception ex){ } return jsonData; } }
Invoke the method:
String jsonData = ConvertsObjectToJSON.getJsonFromSObject('001B000000pA7sV'); system.debug('jsonData-' + jsonData);
How SOQL differs from SQL?
- No INSERT, UPDATE or DELETE statements, only SELECT.
- No command execution.
- No wild cards for fields, all fields must be explicitly typed.
- No JOIN statement. However, we can include information from parent objects like Select name, phone, account.name from contact.
- No UNION operator.
- Queries cannot be chained together.