Damian Sima on Tuesday, June 10, 2014

The Entities Graph Inconvenience

0

It seems like everyone is talking about APIs lately.

We can find tons of them out there. More and more cloud based services and on-premises services are exposing themselves to the outside world through APIs. Many of these systems are fairly complex, so they need a complex object model to reach their full potential. By complex I mean deep object graphs and many relations between the objects. While this is easy to achieve in any language, it is not as easy to serialize them or to deal with them afterwards.

For instance we all have to deal, at some point or another, with big XML documents describing an objects graph.

Here is were the API world starts getting a little bit more complicated. How do these services expose such complexity to the open world and at the same time offer an easy enough way of operate with the model?

There are a few issues to deal with, let’s take a look at them.

Querying the object model

The problem here is not with representation – you could serialize the model to XML or JSON – but you need to consider the impact of the users of your API querying a large object graph. As the graph gets bigger there is more data to transfer over the wire, but this shouldn’t really be a problem now a days.

On the other hand, loading an object graph in your server and then serializing it could be quite expensive. Finally, there is a usability impact on the client’s side as it’s troublesome to deal with really large models on the client’s side.

Operations over the graph

  • How do you deal with CRUD operations?
  • How do you create an object that is related to a top level one?
  • How do you create two object that are related to each other?
  • What if your clients only knows a top level object but really want to edit a field in an object of the 4th level of the graph?
  • How would you go about creating an object and a list of related objects all at the same time?

All these questions have answers, and you should consider all of them while designing your API. But as your service grows, you should also keep in mind to come up with a way for achieving any of the previous operations with as few API calls as possible.

The SFDC API as example

The Salesforce API offers a comprehensive set of API calls to operate with a complex object model (again, by complex I mean big). Now how does Salesforce deal with some of the problems we saw before?

Let’s analyze for example: “How do you deal with querying related objects?“.  Salesforce offers a few options to do so:

Nested SOQL

This is an elegant way, after ANSI SQL, that with no explicit reference to its parent in a WHERE clause, allows you to bring over not only an Opportunity, but also all the Opportunity lines (or at least a few fields of those).

SELECT Id, Name, Account.Name, (SELECT Quantity, UnitPrice, TotalPrice FROM OpportunityLineItems) FROM Opportunity

Parent Relations

Salesforce offers the concept of relationships – particularly parent relationships. The concept is really simple; Salesforce offers you an alias name to the parent entity. For instance the parent entity of Contact is an Account.

Through the Account alias, you can still query a Contact while at the same time get all the required fields of its parent (the Account) in a simple query.

SELECT Email, LastName, Id, LastModifiedDate, Account.Id, Account.Name, Account.AccountNumber FROM Contact

Note 1: Bear in mind that not all alias names are that simple, for instance in the Account entity 

Note 2: This blog post is not intended to explain all this in detail but rather to use this concepts as good examples on how to deal with this topic. The parent of it is the User entity but the alias of the parent relationship is Owner.

If you want to know more about this you should definitely check this blog post.

The design question for all of you

How will you design your API to achieve in just one API call?

  • Create several entities
  • Allow these entities to have dependencies to entities that have not yet been created

For instance an operation that allow you to create several Contacts at once. BUT WAIT, for the Contacts need an Account to be related to otherwise the operation should fail, and remember that the Account may not exists yet.

Done thinking?

Ok this could be one approach, may be not the best but certainly one:
Crate an operation that allows you to create the parent entity and all its child. So if the payload were a JSON one  could look like:

Account
{
Id: “”,
AccountNumber:”",
Name: “”
Contacts:
[
{Id:"", Email:"", LastName:"", LastModifiedDate:""},
{Id:"", Email:"", LastName:"", LastModifiedDate:""}
]
}

The Anypoint Templates Approach

We faced similar issues when creating our Anypoint Templates. The approach we took to tackle this was to leverage the Salesforce Anypoint Connector and create a sequence of steps to do it.

For instance, let’s take a look to the Anypoint Template SFDC to SFDC Broadcast

In this Anypoint Template, we solve the issue by validating the existence of the Account before the creation of the Contact.

  • If the Account does not exists we create it
  • If it does then we don’t
  • In any scenario we get an Account Id back which we use later on to establish the relationship with the Contact when we create it.

We tackled many more of interesting use cases, take a look at them here: Anypoint Templates for Salesforce Integration.

Related posts:

  1. Explore the graph with Mule and Neo4j

Leave a Comment