The Apex Metadata API (a native Apex wrapper around the Salesforce equivalent) has had a steady increase of followers and questions since it was created in October 2012. Judging by the feedback I have had its enabling quite a few time saving and wizard style solutions in your native applications! This blog introduces a new example using Batch Apex to ‘script’ the creation of custom objects, fields, pages etc. in an org more easily in a none UI context.
The Salesforce Metadata API is an asynchronous API, which means you have to poll it to determine the fate of your requests. At launch I provided some examples of doing this via apex:actionPoller using Visualforce. Recently given some queries on the forums and this blog, I decided to invest a little more in a Batch Apex example. The new MetadataCreateJob class (and test) implements Batch Apex using a custom iterator to process the Metadata items in order and will even wait for proceeding items to complete, to handle dependencies.
The following example (included here in the repo) will perform the following steps with the given name.
- Create a custom object of the given name
- Create 2 custom fields on the object
- Create a Visualforce page that references the two fields using the standard controller
- Email the user once the above is completed, including any errors returned by checkStatus.
Trying out the sample code…
If you want to try out the following example install, MetadataService.cls, MetadataServiceExamples.cls and MetadataCreateJob.cls in your org (test classes are also available). You will also need to add to your Remote Site Settings (under Security Controls), https://na11.salesforce.com (changing na11 to your org instance). Then issue the following command from the Developer Console or Execute Annoynmous from Eclipse.
MetadataServiceExamples.dynamicCreation('Test');
Once you receive the confirmation email, you will then see the following items in your org…
If you repeat the above you should see the following errors (returned from Metadata API’s checkStatus operation) in the email once the job is complete.
The code to perform the above steps is shown below, note how the ‘wait’ parameter is used on the job items to cause the items to be processed only once a dependent proceeding item has been completed.
public static void dynamicCreation(String objectName) { // Define Metadata item to create a Custom Object MetadataService.CustomObject customObject = new MetadataService.CustomObject(); customObject.fullName = objectName + '__c'; customObject.label = objectName; customObject.pluralLabel = objectName+'s'; customObject.nameField = new MetadataService.CustomField(); customObject.nameField.type_x = 'Text'; customObject.nameField.label = 'Test Record'; customObject.deploymentStatus = 'Deployed'; customObject.sharingModel = 'ReadWrite'; // Define Metadata item to create a Custom Field on the above object MetadataService.CustomField customField1 = new MetadataService.CustomField(); customField1.fullName = objectName+'__c.TestField1__c'; customField1.label = 'Test Field 1'; customField1.type_x = 'Text'; customField1.length = 42; // Define Metadata item to create a Custom Field on the above object MetadataService.CustomField customField2 = new MetadataService.CustomField(); customField2.fullName = objectName+'__c.TestField2__c'; customField2.label = 'Test Field 2'; customField2.type_x = 'Text'; customField2.length = 42; // Define Metadata item to create a Visualforce page to display the above field MetadataService.ApexPage apexPage = new MetadataService.ApexPage(); apexPage.apiVersion = 25; apexPage.fullName = objectName.toLowercase(); apexPage.label = objectName + ' Page'; apexPage.content = EncodingUtil.base64Encode(Blob.valueOf( '<apex:page standardController=\''+objectName+'__c\'>'+ '{!' + objectName + '__c.TestField1__c}' + '{!' + objectName + '__c.TestField2__c}' + '</apex:page>')); // Pass the Metadata items to the job for processing, indicating any dependencies MetadataCreateJob.run( new List<MetadataCreateJob.Item> { new MetadataCreateJob.Item(customObject), new MetadataCreateJob.Item(customField1, null, true), // Set wait to true, to process after object creation new MetadataCreateJob.Item(customField2), new MetadataCreateJob.Item(apexPage, null, true) // Set wait to true, to process after field creation }, new MetadataCreateJob.EmailNotificationMetadataAsyncCallback()); }
Note: This will email the user when the work is completed. However you can implement your own callback handler if you wish, take a look at the MetadataCreateJob.IMetadataAsyncCallback interface and the email example included.
This is quite a basic example, but starts to illustrate how you could build a more dynamic solution. Perhaps one that takes some form of data input, like a CSV file, which will create the object and fields, before importing the data. Or one that is fired from an Apex Trigger whenever some configuration data in your application is changed?
What will you do with this?
May 8, 2013 at 11:36 pm
Reblogged this on Sutoprise Avenue, A SutoCom Source.
June 26, 2013 at 2:53 pm
Hi
Can you give e example for trigger and weblinks?
There are some problem, I think.
best regards
Yue
June 30, 2013 at 9:46 am
Take a look at the Deploy example (it deploys an Apex Class, but the process is the same). Unfortunately the Salesforce Metadata API (which this library wraps), does not allow creation of Apex Classes or Triggers, via the ‘create’ operation most of the other component types can use.
June 30, 2013 at 9:53 am
Thanks a lot, It can be a good solution. I will try that. 😉
June 27, 2013 at 12:09 pm
Hi
in link
http://www.salesforce.com/us/developer/docs/api_meta/index_Left.htm#CSHID=meta_weblink.htm|StartTopic=Content%2Fmeta_weblink.htm|SkinName=webhelp first line say that
“Represents a Weblink defined in a custom object. It extends the Metadata metadata type and inherits its fullName field.”
but weblink does’t extends the Metadata. so I am not sure if it can be a problem.
Yue
June 30, 2013 at 9:44 am
Yes that will be the issue, i mentioned in the read me that I’d not gone through them all as yet. I’ve just updated it with the required changes and an example here for WebLink for you, enjoy! In the future if you do find another you need and its not been done, please feel free to follow the steps here (also in the read me) and submit them back to the repository.
– Review WSDL for types that extend ‘tns:Metadata’ and update related Apex classes to also extend Metadata
– Review WSDL for types that extend ‘tns:MetadataWithContent’ and update related Apex classes to also extend MetadataWithContent
– Apply the following to each class that extends Metadata, e.g. for CustomObject
Add the following at the top of the class
public String type = ‘CustomObject’;
public String fullName;
Add the following at the top of the private static members
private String[] type_att_info = new String[]{‘xsi:type’};
private String[] fullName_type_info = new String[]{‘fullName’,’http://www.w3.org/2001/XMLSchema’,’string’,’0′,’1′,’false’};
Add ‘fullName’ as the first item in the field_order_type_info String array, e.g.
private String[] field_order_type_info = new String[]{‘fullName’, ‘actionOverrides’ …. ‘webLinks’};
– Apply the following to each class that extends MetadataWithContent, e.g. for ApexPage
Add the following after ‘fullName’
public String content;
Add the following after ‘fullName_type_info’
private String[] content_type_info = new String[]{‘content’,’http://www.w3.org/2001/XMLSchema’,’base64Binary’,’0′,’1′,’false’};
Add ‘content’ after ‘fullName’ in the field_order_type_info String array, e.g.
private String[] field_order_type_info = new String[]{‘fullName’, ‘content’, ‘apiVersion’,’description’,’label’,’packageVersions’};
June 30, 2013 at 9:56 pm
I have already finished it in the same way. I take a long time to find right type (webLink, but It is weblink in API DOC). Now it works. Thanks for your Good Scripting again, it is all useful to me. 😉
July 9, 2013 at 8:21 am
Hi
I just want to add/remove field from Custom object page layout also make it read only from the page layout using metadata api can u provide me the syntax,
Other problem is that I want to create profile by cloning the “Standard User” using Apex Metadata API .
Can u help me to come out of this.
July 9, 2013 at 4:58 pm
Wow thats quite an ask, something I have to confess I’m not able to turn around quickly, but will for sure turn my attention to giving you a more detailed answer in the coming days. In the meantime, for Layout editing you will have to review and combine the Retrieve and Deploy examples and place logic in the middle to parse the XML files (there is a native XML parser in Apex) to manipulate the layout definitions before feeding them back into the Deploy process. There is no direct clone API that I am aware, you will simply have to retrieve the Profile definition, modify the name and deploy, again the Retrieve and Deploy examples should show you the plumbing to make these two operations happen. Sorry I cannot give a more detailed answer at this stage, but hopefully this gives you some pointers… 🙂
July 15, 2013 at 1:30 pm
hi Andrew
Can u give me an example for Layout editing that how to Retrieve and Deploy and place logic in the middle to parse the XML files (there is a native XML parser in Apex) to manipulate the layout definitions before feeding them back into the Deploy process.
And same for the profile because in this process there are some points which are not clear, So can u post an example of doing the same
My mail id is abhishek_sf@hotmail.com
thanks in advance
July 10, 2013 at 11:06 am
thanks for reply Andrew
Your reply is little bit helpful bcoz it give me direction than how can we do this. If you find the solution that how we can create profile using apex Metadata api or add/remove field from Custom object page layout also make it read only from the page layout using metadata api then please let me know.
My mail id is abhishek_sf@hotmail.com
thanks in advance
August 19, 2013 at 7:56 pm
Andy, really lovin this API. I’m struggling with the limitations I keep running into. I wanted to be able to get the columns on a list view so I could export to Excel, but any Views created with “Visible Only To Me” selected are not available in the Metadata API.
I am also trying to develop a trigger on a configuration object that will update the available pick list options on another object. However, it appears that you can only add pick list options via the metadata api. You cannot remove or modify existing options.
Do you have any advice for working around either of these limitations?
August 21, 2013 at 6:54 pm
RE: ListViews. Yes sadly the Salesforce Metadata API documentation for ListView states this “List views with the Visible only to me Restrict Visibility option are not accessible in Metadata API. Each of these list views is associated with a particular user.”.
RE: Deleting Picklist options. The Salesforce docs do seem to indicate delete is possible “Picklist values are deleted if necessary on a deploy of a custom field in API version 27.0 and later.”, the wrapper is current at 28, so this should work. Have you tried the update picklist example here?
August 21, 2013 at 8:51 pm
This developer seems to have managed to get deletion of picklist values working and has published the code to his utility, you might want to check it out as well.
August 27, 2013 at 8:54 am
Hi, As you have mentioned in the Note,
Note: This will email the user when the work is completed. However you can implement your own callback handler if you wish, take a look at the MetadataCreateJob.IMetadataAsyncCallback interface and the email example included.
MetadataCreateJob.run(
batchjobList,
new MetadataCreateJob.EmailNotificationMetadataAsyncCallback());
I am adding customObject in batchJobList. and passing as parameter. Now, I want to handle call back function in this. so, whatever result comes from there and based on their result I want to do next process…
How Can I do it ?
Thanks
August 29, 2013 at 6:15 am
Take a look at the MetadataCreateJob.EmailNotificationMetadataAsyncCallback class, it implements an interface, you can create one of your own to do whatever you need. I’m sorry I don’t have a great deal of time to give a better example, I’m in the US currently and got quite a busy schedule. Happy to take a closer look next week if your still puzzling.
September 1, 2013 at 2:50 pm
Hi Andrew…
I read few of your comments on salesforce.stackexchange.com mentioning that metadata is exposed to REST api. I searched online for example but no luck. Can you please provide an example or link.
Actually I am facing a problem these days with metadata api. I am using REST api and metadata api for an app. I thought that REST api cannot be used for metadata calls therefore I am using soap api for metadata calls.. Please have a look at my question : http://salesforce.stackexchange.com/questions/15891/how-to-use-salesforce-rest-api-session-for-metadata-api
September 1, 2013 at 7:11 pm
Sadly the Salesforce REST API for Metadata (which as in pilot around a year ago) has been shelved for now, they have not said when it will return. It looks like the Session ID maybe incompatible between the API’s, sometimes Salesforce issues difference types of session Id’s. I’ve seen this before. Anyway, I see metadaddy is working with you, he is a Salesforce technical evangelist and is very familiar with the Salesforce API’s. I’ll for sure keep an eye on the question for you though! 😉
September 2, 2013 at 4:57 am
Thank you so much 🙂
October 3, 2013 at 12:11 pm
Hi Andrew ,Am trying to create a custom object using metadata ,i created stub and requested sessionid and metadataurl using enterprise wsdl .and am using these parameters im metadata class ,while am saving the class
1.Field name FirstName Doesn’t exist
2.Compile Error: Invalid type: MetadataService.Metadata.
this is my code .
soapSforceCom200604Metadata.CustomObject cs =new soapSforceCom200604Metadata.CustomObject();
cs.fullName = ‘Test__c’;
cs.label = ‘Test’;
cs.pluralLabel = ‘Tests’;
cs.nameField = new MetadataService.CustomField();
cs.nameField.type_x = ‘Text’;
cs.nameField.label = ‘Test Record’;
cs.deploymentStatus = ‘Deployed’;
cs.sharingModel = ‘ReadWrite’;
soapSforceCom200604Metadata.AsyncResult[] results = meta.create(new List { cs });
Please help where am doing wrong ..
October 3, 2013 at 7:16 pm
Try using the MetadataService.cls (prebuilt for you from the WSDL). There is also an create object example in the MetadataServiceExamples.cls. Both are Apex classes in the associated GitHub repo.
October 24, 2013 at 6:44 am
Thanks a lot Andrew ,,Have a small Question ,is partner wsdl ,enterprise wsdl and meta data wsdl is same for every one in salesforce org i mean developer Edition
October 24, 2013 at 8:54 am
Partner and Metadada WSDL are not bound to the specific org you downloaded them from. Enterprise WSDL is. Check out the Salesforce SOAP API Developers guide for a full discussion on these differences.
October 24, 2013 at 11:02 am
Hey there Andrew ,Fantastic Article ,have a few Questions ,While Am Converting my Metadata Wsdl ,am getting a error like port name already exits ,and then i searched through Google they said to change wsdl port type to some x name ,after that i parsed it successfully ,as i seen through your parsed metadata code in gitHub ,many of the classes were extended to metadata , like ” public class CustomObject extends Metadata “but in my parsed wsdl class i haven’t found such things ,and am also unable to find fullName in my parsed class ..Can u help me to come out of this. and once again Thanks for Such a Wonder Full Blog Andrew 🙂
October 24, 2013 at 3:40 pm
Your very welcome. Just wanted to check you had seen the MetadadaSevice.cls in the repo? I have already converted the WSDL for you.
January 22, 2014 at 5:48 am
Hi Andrew,
Is there a way to change the name and type of existing custom field name say “Middle Name” for example, in a case object using Meta data API?
January 22, 2014 at 4:18 pm
Yes this should be possible, if you can do it in the UI, i know some type changes are restricted. Take a look at this, https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataServiceExamples.cls#L119. Notice the currentName field. Feel free to contribute back a snippet once you get it working or let me know if its still giving you some challenges.
May 3, 2014 at 2:04 pm
thanks Andrew.I have one question.In visualforce page i created one field type as text.i entered values of text as 1,2,3 and another field as also text values as 2,3,4.after i created one field as picklist.i given picklist values are textarea,drop.after competion of above field values i selected picklist value as drop, automatically one field will be created name as above text value(1,2,3) and datatype as picklist values are(2,3,4).after click save all values are stored in database.How ?
please give replay
thanks & Regards,
mahesh
May 3, 2014 at 4:31 pm
That’s a very broad question indeed. What have you tried so far and what resources are you reading, for example developer.salesforce.com
May 6, 2014 at 4:21 am
thank u Andrew Fawcett
Actually my requirement is
Fields are
1)Label For Field 1(type=text)
2)Default value for field 1(type=text)
3)Maximum length of field 1(type=text)
4)Display size of field 1(type=text)
5)Field Datatype(picklist) values are text area,normal,drop,checkbox,radio
Actually my requirement is i given allfields data(like Label For Field 1(current location),Default value for field 1(banglore,Chennai,hyderabad etc…) ,Maximum length of field 1(40),Display size of field 1(255))and select picklist value (like Drop)automatically that picklist values related field is created in database and as well as display that field in visualforce page.
please help this requiement
thanks
Mahesh.k
May 6, 2014 at 6:59 am
So you are trying to create a Visualforce Page to describe a field definition and then a button to create it? Is this your requirement in more general terms? If so there is an example of creating a field in the readme and further ones in the MetadataServiceExamples.cls file including other field type like picklist. Your can store in your VF page viewstate for editing the MetadataService.CustomField type until you are ready to call the createMetadata method. Please review the Visualforce developers guide on the VF components you need, such as apex:inputText apex:selectList. I hope this information gets you started, I am not able to write a fully coded example for you, but if you get started and have more questions please feel free to ask again, good luck!
May 6, 2014 at 7:13 am
As a fresher i joined our company, this requirement from one month i try to solve but as ur posting click a button field will be created in an object i completed through visualforce page .Actually i created 4 fields like above fields using component and their input values i added into metadata related varibles like
public Integer field4 { get; set; }
public String field3 { get; set; }
public String field2 { get; set; }
public String field1 { get; set; }
MetadataService.CustomField customField = new MetadataService.CustomField();
customField.fullName = ‘Contact.field1__c’;
customField.label = ‘field2’;
customField.type_x = ‘field3’;
customField.length = field4;
after click a create a button the following error will be occur
Visualforce Error
Help for this Page
System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: ‘field3’ is not a valid value for the enum ‘FieldType’ faultcode=soapenv:Client faultactor=
Error is in expression ‘{!createField}’ in component in page bisoftsols:create
Class.Bisoftsols.MetadataService.MetadataPort.create: line 8276, column 1
Class.Bisoftsols.CreateCls.createField: line 22, column 1
please help me
May 6, 2014 at 7:45 am
You must assign the variable values not strings containing the variable names.
customField.label = field2;
customField.type_x = field3;
You need to learn some programming basics, the Apex Developers guide is a good place to start. http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_datatypes_variables_intro.htm
May 6, 2014 at 8:01 am
thank u Andrew Fawcett
May 6, 2014 at 11:01 am
ok Andrew Fawcett but customField.fullName =’Bisoftsols__DynaForm__c.Field1__c’ .all fields ok but this field is same as created with field1__c api name this field name is not changed in object.and how to get after creation of this field in an visualforce page.
please help me
May 6, 2014 at 12:10 pm
I am really sorry I cannot understand your question. It might be worth raising this question and some sample code on StackExchange. Are you reading any of the Salesforce documentation on Apex of Visualforce? Please try when you do post a question there to explain what your end goal is, what you have tried, what documentation you have read and show some sample code.
May 6, 2014 at 12:24 pm
Field Datatype
class:
public with sharing class CreateCls {
public DynaForm__C a { get; set; }
public Integer field4 { get; set; }
public String field3 { get; set; }
public String field2 { get; set; }
public String field1 { get; set; }
public MetadataService.AsyncResult result {get;set;}
public DescribeFieldResult[] fields {
get
{
if (fields == null)
{
fields = new DescribeFieldResult[0];
for (SObjectField sf : Schema.SObjectType.DynaForm__C.Fields.getMap().values())
{
fields.add(sf.getDescribe());
}
}
return fields;
} private set; }
public PageReference createField()
{
// Create a Custom Field
MetadataService.CustomField customField = new MetadataService.CustomField();
customField.fullName =’Bisoftsols__DynaForm__c.Field1__c’ ;
customField.label = Field2;
customField.type_x = Field3;
customField.length = Field4;
result = createService().create(new List { customField })[0];
System.debug(‘—-result—–‘ +result);
// Display status of the request
displayStatus();
return null;
}
public PageReference deleteField()
{
// Delete a Custom Field
MetadataService.CustomField customField = new MetadataService.CustomField();
customField.fullName = ‘Bisoftsols__DynaForm__c.Field1__c’;
System.debug(‘——fullname———-‘+customField.fullName);
result = createService().deleteMetadata(new List { customField })[0];
// Display status of the request
displayStatus();
return null;
}
public PageReference checkStatus()
{
// Check status of the request
result = createService().checkStatus(new List { result.Id })[0];
displayStatus();
return null;
}
private void displayStatus()
{
// Inspect the AsyncResult and display the result
ApexPages.addMessage(
new ApexPages.Message(ApexPages.Severity.Info,
result.done ? ‘Request completed’ : ‘Request in progress…’));
if(result.state == ‘Error’)
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.Error, result.message));
if(result.done)
result = null;
}
private static MetadataService.MetadataPort createService()
{
// Create the Metadata API service stub and authenticate
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
return service;
}
}
in above code customField.fullName =’Bisoftsols__DynaForm__c.Field1__c’ ; here Field1 field only create in the data base,but i given some value(Label for field 1)but, this(Field1)is not take that value.
please after creation of this field how to display this field in an visualforce page dynamically(dont touch admin part).Please help me
Thanks
Mahesh
May 6, 2014 at 12:26 pm
Search for Dynamic Visualforce in the Visualforce Developers guide. Also check out the new examples for creating field you don’t need to use the asynchronous versions of the methods anymore and this can simplify your code.
May 6, 2014 at 12:25 pm
page:
Field Datatype
May 6, 2014 at 12:25 pm
Field Datatype
May 6, 2014 at 12:27 pm
sorry i try to copy page code that code is not copied
Field Datatype
May 6, 2014 at 1:06 pm
sorry i try to paste the code .but code is not pasted
May 7, 2014 at 7:13 am
hi Andrew Fawcett Field i created but how to display created field dynamically on visualforce page. i saw Dynamic Visualforce in the Visualforce Developers guide, using this field label only displayed on visualforce page but related field type(text box) not displayed.
please help me
May 7, 2014 at 9:34 am
I really want to help, but using blog comments is not easy, it would be better if you moved your latest question to http://salesforce.stackexchange.com/ where you can share your code, as this makes it easier to answer questions also. Sorry but I cannot help you further like this, i am also on holiday and understand your under pressure. So feel giving the rest of the Salesforce community a chance at helping you is also best. Hope you understand.
May 7, 2014 at 12:36 pm
ok thanks Andrew Fawcett .this is my mail id:mahesh060708@gmail.com
thank u for your reply Because of ur replay I learn something
thanks
Mahesh.
May 9, 2014 at 10:06 am
Hi Andrew Fawcett I completed how to create fields(text,textarea,picklist,Checkbox)Dynamically in an object.But last requirement,How to retrive Creted Fields dynamically (like )using visualforce page and apex.Please help me
May 9, 2014 at 10:07 am
Excellent! You can retrieve using the readMetadada method.
May 9, 2014 at 10:41 am
I try to tis code but this code not working
Class:
public Book__c testDetails { get; set; }
//public List ACTFields{get; set;}
public List getACTFields() {
return getFields(‘Book__C’,’fieldset1′);
}
public static List getFields(String objectName, String fieldSetName) {
Map GlobalDescribeMap = Schema.getGlobalDescribe();
Schema.SObjectType SObjectTypeObj = GlobalDescribeMap.get(objectName);
Schema.DescribeSObjectResult DescribeSObjectResultObj = SObjectTypeObj.getDescribe();
Schema.FieldSet fieldSetObj = DescribeSObjectResultObj.FieldSets.getMap().get(fieldSetName);
return fieldSetObj.getFields();
}
Below error will be occur:
System.NullPointerException: Attempt to de-reference a null object
Class.Maheshfile.ACTCls.getFields: line 17, column 1
Class.Maheshfile.ACTCls.getACTFields: line 10, column 1
May 9, 2014 at 11:00 am
What is at line 17?
May 9, 2014 at 11:09 am
Thank u Andrew Fawcett .
line17:-Schema.DescribeSObjectResult DescribeSObjectResultObj = SObjectTypeObj.getDescribe();
line10:- return getFields(‘Book__C’,’fieldset1′);
In page i was using
apex:repeat value=”{!ACTFields}”
AND
apex:inputField value=”{!testDetails[f.fieldpath]}” required=”{!OR(f.required,f.dbrequired)}”
May 12, 2014 at 6:12 am
Hi Andrew Fawcett,
I created object also using visualforce page. Is it possible assign custom tab dynamically created object using visualforce page and Apex class.
ERROR:Fields not return above class .this is my last requirement
please help me………
May 12, 2014 at 7:09 am
You need to use the CustomTab metadata type, http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_tab.htm, see example at the bottom for web custom tab, you will need to adapt the fields you set for a custom object custom tab. One approach i use is to create one via the Setup menu then download it via Eclipse or MavensMate to see what to fill in programatically.
May 12, 2014 at 7:23 am
the above problem(Fields not return above class ) solved but pagelayout fields not added(i.e; only which fields i added that fileldset(fieldset1) that fields only display in an visualforce page) dynamically that fieldset(fieldset1) .How to add pagelayout fields to fieldset dynamically .
please help me………
May 12, 2014 at 7:46 am
There is an example of updating a Fieldset here, https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataServiceExamples.cls#L547. Please check this file before asking questions, thanks.
May 12, 2014 at 1:24 pm
Hi Andrew Fawcett i can not understand tab creation .when i created object automatically how to create a custom tab of created object.
please help me……
May 12, 2014 at 1:25 pm
You cannot create a tab at the same time as creating an object, you must make a separate call to the createMetadata method
May 12, 2014 at 1:28 pm
thanks Andrew Fawcett, send me createMetadata method related url please
May 12, 2014 at 1:30 pm
Review the Metadada API Developers guide and also the MetadaServiceExamples.cls file for general examples. Also as I said earlier the CustomTab link and approach I described for learning what fields to complete.
May 12, 2014 at 2:33 pm
thank u Andrew Fawcett i created custom tab
May 12, 2014 at 2:38 pm
That’s great!
May 13, 2014 at 5:02 am
hi Andrew Fawcett,
Not Fieldset Updation(field updation means existing field change to new field according to my knowledge) .my requirement is ,when a click button how to add pagelayout fields to fieldset dynamically(I created object) and display that fields in an visualforce page dynamically using metadata api in salesforce OR any other way is there without using fieldset .
please help me…
May 13, 2014 at 8:13 am
Dynamic Visualforce or dynamically generate the Visualforce page via createMetadada?
May 13, 2014 at 8:42 am
I created One field as file name(object) ,when user enter file name and click save object is saved in database.Next user click createtab button that object related tab is created .Next click Createfields that page related object name reference to field creation page.This is my process flow.Now all fields are there in database. How to user see that form related fields in an visualforce page dynamically means when user enter formName and click formFields(what fields user created that filelds) ,that form fields all will be display in an visualforce dynamically(dynamically generate the Visualforce page via createMetadada)
May 13, 2014 at 8:56 am
Sounds like your having some fun. Is there a question here?
May 13, 2014 at 9:09 am
hi Andrew Fawcett,
Actually above i mentioned my requirement.how to dynamically generate the Visualforce page via createMetadada .this is my question
please help me…
May 13, 2014 at 10:20 am
In database fields i created using visualforce page and apex class, but how to retrieve created fields on visualforce page dynamically .
please help me……..
May 13, 2014 at 11:22 am
As I have said look at either Dynamic Visualforce components or dynamically create your Visualforce page as I have just replied
May 13, 2014 at 11:19 am
As before please check MetadataServiceExamples.cls there is an example in that for this
May 13, 2014 at 12:03 pm
I try to create and update fieldset the following code
public static void createAndUpdateFieldSet()
{
MetadataService.MetadataPort service = createService();
MetadataService.FieldSet fieldSet = new MetadataService.FieldSet();
fieldSet.fullName = ‘mahesh__Test__c.MyFieldSet’;
fieldSet.label = ‘My FieldSet’;
fieldSet.description = ‘Used by my VF page’;
MetadataService.AsyncResult[] results = service.create(new List { fieldSet });
List lstmyAvailableField = new List();
for(String s:lstmyAvailableField)
{
MetadataService.FieldSetItem myAvailableField = new MetadataService.FieldSetItem();
S = S.replaceAll(‘ ‘,’_’);
myAvailableField=s +’__c’
myAvailableField.isFieldManaged =true;
myAvailableField.isRequired = true;
fieldSet.lstmyAvailableField.add(myAvailableField);
}
List updateMetadataList = new List();
updateMetadataList.add(new MetadataService.UpdateMetadata());
updateMetadataList[0].currentName = ‘mahesh__Test__c.MyFieldSet’;
updateMetadataList[0].metadata = fieldSet;
MetadataService.AsyncResult[] results = service.updateMetadata(updateMetadataList);
}
But this code not working .using above code is possible to update fieldset (means i create a field that field automatically add to this fieldset)please help me..
May 13, 2014 at 9:59 pm
You have not told me the error your getting, so I am guessing it is your using the asynchronous create and the Fieldset has not been created by the time the rest of your code executes. Use createMetadata method instead.
May 14, 2014 at 4:32 am
Hi Andrew Fawcett,
This is my last requirement ,when i created field using visualforce page that created field automatically add to fieldset and and add created field visualforce page dynamically.
please help me
May 14, 2014 at 7:26 am
Sorry. Which part do you need help with? Have we not been discussing this all along? Did my previous responses not help? What have you tried?
May 14, 2014 at 12:11 pm
Hi Andrew Fawcett,
Actually,i saw MetadataServiceExamples.cls updatefieldset() .using this updatefieldset() i try to add pagelayout fields to fieldset using visualforce page ,apex code and display fieldset fields in an visualforce page dynamically.How to add pagelayout fields to fieldset dynamically?
please help me….
May 14, 2014 at 12:39 pm
I don’t understand your question, so sorry, you keep asking the same question over and over again and I just don’t understand it. You can add fields to Fieldsets using the examples. Conceptually you don’t add “page layout fields to a Fieldset” you add fields.
May 15, 2014 at 10:18 am
Hi Andrew Fawcett,
Actually ,i try to retrieve fields (with lableName, Api name,Datatype) in the database ,but through admin created fields only display in an pagblocktable .How to retrive metadata created fields with in the pageblocktable using visualforce page?
please help me
May 16, 2014 at 7:06 am
The fields may only display for admin due to field level security, check the profile of the non admin users. If this is the case you could use the permission set objects to create or update a permission set that could be assigned to users to ensure they can see the field. The permission set objects can be found in the standard object documentation and can be updated using standard apex DML not need for Metadada API
May 16, 2014 at 8:48 am
Hi Andrew Fawcett,
I can not understad.Using this url i trid to solve https://www.salesforce.com/us/developer/docs/pages/Content/pages_dynamic_vf_globals_objecttype.htm .How to display metadata created fields in an pageblock table(using wrapper class ) using visualforce page(field header values like lableName,API name, datatype).\
please help me………
May 22, 2014 at 7:15 am
Hi Andrew Fawcett,
Thank you………..
May 22, 2014 at 10:43 am
Hi Andrew Fawcett,
Actually ,In my my requirement Object like following type
string strtemp = ‘Mahesh__’+strFieldName + ‘__c’;
the above strtemp(object),using this how to perform edit and delete functionalities of related fields
please help me………….
June 21, 2014 at 11:48 am
Hi Andrew,
I am using the Apex metadata API to create a vf page with standardController as a custom object .
…code here …
The code that creates this is :
public class ctrlMetadataHandler{
public static MetadataService.MetadataPort createService(){
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
return service;
}
public PageReference createPage(){
apexPage = new MetadataService.ApexPage();
apexPage.apiVersion = 25;
apexPage.fullName = ‘TestPage’;
apexPage.label = ‘TestPage’;
String objectName = ‘PM_Rule__c’ ;
apexPage.content = EncodingUtil.base64Encode(Blob.valueOf(
”+”));
results = createService().createMetadata(new MetadataService.Metadata[] { apexPage });
}
}
But when i try to give a standardObject like Lead,Account etc . it works perfectly fine .
For ex : String objectName= ‘Lead’;
Any idea on why this is happening.
Thanks !!
June 21, 2014 at 3:19 pm
What error message are you getting? The body does not look like a valid page and also the objectname variable is not used, is this a fragment?
June 21, 2014 at 4:15 pm
How about raising an issue on the GitHub repository? This has better support for code. As as far as I can see your content for the page is not valid XML if you tried to create a page in the editor with just + character in it you would get an error. Let’s see if we can continue to trouble shoot this on the GitHub repo via the issues page.
June 21, 2014 at 3:52 pm
Sorry for incorrectly pasting the code . The apex page content is as :
String objectName = ‘PM_Rule__c’ ;
apexPage.content = EncodingUtil.base64Encode(Blob.valueOf(
”+”));
Yes this was a fragment of code.Below is the complete code.
There is a VF Page that calls the createPage() method of the class.
The results output is null and there is no error as such.
Comlete Code :
public class ctrlMetadataHandler{
public List results{get;set;}
public MetadataService.ApexPage apexPage;
public static MetadataService.MetadataPort createService(){
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
return service;
}
public PageReference createPage(){
apexPage = new MetadataService.ApexPage();
apexPage.apiVersion = 25;
apexPage.fullName = ‘TestPage’;
apexPage.label = ‘TestPage’;
String objectName = ‘PM_Rule__c’ ;
apexPage.content = EncodingUtil.base64Encode(Blob.valueOf(
”+”))
results = createService().createMetadata(new MetadataService.Metadata[] { apexPage });
}
}
Thanks a lot!!
June 21, 2014 at 3:53 pm
I guess again the code is not getting pasted in this blog , don’t the reason
June 26, 2014 at 10:12 am
Hi Andrew Fawcett,
Using metadata api How to give field visible permission on Add to page layouts(how to check this check box through coding) permission through coding?
Note:using metadata api i gave field visible permission related to profie through coding but Field Add to page layouts locaton check box is not checked.How to check add field to pagelayout checkbox through coding?
help me…
June 26, 2014 at 12:05 pm
You don’t need to use the Metadada API for this. Just create a permission set and assign to the user via DML.
June 27, 2014 at 6:10 am
Hi Andrew Fawcett,
Using below code i gave field visible permission related to admin profile but add fields to pagelayout location visible permission not checked.How to check that fields related add fields to pagelayout permission?
public static void updateFieldLevelSecurity() {
MetadataService.MetadataPort service = createService();
MetadataService.Profile admin = (MetadataService.Profile) service.readMetadata(‘Profile’, new String[] { ‘Admin’ }).getRecords()[0];
MetadataService.ProfileFieldLevelSecurity fieldSec = new MetadataService.ProfileFieldLevelSecurity();
fieldSec.field=’Test__c.TestField__c’;
fieldSec.editable=true;
admin.fieldPermissions = new MetadataService.ProfileFieldLevelSecurity[] {fieldSec} ;
MetadataService.UpdateMetadata ut = new MetadataService.UpdateMetadata();
ut.currentName=’Admin’;
ut.metadata= admin;
MetadataService.AsyncResult[] results = service.updateMetadata(new List {ut});
}
Please give me any sample code.
Thanks,
mahesh
June 27, 2014 at 6:24 am
Hi,
In my requirement my object will come dynamically through url and create fields and display fields in an visualforce page and save object related record also Dynamically.That’s why i am asking
Like
https://rajesh.ap1.visual.force.com/apex/CreateFields?FN=ramobj
please help me…..
June 27, 2014 at 6:41 am
Thanks for the further background. Sounds interesting. Is the related object hard coded?
June 27, 2014 at 6:45 am
I have looked at the ProfileFieldLevelSecurity class and there is two more properties in addition to ‘field’, these are ‘editable’ and ‘readable’ perhaps try setting these on your ‘fieldSec’ above?
June 27, 2014 at 6:59 am
Hi Andrew Fawcett,
I added those also but add fields to pagelayout location checkbox not cheked only profile permission checked
I try to
fieldSec.editable=true;
fieldSec.readable=true;
fieldSec.Hidden=false;
Note:Here in metadataService.Cls hidden field is not there but i added in that class.But not worked
help me……….
June 27, 2014 at 7:00 am
Can you clarify what “pagelayout location checkbox” is please?
June 27, 2014 at 7:08 am
Hi Andrew Fawcett,
custom object->Custom Fields & Relationships->NEw->Choose the field type-> Enter the details->.Establish field-level security(Here i gave profie permission using above code)->Add to page layouts
Here Add to page layouts location how to check checkbox of add fields to pagelayouts through coding
help me..
June 27, 2014 at 7:14 am
I understand now, thanks. To emulate the ‘Add to page layouts’ option you will need to read the page layout, modify it by adding your field and then update it. Here is an example of adding a button, you should be able to study the PageLayout structure to add your field in the same way. https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataServiceExamples.cls#L696
June 27, 2014 at 7:22 am
Hi Andrew Fawcett,
https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataServiceExamples.cls#L696
This URL related to weblink and buttons.I want when i create a field from visualforce page automatically how to check add fields to page layout checkbox Dynamically like above updateFieldLevelSecurity().
help me…..
June 27, 2014 at 7:29 am
Yes, but the basics are there for you to adapt, that code reads and updates, it’s the bit in the middle you need to adapt. Take a look at the PageLayout structure https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataService.cls#L3900. It has Layout sections, https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataService.cls#L3909. And within those you can layout columns, https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataService.cls#L2040 etc..
June 27, 2014 at 7:41 am
Hi Andrew Facett,
My field full name like this
fieldSec.field=’rajesh__’+ objectName+’__c.’ +Field2+’__c’ ;
But here There is no field related name .only like this
webLink.fullName = ‘Test__c.googleButton’;
June 27, 2014 at 7:50 am
As I said before, please ignore the button stuff you don’t need that, refer to the links i sent you on the general structure of the Layout object to determine how to add the fields, basically…
// Read the Layout
MetadataService.Layout layout =
(MetadataService.Layout) service.readMetadata(‘Layout’,
new String[] { ‘Test__c-Test Layout’ }).getRecords()[0];
// Here add your field by finding or adding the layout section and columns etc…
MetadataService.LayoutItem layoutItem = new MetadataService.LayoutItem();
layoutItem.field = rajesh__’+ objectName+’__c.’ +Field2+’__c’ ;
// This code assumes the first section, first column of the layout
layout.layoutSections[0]. layoutColumns[0].layoutItems.add(layoutItem);
// Update the Layout
handleSaveResults(
service.updateMetadata(
new MetadataService.Metadata[] { layout })[0]);
June 27, 2014 at 9:09 am
Hi Andrew Fawcett,
Here i added like
MetadataService.Layout layout =
(MetadataService.Layout) service.readMetadata(‘Layout’,
new String[] {‘objectname+’__c’- objectname Layout’ }).getRecords()[0];//here how to add myobject
Note: In object creation time already one pagelayout created like this :- objectname Layout
field created but i got following error
System.NullPointerException: Attempt to de-reference a null object
Error is in expression ‘{!createField}’ in component in page rajesh:createfields
Class.rajesh.MetadataController11.updateFieldpageLayout: line 902, column 1
Class.rajesh.MetadataController11.createField: line 262, column 1 //layout method calling location
help me…….
June 27, 2014 at 11:45 am
This error means there is a bug in your code. You have attempted to use a variable that has not got a value. This should be clear from the code on line 902. I really wish you would use GitHub issues to let me help you, it is much easier and clearer to exchange code.