[SalesForce] Must specify a {http://www.w3.org/2001/XMLSchema-instance}type during creating Approval process using metadata API

I am trying to create Approval process using Metadata API but unable to figure out what i am missing.

One doubt is XML don't have any symbol why which me or Salesforce could identify on which object i am creating the approval process.

I have tried by using wsdl and REST API but no success.

Receiving error:

soapenv:ClientMust
specify a {http://www.w3.org/2001/XMLSchema-instance}type attribute
value for the {http://soap.sforce.com/2006/04/metadata}metadata
element

Using WSDL:

        MetadataService_Chris.Metadata_Chris service = new MetadataService_Chris.Metadata_Chris();
        service.SessionHeader = new MetadataService_Chris.SessionHeader_element();
        service.SessionHeader.sessionId = UserInfo.getSessionId();

        MetadataService_Chris.ApprovalProcess process = new MetadataService_Chris.ApprovalProcess();
        process.fullName = 'TestApproval';
        process.active = true;
        process.allowRecall = true;

        MetadataService_Chris.ApprovalSubmitter submitter = new MetadataService_Chris.ApprovalSubmitter();
        submitter.type_x = 'user';
        submitter.submitter = UserInfo.getUserId();

        List<MetadataService_Chris.ApprovalSubmitter> submitters = new List<MetadataService_Chris.ApprovalSubmitter>();
        submitters.add(submitter);

        process.allowedSubmitters = submitters;
        process.label = 'Test Approval';
        process.showApprovalHistory = true;

        //MetadataService_Chris.Metadata mdata = new MetadataService_Chris.Metadata();
        //mdata.fullName = 'Test Metadata';

        MetadataService_Chris.AsyncResult[] results = service.create(new List<MetadataService_Chris.Metadata> { process });
        System.debug('----------------------------------  '+results);

Using REST:

        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();
        req.setMethod('POST');
        req.setHeader('Content-Type', 'text/xml');
        req.setHeader('SOAPAction', 'create');

        String xml = /*'<?xml version="1.0" encoding="UTF-8"?>'+
        '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'+
           '<env:Header>'+
              '<SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata">'+
                 '<sessionId>'+userinfo.getSessionId()+'</sessionId>'+
              '</SessionHeader>'+
           '</env:Header>'+
           '<env:Body>'+
              '<create xmlns="http://soap.sforce.com/2006/04/metadata">'+
                 '<metadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'+ // xsi:type="Account"
                        '<active>false</active>'+
                        '<allowRecall>true</allowRecall>'+
                        '<allowedSubmitters>'+
                           '<submitter>005i00000033nPoAAI</submitter>'+
                           '<type />'+
                        '</allowedSubmitters>'+
                        '<label>Test Approval</label>'+
                        '<recordEditability />'+
                        '<showApprovalHistory>true</showApprovalHistory>'+
                 '</metadata>'+
              '</create>'+
           '</env:Body>'+
        '</env:Envelope>';

        req.setBody(xml);
        req.setCompressed(false);
        req.setEndpoint('https://na15.salesforce.com/services/Soap/m/29.0');
        HTTPResponse resp = h.send(req);
        System.debug(resp.getBody());

I have tried with several combinations but no success. In back-end XML formed as:

<?xml version="1.0" encoding="UTF-8"?>
    <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <env:Header>
          <SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata">
             <sessionId>00Di0000000k2kv!AR4AQBKoHVPE4sLzQbOuu.CAU0o1qsMldVzPRDGFStoboKik1lt_WUNe.5YiHR2MQOlrKExKf05TnYB_7SO7kPdwQGfjwNis</sessionId>
          </SessionHeader>
       </env:Header>
       <env:Body>
          <create xmlns="http://soap.sforce.com/2006/04/metadata">
             <metadata>
                <active>true</active>
                <allowRecall>true</allowRecall>
                <allowedSubmitters>
                   <submitter>005i00000033nPoAAI</submitter>
                   <type />
                </allowedSubmitters>
                <label>Test Approval</label>
                <recordEditability />
                <showApprovalHistory>true</showApprovalHistory>
             </metadata>
          </create>
       </env:Body>
    </env:Envelope>

The problem is "xsi:type="ApprovalProcess" which throws exception.

Best Answer

I've just uploaded a new MetadataService.cls with support for this, you can also see in the MetadataSeviceExamples.cls class an example as follows below on how to do this. I'm not 100% what your issue was with your copy of the generated class, but at least you could compare with the one above if your interested.

    MetadataService.MetadataPort service = createService();
    MetadataService.ApprovalProcess approvalProcess = new MetadataService.ApprovalProcess();
    approvalProcess.fullName = 'Test__c.TestApproval';
    approvalProcess.label = 'Test Approval';
    approvalProcess.active = false;
    approvalProcess.allowRecall = false;
    approvalProcess.showApprovalHistory = true;
    approvalProcess.recordEditability = 'AdminOnly';
    approvalProcess.finalApprovalRecordLock = false;
    approvalProcess.finalRejectionRecordLock = false;
    approvalProcess.showApprovalHistory = false;
    MetadataService.ApprovalSubmitter submitter = new MetadataService.ApprovalSubmitter();
    submitter.type_x = 'user';
    submitter.submitter = UserInfo.getUserName();
    approvalProcess.allowedSubmitters = new List<MetadataService.ApprovalSubmitter> { submitter };
    MetadataService.AsyncResult[] results = service.create(new List<MetadataService.Metadata> { approvalProcess });

Finally, keep in mind (at least for now) there is only an Async option for the create operation, which means you need to check back using the checkAsync method the final status. For more information about doing this you can read this blog.

Once Spring'14 is released (later in April) i will update the library to support the new immediate create operation which does not require you to poll for the result.

Related Topic