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!

3
  • 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
    Commented Nov 13, 2013 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
    Commented Nov 14, 2013 at 17:47
  • Then that answer definitely does you service. It's a good answer, too.
    – sfdcfox
    Commented Nov 14, 2013 at 17:57

1 Answer 1

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.

3
  • 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
    Commented Nov 13, 2013 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
    Commented Nov 13, 2013 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
    Commented Nov 14, 2013 at 17:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .