Motivation behind this
I was exploring Big Objects and trying to create Big Object and Field definitions through Metadata API. I have searched all possible way but didn't find any code regarding this use case.
I am thankful to Andrew Fawcett (Andrew Fawcett) and his team for building MetadataService.cls which a wrapper to Metadata API which actually helped me to build this solution. Though this example doesn't exists anywhere which motivates me to write this code.
It has taken almost 5 hours to build this solution since I didn't have any prior experience to handle Metadata API through Apex.
It has taken almost 5 hours to build this solution since I didn't have any prior experience to handle Metadata API through Apex.
- It stores billions of data on Salesforce Platform and we can archive data from other objects or datasets.
- There are two type of Big Objects: Standard and Custom
- Only following field types are available: Lookup Relation, Number, Text, Long Text Area and Date/Time
- Big Object supports custom Lightning and Visualforce components rather than standard UI elements home pages, detail pages, list views etc.
- We can create up to 100 Big Objects in per org.
- It doesn't support encryption.
For more information, refer Big Objects Implementation Guide
Implementation Approach and important points
Firstly I have referred the codebase in MetadataService.cls and then started exploring.
To create Big Objects following points must be followed:
1. AllOrNoneHeader element and allOrNone should be true.
2. During firing createMetadata(), Big Object definition along with a custom field and index are must.
3. It will use MetadataService.CustomObject to create Big Object, but fullName should have API Name which ends with __b
4. Big Object doesn't have Standard Name field.
5. Big Object doesn't have SharingModel. Though you can use permission sets to assign permissions.
4. Big Object doesn't have Standard Name field.
5. Big Object doesn't have SharingModel. Though you can use permission sets to assign permissions.
Script
I have provided step by step approach with in-line comments.
Here I have tried to create Big Object with a name Application (Application__b) with following fields:
Here I have tried to create Big Object with a name Application (Application__b) with following fields:
- Account - Lookup (Account)
- Amount - Number (16,2)
- Description - Long Text Area (33000)
- Name - Text (50) and it is indexed
- Start Date - Date/Time
- MetadataService.MetadataPort service = new MetadataService.MetadataPort();
- service.SessionHeader = new MetadataService.SessionHeader_element();
- service.SessionHeader.sessionId = UserInfo.getSessionId();
- //AllOrNoneHeader is mandatory for Big Object
- service.AllOrNoneHeader = new MetadataService.AllOrNoneHeader_element();
- service.AllOrNoneHeader.allOrNone = true; //this is required for Big Objects
- //define Big Object
- MetadataService.CustomObject bigObject = new MetadataService.CustomObject();
- bigObject.fullName = 'Application__b';
- bigObject.label = 'Application';
- bigObject.pluralLabel = 'Applications';
- bigObject.deploymentStatus = 'InDevelopment'; //Make it Deployed if you need
- List<MetadataService.CustomField> lstCustomFields = new List<MetadataService.CustomField>();
- //define Text Field
- MetadataService.CustomField fieldObj = new MetadataService.CustomField();
- fieldObj.type_x = 'Text';
- fieldObj.label = 'Name';
- fieldObj.fullName = 'Name__c';
- fieldObj.length = 50;
- fieldObj.required = true;
- lstCustomFields.add(fieldObj);
- //define DateTime Field
- fieldObj = new MetadataService.CustomField();
- fieldObj.type_x = 'DateTime';
- fieldObj.label = 'StartDate';
- fieldObj.fullName = 'StartDate__c';
- lstCustomFields.add(fieldObj);
- //define Number Field
- fieldObj = new MetadataService.CustomField();
- fieldObj.type_x = 'Number';
- fieldObj.label = 'Amount';
- fieldObj.fullName = 'Amount__c';
- fieldObj.externalId = false;
- fieldObj.precision = 18;
- fieldObj.required = false;
- fieldObj.scale = 2;
- fieldObj.unique = false;
- lstCustomFields.add(fieldObj);
- //define Long Text Area Field
- fieldObj = new MetadataService.CustomField();
- fieldObj.type_x = 'LongTextArea';
- fieldObj.label = 'Description';
- fieldObj.fullName = 'Description__c';
- fieldObj.length = 33000;
- fieldObj.visibleLines = 3;
- fieldObj.required = false;
- fieldObj.unique = false;
- lstCustomFields.add(fieldObj);
- //define Lookup Relationship with Account
- fieldObj = new MetadataService.CustomField();
- fieldObj.type_x = 'Lookup';
- fieldObj.label = 'Account';
- fieldObj.fullName = 'Account__c';
- fieldObj.relationshipLabel = 'Applications';
- fieldObj.relationshipName = 'Applications';
- fieldObj.referenceTo = 'Account';
- lstCustomFields.add(fieldObj);
- bigObject.fields = lstCustomFields;
- //define index
- List<MetadataService.Index> lstIndex = new List<MetadataService.Index>() ;
- MetadataService.Index indexObj = new MetadataService.Index();
- indexObj.label = 'MyIndex';
- indexObj.fullName = 'MyIndex';
- bigObject.indexes = lstIndex;
- //define index field and add it to index
- List<MetadataService.IndexField> lstIndexFields = new List<MetadataService.IndexField>();
- MetadataService.IndexField indfl = new MetadataService.IndexField();
- indfl.name = 'Name__c';
- indfl.sortDirection = 'ASC';
- lstIndexFields.add(indfl);
- indexObj.fields = lstIndexFields;
- lstIndex.add(indexObj);
- //finally create Big Object with Index field
- List<MetadataService.SaveResult> saveResults =
- service.createMetadata(
- new MetadataService.Metadata[] { bigObject});
- MetadataService.SaveResult saveResult = saveResults[0];
- if(saveResult==null || saveResult.success)
- return;
- // Construct error message
- if(saveResult.errors!=null)
- {
- System.debug('errors=' + JSON.serialize(saveResult.errors));
- List<String> messages = new List<String>();
- messages.add(
- (saveResult.errors.size()==1 ? 'Error ' : 'Errors ') +
- 'occured processing component ' + saveResult.fullName + '.');
- for(MetadataService.Error error : saveResult.errors)
- messages.add(
- error.message + ' (' + error.statusCode + ').' +
- ( error.fields!=null && error.fields.size()>0 ?
- ' Fields ' + String.join(error.fields, ',') + '.' : '' ) );
- if(messages.size()>0)
- System.debug(String.join(messages, ' '));
- }
- if(!saveResult.success)
- System.debug('Request failed with no specified error.');
Pain Points
In the MetadataService.cls Index class doesn't have fullName and it should be added otherwise after creating Big Object, Index name will show as null and Index API name will should null__b
- public class Index {
- public MetadataService.IndexField[] fields;
- public String label;
- public String fullName; //added by Santanu otherwise index name will show null and api name as null__b
- private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'}; //added by Santanu
- private String[] fields_type_info = new String[]{'fields',SOAP_M_URI,null,'0','-1','false'};
- private String[] label_type_info = new String[]{'label',SOAP_M_URI,null,'1','1','false'};
- private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
- //private String[] field_order_type_info = new String[]{'fields','label'};
- private String[] field_order_type_info = new String[]{'fields','label','fullName'}; //fullName added
- }
I have run the scripts when I was adding fields one by one. After creating Big Object if you have to rerun the script, you need to delete the Big Object permanently if it contains Lookup field.
Secondly, you can create permission set to provide field level permissions.
Final Outcome
The Big Object has been created and found as follows:
Data Entry
To insert data into Big Object as record create an instance of the object and assign field values and use Database.insertImmediate() .
- Account acct = new Account(Name='Account1');
- insert acct;
- Application__b appObj = new Application__b();
- appObj.Name__c = 'My Application';
- appObj.Amount__c = 100;
- appObj.Description__c = 'Testing with data';
- appObj.Account__c = acct.Id;
- appObj.StartDate__c = System.today();
- Database.insertImmediate(appObj);
Wonderful blog post, thank you so much for the great information which you provided.
ReplyDeleteTop 5 features of salesforce lightning