6

I'm trying to create a REST API class that will allow the following:

  • POST Object ID
  • Update(ObjId); ('Touching' the record, fires triggers on Salesforce)
  • Find SObjects on a custom object that have been created, with Relationship__c = ObjId
  • Return entire SObjects via JSON

I found some general examples here, and also read up on the describeSObjectResult class, but so far I have not been able to put all of these pieces together.

Thank you for any advice or sample code!

  • What's the context for calling this RestResource? If you're inside salesforce.com, you should probably be using another mechanism, such as a Visualforce page's RemoteAction function. I'm not saying that this won't work, because it will, but I wonder if there might be a better option for your use case. – sfdcfox Nov 13 '13 at 17:27
  • Im calling this from an external web service. Creating this ad-hoc REST API via an Apex class allows me to run methods not generally available via Salesforce's existing REST API – CDD Nov 14 '13 at 17:47
  • Then that answer definitely does you service. It's a good answer, too. – sfdcfox Nov 14 '13 at 17:57
4

Assuming you want the original object returning together with its related children the code below should provide a starting point. Note that to call the code you will need to include authentication information. The code assumes you will pass the object id in the URL e.g.:

/services/apexrest/xyz/a00i000000AnlOC.json

The code:

@RestResource(urlMapping='/xyz/*')
global with sharing class ParentRest {
    @HttpPost
    global static SObject doPost() {
        Id parentId = extractId(RestContext.request.requestURI);
        // Fire triggers by updating
        update parentId.getSObjectType().newSObject(parentId);
        // Query parent and children in one go so all serialized
        return query(parentId);
    }
    private static SObject query(Id parentId) {
        // Query all parent fields
        DescribeSObjectResult pd = parentId.getSObjectType().getDescribe();
        String soql = 'select ' + csvs(pd.fields.getMap().keySet());
        for (ChildRelationship cr : pd.getChildRelationships()) {
            if (String.valueOf(cr.getChildSObject()).endsWithIgnoreCase('__c')) {
                // Query all child fields of each child
                DescribeSObjectResult cd = cr.getChildSObject().getDescribe();
                soql += ', (select ' + csvs(cd.fields.getMap().keySet())
                        + ' from ' + cr.getRelationshipName() + ')';
            }
        }
        soql += ' from ' + parentId.getSObjectType();
        soql += ' where Id = :parentId';
        System.debug('>>> soql=' + soql);
        return Database.query(soql);
    }
    private static String csvs(Set<String> strings) {
        return String.join(new List<String>(strings), ',');
    }
    private static Id extractId(String uri) {
        String prefix = '/xyz/';
        Integer s = uri.indexOf(prefix);
        if (s != -1) {
            s += prefix.length();
            Integer f = uri.indexOf('.', s);
            if (f == -1) {
                f = uri.length();
            }
            return (Id) uri.substring(s, f);
        }
        return null;
    }
}

An example of the sort of JSON returned:

{
  "attributes":{
    "type":"Parent__c",
    "url":"/services/data/v29.0/sobjects/Parent__c/a00i000000AnlOCAAZ"
  },
  "Name":"Parent 1",
  "LastViewedDate":"2013-11-12T21:43:10.000+0000",
  "LastReferencedDate":"2013-11-12T21:43:10.000+0000",
  "LastModifiedById":"005i0000001PYqgAAG",
  "SystemModstamp":"2013-11-12T21:43:10.000+0000",
  "CreatedById":"005i0000001PYqgAAG",
  "OwnerId":"005i0000001PYqgAAG",
  "CreatedDate":"2013-11-12T21:25:43.000+0000",
  "LastModifiedDate":"2013-11-12T21:43:10.000+0000",
  "IsDeleted":false,
  "Id":"a00i000000AnlOCAAZ",
  "Children__r":{
    "totalSize":3,
    "done":true,
    "records":[
      {
        "attributes":{
          "type":"Child__c",
          "url":"/services/data/v29.0/sobjects/Child__c/a01i0000007AfA9AAK"
        },
        "Name":"Child 2",
        "LastModifiedById":"005i0000001PYqgAAG",
        "SystemModstamp":"2013-11-12T21:26:13.000+0000",
        "CreatedById":"005i0000001PYqgAAG",
        "CreatedDate":"2013-11-12T21:26:13.000+0000",
        "LastModifiedDate":"2013-11-12T21:26:13.000+0000",
        "IsDeleted":false,
        "Id":"a01i0000007AfA9AAK",
        "Parent__c":"a00i000000AnlOCAAZ"
      },
      {
        "attributes":{
          "type":"Child__c",
          "url":"/services/data/v29.0/sobjects/Child__c/a01i0000007AfAmAAK"
        },
        "Name":"Child 3",
        "LastModifiedById":"005i0000001PYqgAAG",
        "SystemModstamp":"2013-11-12T21:26:22.000+0000",
        "CreatedById":"005i0000001PYqgAAG",
        "CreatedDate":"2013-11-12T21:26:22.000+0000",
        "LastModifiedDate":"2013-11-12T21:26:22.000+0000",
        "IsDeleted":false,
        "Id":"a01i0000007AfAmAAK",
        "Parent__c":"a00i000000AnlOCAAZ"
      },
      {
        "attributes":{
          "type":"Child__c",
          "url":"/services/data/v29.0/sobjects/Child__c/a01i0000007AfAhAAK"
        },
        "Name":"Child 1",
        "LastModifiedById":"005i0000001PYqgAAG",
        "SystemModstamp":"2013-11-12T21:25:57.000+0000",
        "CreatedById":"005i0000001PYqgAAG",
        "CreatedDate":"2013-11-12T21:25:57.000+0000",
        "LastModifiedDate":"2013-11-12T21:25:57.000+0000",
        "IsDeleted":false,
        "Id":"a01i0000007AfAhAAK",
        "Parent__c":"a00i000000AnlOCAAZ"
      }
    ]
  }
}

You can filter out fields as you build the query to simplify the response. If you want more control over the response structure, you can create your own bean classes and populate them from the query result.

| improve this answer | |
  • Looks very promising, thank you! I won't be able to test right now, but I will let you know how it works out. – CDD Nov 13 '13 at 0:33
  • Fair enough. If "This answer is useful" please click the up arrow button next to the answer - explanation here salesforce.stackexchange.com/about. – Keith C Nov 13 '13 at 8:39
  • Worked like a charm when I switched over to the proper class names. Thank you very much sir, saved me a world of headaches! – CDD Nov 14 '13 at 17:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.