Dynamic Apex In Salesforce
page:
=====
======
If we don't have standard controller then we have to use
the following sample.
page:
=====
<apex:page
controller="RetrievePicklistData">
<apex:form >
<apex:outputlabel value="Stage"/>
<apex:selectList
size="1" >
<apex:selectOptions
value="{!pickNames}">
</apex:selectOptions>
</apex:selectList>
</apex:form>
</apex:page>
class:
=======
We can avoid SOQL query on RecordType object with this method.The following example shows how to access Record Type information through dynamic apex.
Schema Describe:
- Is a way to programmatically learn about metadata of your datamodel with in Apex.
- Schema Describe calls provides the ability to programitically describe the information about the current org schema such as list of top level objects including custom objects and their fields.
Map<String,Schema.SobjectType>
gd = Schema.getGlobalDescribe();
- We can also use schemaDescribe() to create tree structure of all the objects and fields in the schema browser, to do this we need to use the codemap
Map<String,Schema.SobjectType>
gd = Schema.getGlobalDescribe();
Returns map
of all Sobjects names or Keys to sObject tokens or values for the standard and
custom objects defined in the organization.
Schema Class
The following are methods for Schema. All methods are
static.
Returns a map of all sObject names (keys) to sObject tokens (values) for
the standard and custom objects defined in your organization.
Returns a list of the category groups associated with the
specified objects.
Describes metadata (field list and object properties) for the specified
sObject or array of sObjects.
Returns information about the standard and custom apps available to the
running user.
Returns available category groups along with their data
category structure for objects specified in the request.
Schema Namespace
The Schema namespace provides classes and methods for
schema metadata information.
The following are
the classes in the Schema namespace.
ChildRelationship
Class
Contains methods for accessing the child relationship as well as the child sObject for a parent sObject.
Contains methods for accessing the child relationship as well as the child sObject for a parent sObject.
DescribeFieldResult
Class
Contains methods for describing sObject fields.
Contains methods for describing sObject fields.
DescribeSObjectResult
Class
Contains methods for describing sObjects.
Contains methods for describing sObjects.
DescribeTabResult
Class
Contains tab metadata information for a tab in a standard or custom app available in the Salesforce user interface.
Contains tab metadata information for a tab in a standard or custom app available in the Salesforce user interface.
FieldSet
Class
Contains methods for discovering and retrieving the details of field sets created on sObjects.
Contains methods for discovering and retrieving the details of field sets created on sObjects.
PicklistEntry
Class
Represents a picklist entry.
Represents a picklist entry.
RecordTypeInfo
Class
Contains methods for accessing record type information for an sObject with associated record types.
Contains methods for accessing record type information for an sObject with associated record types.
SObjectField
Class
A Schema.sObjectField object is returned from the field describe result using the getControler and getSObjectField methods.
A Schema.sObjectField object is returned from the field describe result using the getControler and getSObjectField methods.
SObjectType
Class
A Schema.sObjectType object is returned from the field describe result using the getReferenceTo method, or from the sObject describe result using the getSObjectType method.
A Schema.sObjectType object is returned from the field describe result using the getReferenceTo method, or from the sObject describe result using the getSObjectType method.
More about Schema Namespace:
1. Retrieve the objects from the salesforce Org.
Display all the Custom objects with “__C” names in a picklist field:
page:
=====
<apex:page controller="ObjectRetrieve">
<apex:form >
<apex:outputlabel value="All Objects"/>
<apex:selectList size="1">
<apex:selectoptions value="{!objnames}"></apex:selectoptions>
</apex:selectList>
</apex:form>
</apex:page>
class:
======
public with sharing class ObjectRetrieve {
//Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
public List<SelectOption> getobjNames()
{
List<Schema.SObjectType> gd = Schema.getGlobalDescribe().Values();
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('--None','--None--'));
for(Schema.SObjectType f : gd)
{
if(f.getDescribe().getName().contains('__c'))
options.add(new SelectOption(f.getDescribe().getName(),f.getDescribe().getName()));
}
return options;
}
}
2. Retrieveing all the field api names dynamically.The below samples helps to retrieve the field api names dynamically from the salesforce object.
page:
=====
<apex:page standardcontroller="Opportunity" extensions="DynamicVFClass">
<apex:form >
<apex:pageBlock >
<apex:pageBlockSection columns="1">
<apex:repeat value="{!fieldapis}" var="f">
<apex:inputField value="{!Opportunity[f]}"/>
</apex:repeat>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
class:
======
public with sharing class DynamicVFClass {
public DynamicVFClass(ApexPages.StandardController controller) {
}
public List<String> getFieldapis() {
map<String, Schema.SObjectType> m1 = Schema.getGlobalDescribe() ;
SObjectType objToken1 = m1.get('Opportunity');
DescribeSObjectResult objDef1= objToken1.getDescribe();
map<String, SObjectField> fieldmap = objDef1.fields.getmap();
List<String> lstobjectfields1= new List<String>();
List<String> fieldLabels1= new List<String>();
map<String,String> fieldLabelNamemap1= new map<String,String>();
for (String fName1:fieldmap.keySet())
{
if(fieldmap.get(fName1).getDescribe().getType()!=Schema.DisplayType.Time &&
fieldmap.get(fName1).getDescribe().getType()!=Schema.DisplayType.anytype&&
fieldmap.get(fName1).getDescribe().getType()!=Schema.DisplayType.base64 &&
fieldmap.get(fName1).getDescribe().getType()!=Schema.DisplayType.EncryptedString &&
fieldmap.get(fName1).getDescribe().getType()!=Schema.DisplayType.Id &&
fieldmap.get(fName1).getDescribe().getType()!=Schema.DisplayType.multiPicklist &&
fieldmap.get(fName1).getDescribe().getType()!=Schema.DisplayType.TextArea)
{
fieldLabels1.add(fieldmap.get(fName1).getDescribe().getLabel());
fieldLabelNamemap1.put(fieldmap.get(fName1).getDescribe().getLabel(), fName1);
}
}
for (String fLabel1:fieldLabels1){
if(flabel1 !='Created Date'&& flabel1!='Last Activity Date' && flabel1!='Last modified Date' && flabel1!='Deleted' && flabel1!='System modstamp'&& flabel1!='')
{
//lstobjectfields.add(new selectOption(fieldLabelNamemap.get(flabel),fLabel));
lstobjectfields1.add(fieldLabelNamemap1.get(flabel1));
}
}
system.debug('#### All Fields are ####'+lstobjectfields1);
return lstobjectfields1;
}
}
(3). Retrieve the picklist values from the picklist
field:
If we don't have standard controller then we have to use
the following sample.
page:
=====
<apex:page
controller="RetrievePicklistData">
<apex:form >
<apex:outputlabel value="Stage"/>
<apex:selectList
size="1" >
<apex:selectOptions
value="{!pickNames}">
</apex:selectOptions>
</apex:selectList>
</apex:form>
</apex:page>
class:
=======
public with sharing
class RetrievePicklistData {
public
List<SelectOption> getpicknames()
{
set<String>
setobj = new set<string>();
List<SelectOption>
options = new List<SelectOption>();
Schema.DescribeFieldResult
ccity =
Schema.sObjectType.Opportunity.fields.StageName.getSObjectField().getDescribe();
options.add(new
SelectOption('--None--', '--None--'));
for(PicklistEntry
ent:ccity.getpicklistvalues())
{
options .add(new
SelectOption(ent.getValue(), ent.getLabel()));
setobj.add(ent.getvalue());
}
return options;
}
}
To get the Object properties such as keyfix, label,plural label etc…..:
Schema.DescribeSObjectResult sobjectResultTemp = Schema.sobjecttype.Account;
system.debug('==>Account Properties==>'+sobjectResultTemp);
System.debug('==>Account Prefix==>'+sobjectResultTemp.getKeyPrefix());
System.debug('==> Acount Plural label==>'+sobjectResultTemp.getLabelPlural());
System.debug('==> Account Label ==>'+sobjectResultTemp.getLabel());
Get all the required fields of sObject dynamically?
There is no direct property
available in Apex dynamic API to represent the required field. However there is
another way to know about it.
If any field have below three properties then it is mandatory field.
If any field have below three properties then it is mandatory field.
1. If it is Creatable
2. If it is not nillable and
3. If it does not have any default value
Map<String,
Schema.SObjectType> m = Schema.getGlobalDescribe()
;
system.debug('==>m
is==>'+m);
Schema.SObjectType s =
m.get('Account') ;
system.debug('==>Sobject Type
is ==>'+s);
Schema.DescribeSObjectResult r =
s.getDescribe() ;
system.debug('==>DescribeSObjectResult==>'+r);
Map<String,Schema.SObjectField>
fields = r.fields.getMap() ;
system.debug('==>fields==>'+fields);
List<String>
lstrequiredfields=new List<String>();
for(String f : fields.keyset())
{
Schema.DescribeFieldResult desribeResult =
fields.get(f).getDescribe();
if( desribeResult.isCreateable() && !desribeResult.isNillable()
&& !desribeResult.isDefaultedOnCreate()
{
//This is mandatory / required
field
lstrequiredfields.add(f);
}
}
system.debug('==>lstrequiredfields==>'+lstrequiredfields);
Getting Childrelationships from an object using dynamic
Apex
If
an sObject is a parent object, you can access the child relationship as well as
the child sObject using the ChildRelationship object methods.
A
ChildRelationship object is returned from the sObject describe result using the
getChildRelationship method. For
example:
Schema.DescribeSObjectResult describeresult =
Account.SObjectType.getDescribe();
//it gives
Account object properties or describe
results;
List<Schema.ChildRelationship> lstchildrelationships =describeresult.getChildRelationships();
//It gives you all
the childrelationships associated with the account.To get relationship names
from the above list;
for(Schema.ChildRelationship
relname:lstchildrelationships){
System.debug('Relationshipname:'+relname.getrelationshipname());
}
Limitation:
You
can only use 100getChildRelationships method calls per Apex request.
Record Type
Id without SOQL query:
We
have getRecordTypeInfosByName() method to get record type id with
out SOQL query.
We can avoid SOQL query on RecordType object with this method.The following example shows how to access Record Type information through dynamic apex.
Schema.DescribeSObjectResult
resSchema = Account.sObjectType.getDescribe();
//getting
all Recordtype Account
if(resSchema.getRecordTypeInfosByName()
!=null) {
Map<String,Schema.RecordTypeInfo>
recordTypeInfo = resSchema.getRecordTypeInfosByName();
system.debug('==>recordTypeInfo==>'+recordTypeInfo);
//Getting
Business Record Type Id
if(recordTypeInfo.containsKey('Business')) {
Id rtId =
recordTypeInfo.get('Business').getRecordTypeId();
system.debug('==>Record Type id is
==>'+rtId);
}
}
Display
Trigger names of selected objects:
List<String>
triggerName = new List<String>();
List<ApexTrigger> apexTriggers = new
List<ApexTrigger>();
Schema.DescribeSObjectResult
resSchema = Account.sObjectType.getDescribe();
system.debug('==>resSchema==>'+resSchema);
for(ApexTrigger aptrig:[select id,name,Status,TableEnumOrId
from apextrigger where TableEnumOrId=:resSchema.getName()]){
triggerName.add(aptrig.name);
apexTriggers.add(aptrig);
}
system.debug('==>trigger
Name==>'+triggerName);
System.debug('==>apexTriggers==>'+apexTriggers);
Access Salesforce app information
You can obtain describe information for standard and
custom apps available in the Salesforce user interface. Each app corresponds to
a collection of tabs. Describe information for an app includes the app’s label,
namespace, and tabs. Describe information for a tab includes the sObject
associated with the tab, tab icons and colors.
This example shows how to get the tab sets for each
app. The example then obtains tab describe metadata information for the Sales
app. For each tab, metadata information includes the icon URL, whether the tab
is custom or not, and colors among others. The tab describe information is
written to the debug output.
// Get tab set describes for each app
List<Schema.DescribeTabSetResult> tabSetDesc = Schema.describeTabs();
// Iterate through each tab set describe for each app and display the info
for(DescribeTabSetResult tsr : tabSetDesc) {
String appLabel = tsr.getLabel();
System.debug('Label: ' + appLabel);
System.debug('Logo URL: ' + tsr.getLogoUrl());
System.debug('isSelected: ' + tsr.isSelected());
String ns = tsr.getNamespace();
if (ns == '') {
System.debug('The ' + appLabel + ' app has no namespace defined.');
}
else {
System.debug('Namespace: ' + ns);
}
// Display tab info for the Sales app
if (appLabel == 'Sales') {
List<Schema.DescribeTabResult> tabDesc = tsr.getTabs();
System.debug('-- Tab information for the Sales app --');
for(Schema.DescribeTabResult tr : tabDesc) {
System.debug('getLabel: ' + tr.getLabel());
System.debug('getColors: ' + tr.getColors());
System.debug('getIconUrl: ' + tr.getIconUrl());
System.debug('getIcons: ' + tr.getIcons());
System.debug('getMiniIconUrl: ' + tr.getMiniIconUrl());
System.debug('getSobjectName: ' + tr.getSobjectName());
System.debug('getUrl: ' + tr.getUrl());
System.debug('isCustom: ' + tr.isCustom());
}
}
}
Dynamic SOQL
Dynamic SOQL refers to the creation of a SOQL string
at runtime with Apex code. Dynamic SOQL enables you to create more flexible
applications. For example, you can create a search based on input from an end
user, or update records with varying field names
To create a dynamic SOQL query at runtime, use the
database query method, in one of the following ways:
• Return a single sObject when the query returns a
single record:
sObject
S = Database.query(string_limit_1);
• Return a list of sObjects when the query returns
more than a single record:
List<sObject>
L = Database.query(string);
The database query method can be used wherever an
inline SOQL query can be used, such as in regular assignment statements and for
loops. The results are processed in much the same way as static SOQL queries
are processed.
Dynamic SOQL results can be specified as concrete
sObjects, such as Account or MyCustomObject__c, or as the generic sObject data
type. At runtime, the system validates that the type of the query matches the
declared type of the variable. If the query does not return the correct sObject
type, a runtime error is thrown. This means you do not need to cast from a
generic sObject to a concrete sObject.
EX:-
String myTestString = 'TestName';
List<sObject> L = Database.query('SELECT Id FROM
MyCustomObject__c WHERE Name = :myTestString');
Retrieving all fields without
specifying field names in SOQL Query:
string fieldnames='
';
List<sObject>
lstaccount = new List<Account>();
Map<String,
Schema.SObjectField> M = Schema.SObjectType.Account.fields.getMap();
for(Schema.SObjectField
s:m.values()){
Schema.DescribeFieldResult
sfield=s.getDescribe();
fieldnames+=s+','; //Here we concatenating all field names with
comma seperation for preparing SOQL query
}
system.debug('==>fieldnames==>+fieldnames);
//Fieldnames string
contains all the fields with comma separation
fieldnames=fieldnames.substring(0,fieldnames.length()-1);
system.debug('==>fieldnames==>+fieldnames);
string query='select '+fieldnames+' from
Account';
//Here we are preparing string query(dynamic
SOQL using "fieldnames" string)
if(query!=null && query!=''){
lstaccount=database.query(query);//Here we
will get all field values from account.
}
system.debug('==>lstaccount==>'+lstaccount);
You CAN directly use primitive data types in SOQL.
So what does this
means?
This means you can
directly use any Integer, String , Date, Datetime,Double, Id variable along
with Collection of this variable within the query.
For Example:
a) You are allowed to do this
//initialize the Datetime with current time
DateTime now = System.now();
//query accounts by merging the variable name inside the query
string
List<Account> accountList = Database.query('SELECT Id FROM
Account WHERE CreatedDate =:now');
b)You can also include LISTs(Collections) in your queries
List<String> accNameList = new
List<String>{'Acc1','Acc2'}
//query accounts by merging the variable name inside the query
string
List<Account> accountList = Database.query('SELECT Id FROM
Account WHERE Name IN:accNameList');
You CANNOT use complex types in a Dynamic SOQL directly.This means that
you cannot use any Sobject, Apex Class or Any other user defined data type
inside the Dynamic Query. In short you cannot use a dot (".")
operator to specify a field value in a Dynamic query.
For Example :
a) Using an Sobject inside the query String will not work
//initialize a Account with a Name value for demo
Account acc = new
Account(Name='MyAccount');
//query accounts by
merging the variable name inside the query string
//This will not work
List<Account>
accountList = Database.query('SELECT Id FROM Account WHERE Name =:acc.Name');
//But You can always make the above work by
writing the code as.
//initialize a Account with a Name value for demo
Account acc = new Account(Name='MyAccount');
String accountName = acc.Name
//query accounts by merging the variable name
inside the query string
List<Account> accountList =
Database.query('SELECT Id FROM Account WHERE Name =: accountName ');
SOQL Injection
SOQL injection
is a technique by which a user causes your application to execute database
methods you did not intend by passing SOQL statements into your code. This can
occur in Apex code whenever your application relies on end user input to
construct a dynamic SOQL statement and you do not handle the input properly.
To prevent SOQL
injection, use the escapeSingleQuotes method. This method adds the escape
character (\) to all single quotation marks in a string that is passed in from
a user. The method ensures that all single quotation marks are treated as
enclosing strings, instead of database commands.
More about soql
Injection:
Dynamic SOSL:
Dynamic SOSL refers to the creation of a SOSL string
at runtime with Apex code. Dynamic SOSL enables you to create more flexible
applications. For example, you can create a search based on input from an end
user, or update records with varying field names.
To create a dynamic SOSL query at runtime, use the
search query method. For example:
List<List <sObject>> myQuery =
search.query(SOSL_search_string);
The following example exercises a simple SOSL query
string.
String searchquery='FIND\'Edge*\'IN ALL FIELDS RETURNING
Account(id,name),Contact, Lead';
List<List<SObject>>searchList=search.query(searchquery);
Dynamic SOSL statements evaluate to a list of lists
of sObjects, where each list contains the search results for a particular
sObject type. The result lists are always returned in the same order as they
were specified in the dynamic SOSL query. From the example above, the results
from Account are first, then Contact, then Lead.
The search query method can be used wherever an
inline SOSL query can be used, such as in regular assignment statements and for
loops. The results are processed in much the same way as static SOSL queries
are processed.
Dynamic DML
In addition to querying describe information and building SOQL queries at runtime, you can also create sObjects dynamically, and insert them into the database using DML.
To create a new sObject of a given type, use the newSObject method on an sObject token. Note that the token must be cast into a concrete sObject type (such as Account). For example:
This example shows how to obtain the sObject token through the Schema.getGlobalDescribe method and then creates a new sObject using the newSObject method on the token. This example also contains a test method that verifies the dynamic creation of an account.
public class DynamicSObjectCreation {
public
static sObject createObject(String typeName) {
Schema.SObjectType targetType =
Schema.getGlobalDescribe().get(typeName);
if (targetType == null) {
// throw an exception
}
// Instantiate an sObject with the
type passed in as an argument
//
at run time.
return targetType.newSObject();
}
}
@isTest
private class DynamicSObjectCreationTest {
static
testmethod void testObjectCreation() {
String typeName = 'Account';
String acctName = 'Acme';
// Create a new sObject by passing
the sObject type as an argument.
Account a =
(Account)DynamicSObjectCreation.createObject(typeName);
System.assertEquals(typeName,
String.valueOf(a.getSobjectType()));
// Set the account name and insert
the account.
a.Name = acctName;
insert a;
// Verify the new sObject got
inserted.
Account[] b = [SELECT Name from
Account WHERE Name = :acctName];
system.assert(b.size() > 0);
}
}
Or
// create instance of
types dynamically
SObjectType
accountType = Schema.getGlobalDescribe().get('Account');
SObject acc =
accountType.newSObject();
// modify values
using .put notation
acc.put('Name','Some
Name');
insert acc;
id accId = acc.Id;
// read back
dynamically and modify again using .put notation if necessary
acc =
Database.query('Select Name From Account Where Id = :accId');
System.debug(
acc.get('Name') );
More on
Dynamic DML:
14 comments:
Great Post..
super
nice description about Dynamic
Nice post. Thanks!!!
Excellent srinivas
Excellent srinivas
How to get the list of all available subject in salesforce database using Apex (Dynamic Apex)?
How to get all the required fields of subject dynamically?
How to display error messages in the visual force page ?
salesforce training in Chennai
Thanks for sharing a good information about salesforce . .......This article is very useful to learners. Sales force online training
nice write up with good details. thanks
the article provided by you is very nice and it is very helpful to know about the salesforce ..i found a article related to you..once you can check it
SalesForce online training
thanks a lot dear.
godaddy renewal coupon
Brock Lesnar
This blog contains many lessons.
https://onlineitguru.com/salesforce-online-training-placement.html
Really Appreciable!
Bulk Object Field Creator
Appexchange Url
thanks for sharing..
Server and Storage
Post a Comment