Tallan's Technology Blog

Tallan's Top Technologists Share Their Thoughts on Today's Technology Challenges

Programmatically Deploying Dell Boomi Processes using the AtomSphere RESTish API and C#

Paul Gutierrez

While the Dell Boomi user interface is highly robust and user friendly there are times when using the user interface can prove to be quite tedious. One example that we have discovered to be an example of this are process deployments. In order to deploy a set of Boomi processes one must search for each individual process and deploy. This may not seem overly tedious if AtomSphere only has a few processes. But in some cases AtomSphere could have numerous applications each consisting of many processes. It is easy to see given the scenario how frequent deployments could prove to be very time consuming.

Luckily, there is an alternative to using the AtomSphere user interface. Dell Boomi offers a set of APIs (both REST and SOAP) that can be used for various sets of tasks and that includes deploying Boomi processes. This blog post will show you how to manipulate the AtomSphere RESTish APIs with C# to programmatically deploy all of your desired processes.

In this blog post we will be using the RESTSharp library for making the RESTish calls out to the Atomsphere API but the contents of this blog can be applied to any other library that utilizes REST.

This blog post will be divided into 6 sections each explaining different parts of the development process. The sections are as follows:

  1. Determine what actions need to occur in order to deploy a process.
  2. Determine what API end points correlate to the actions specified in part 1.
  3. Determine all the necessary parameters needed for the HTTP requests.
  4. Create the request and response models
  5. Write the C# functions that utilize all of the above steps to make the API calls.
  6. Combine all the C# functions from step 5

Step 1. Determine what actions need to occur in order to deploy a process.

Before getting into the code the first step should be to reflect on what actions need to be done in order to deploy a Boomi process. Going through the manual steps for deploying an action, we will find that there are at least three steps that need to occur in order to successfully deploy a process:

  1. Figure out if a process is currently attached to the desired environment.
  2. If the process is not attached to the desired environment, then it needs to be attached.
  3. Deploy the process.

While step three above is the main goal of this blog post, without the first two steps the request to deploy the process will fail if the process is not attached to an environment. The first two steps act as a safety net in case a process becomes unattached from the desired environment.

 

Step 2. Determine what API end points correlate to the actions specified in part 1.

Now that the necessary actions have been determined the next step is to determine the appropriate API endpoints. A list of all the API objects can be found in Boomi’s documentation: http://help.boomi.com/atomsphere/GUID-EB9FBC59-6160-4322-A3A7-4A2B8F00E100.html.

The following are the endpoints we will need:

  1. A Process Environment Attachment Object Query Operation (HTTP POST)
    1. https://api.boomi.com/api/rest/v1/{accountId}/ProcessEnvironmentAttachment/query
  2. A Process Environment Attachment Object Create Operation (HTTP POST)
    1. https://api.boomi.com/api/rest/v1/{accountId}/ProcessEnvironmentAttachment/
  3. A Deployment Object Create Operation (HTTP POST)
    1. https://api.boomi.com/api/rest/v1/{accountId}/Deployment/{id}

The first endpoint above will be used to retrieve all processes attached to a given environment. The code should then check the response of that call to determine if the desired process is attached to the environment. If the process is not attached then we will use the second endpoint above to attach the process to the environment. Finally, the last endpoint will then deploy the process to the environment.

 

Step 3. Determine all the necessary parameters needed for the HTTP requests.

Once all the requests that are needed to deploy a process are known, the next step is to determine all parameters needed for those requests.

To start off, every RESTish API call will need the account id. You can find the account id under setup -> Account Information as shown below:

Now that we have the account id the next parameter needed is the environment id for the Process Environment Attachment Object Query and Create operations. The environment id can be found under Manage -> Atom Management -> {Desired Environment} as shown below:

The last parameter needed is the process id. This is needed for the Process Environment Object Query and Deployment Object Create operations. The process id  can be found by going to the desired process and looking at the revision history. In the revision history the process id is referred to as the “Component ID”. You can see the screen shot below:

processidlocation

 

Step 4. Create the request and response models

With all the preliminary work now completed the next step is to implement the C# code that will make the requests. The first set of classes that should be created are the models that will represent the request and response objects for all of the API calls. Boomi documentation specifically lists out all of the request and responses that can be used to create these models. Below you will see the JSON requests and responses retrieved from the Boomi documentation followed by the correlating C# POCO classes:

4.1 Process Environment Attachment Object Query Operation

JSON Request
{"QueryFilter" :
  {
    "expression" :
      {
        "argument" : ["456789ab-cdef-0123-4567-89abcdef0123"],
        "operator" : "EQUALS",
        "property" : "environmentId"
      }
   }
}
POCO Request
namespace BoomiApiRESTDeploy.BoomiObjects.Request
{
    public class QueryConfig
    {
        public QueryFilter QueryFilter { get; set; }
    }

    public class QueryFilter
    {
        public Expression Expression { get; set; }
    }

    public class Expression
    {
        public string[] Argument { get; set; }
        public string Operator { get; set; }
        public string Property { get; set; }
    }
}
JSON Response
{
  "numberOfResults" : 2,
  "@type" : "QueryResult",
  "result" : [
    {
      "@type" : "ProcessEnvironmentAttachment",
      "id" : "Ab0Cd1Ef1Gh3Ij4Kl5Mn6Op7Qr8St9Uv0Wx9Yz8Zy7Xw6Vu5Ts4Rq3Po2Nm1Lk0Ji1Hg",
      "processId" : "56789abc-def0-1234-5678-9abcdef01234",
      "environmentId" : "456789ab-cdef-0123-4567-89abcdef0123"
    },
    {
      "@type" : "ProcessEnvironmentAttachment",
      "id" : "b0Cd1Ef1Gh3Ij4Kl5Mn6Op7Qr8St9Uv0Wx9Yz8Zy7Xw6Vu5Ts4Rq3Po2Nm1Lk0Ji1HgA",
      "processId" : "6789abcd-ef01-2345-6789-abcdef012345",
      "environmentId" : "456789ab-cdef-0123-4567-89abcdef0123"
    }
  ]
}
POCO Response
using System.Collections.Generic;
using RestSharp.Deserializers;

namespace BoomiApiRESTDeploy.BoomiObjects.Response
{
    public class ProcessEnvironmentAttachmentQueryResult
    {
        public int NumberOfResults { get; set; }
        [DeserializeAs(Name = "@type")]
        public string Type{get; set; }
        public List<ProcessEnvironmentAttachment> Result { get; set; }
    }

    public class ProcessEnvironmentAttachment
    {
        [DeserializeAs(Name = "@type")]
        public string Type { get; set; }
        public string Id { get; set; }
        public string EnvironmentId { get; set; }
        public string ProcessId { get; set; }
    }
}

4.2 Process Environment Attachment Object Create Operation

JSON Request
{
  "processId" : "56789abc-def0-1234-5678-9abcdef01234",
  "environmentId" : "456789ab-cdef-0123-4567-89abcdef0123"
}
POCO Request
namespace BoomiApiRESTDeploy.BoomiObjects.Request
{
    public class ProcessEnvironmentAttachmentRequest
    {
        public string ProcessId { get; set; }
        public string EnvironmentId { get; set; }
    }
}
JSON Response
{
  "@type" : "ProcessEnvironmentAttachment",
  "id" : "Ab0Cd1Ef1Gh3Ij4Kl5Mn6Op7Qr8St9Uv0Wx9Yz8Zy7Xw6Vu5Ts4Rq3Po2Nm1Lk0Ji1Hg",
  "processId" : "56789abc-def0-1234-5678-9abcdef01234",
  "environmentId" : "456789ab-cdef-0123-4567-89abcdef0123"
}
POCO Response
using RestSharp.Deserializers;

namespace BoomiApiRESTDeploy.BoomiObjects.Response
{
    public class ProcessEnvironmentAttachment
    {
        [DeserializeAs(Name = "@type")]
        public string Type { get; set; }
        public string Id { get; set; }
        public string EnvironmentId { get; set; }
        public string ProcessId { get; set; }
    }
}

4.3 Deployment Object Create Operation

JSON Request
{
  "environmentId" : "456789ab-cdef-0123-4567-89abcdef0123",
  "processId" : "789abcde-f012-3456-789a-bcdef0123456",
  "notes" : "via RESTish request: Re-deployment of version 54",
}
POCO Request
namespace BoomiApiRESTDeploy.BoomiObjects.Request
{
    public class DeploymentRequest
    {
        public string EnvironmentId { get; set; }
        public string ProcessId { get; set; }
        public string Notes { get; set; }
    }
}
JSON Response
{
  "@type" : "Deployment",
  "id" : "89abcdef-0123-4567-89ab-cdef01234567",
  "environmentId" : "456789ab-cdef-0123-4567-89abcdef0123",
  "processId" : "789abcde-f012-3456-789a-bcdef0123456",
  "current" : true,
  "notes" : "via RESTish request: Re-deployment of version 54",
  "version" : 55,
  "deployedOn" : "2013-09-23T16:33:53.413Z",
  "deployedBy" : "user123@company.biz"
}
POCO Response
using RestSharp.Deserializers;

namespace BoomiApiRESTDeploy.BoomiObjects.Response
{
    public class Deployment
    {
        [DeserializeAs(Name = "@type")]
        public string Type { get; set; }
        public string Id { get; set; }
        public string EnvironmentId { get; set; }
        public string ProcessId { get; set; }
        public string Current { get; set; }
        public string Notes { get; set; }
        public string Version { get; set; }
        public string DeployedOn { get; set; }
        public string DeployedBy { get; set; }
    }
}

Step 5. Write the C# functions that utilize all of the above steps to make the API calls.

With the models created the next step is to write the code needed to to make the actual requests. Below is code that makes each individual request using RestSharp.

Note: As mentioned earlier in the post, RestSharp is merely one library of many that can be used to handle RESTish calls and responses. While some of the attributes and classes used below are specific to RESTSharp the premise behind the code should be easily transferable to any other REST based library.

Process Environment Attachment Object Query Operation
private static ProcessEnvironmentAttachmentQueryResult QueryProcessEnvironmentAttachment(RestClient client, string accountId, string environmentId)
{
    var queryConfig = new QueryConfig()
    {
        QueryFilter = new QueryFilter()
        {
            Expression = new Expression()
            {
                Argument = new[] { environmentId },
                Operator = "EQUALS",
                Property = "environmentId"
            }
        }
    };

    var request = new RestRequest("api/rest/v1/{accountId}/ProcessEnvironmentAttachment/query", Method.POST);
    request.AddUrlSegment("accountId", accountId);
    request.AddHeader("Content-Type", "application/json");
    request.AddHeader("Accept", "application/json");
    request.AddJsonBody(queryConfig);
    request.RequestFormat = DataFormat.Json;

    var queryResponse = client.Execute<ProcessEnvironmentAttachmentQueryResult>(request);
    if(queryResponse.StatusCode != HttpStatusCode.OK)
        throw new Exception("Unsuccessful request");

    return queryResponse.Data;
}
Process Environment Attachment Object Create Operation
private static ProcessEnvironmentAttachment CreateProcessEnvironmentAttachment(RestClient client, string accountId,string environmentId, string processId)
{
    var processEnvAttachRequest = new ProcessEnvironmentAttachmentRequest()
    {
        EnvironmentId = environmentId,
        ProcessId = processId
     };

     var request = new RestRequest("api/rest/v1/{accountId}/ProcessEnvironmentAttachment", Method.POST);
     request.AddUrlSegment("accountId", accountId);
     request.AddHeader("Content-Type", "application/json");
     request.AddHeader("Accept", "application/json");
     request.AddJsonBody(processEnvAttachRequest);
     request.RequestFormat = DataFormat.Json;

     var processEnvAttachResponse = client.Execute<ProcessEnvironmentAttachment>(request);
     if (processEnvAttachResponse.StatusCode != HttpStatusCode.OK)
        throw new Exception("Unsuccessful request");

     return processEnvAttachResponse.Data;
}
Deployment Object Create Operation
private static Deployment CreateDeployment(RestClient client, string accountId, string environmentId, string processId, string notes)
{
    var deploymentRequest = new DeploymentRequest()
    {
        EnvironmentId = environmentId,
        ProcessId = processId,
        Notes = notes
    };

    var request = new RestRequest("api/rest/v1/{accountId}/Deployment", Method.POST);
    request.AddUrlSegment("accountId", accountId);
    request.AddHeader("Content-Type", "application/json");
    request.AddHeader("Accept", "application/json");
    request.AddJsonBody(deploymentRequest);
    request.RequestFormat = DataFormat.Json;

    var processEnvAttachResponse = client.Execute<Deployment>(request);
    if (processEnvAttachResponse.StatusCode != HttpStatusCode.OK)
        throw new Exception("Unsuccessful request");

    return processEnvAttachResponse.Data;
}

A very important item to make note of is the fact that we pass through “application/json” as a value to the “Content-Type” and “Accept” headers. These headers make it known that both the HTTP request and response should be in JSON. If the “Content-Type” header is left out than the request will expect the format to be in XML and if the “Accept” header is left out than the response returned will also be in XML. For the purpose of this blog post we opted to go with JSON for the request and response but the functions below do not change much if using XML instead.

Step 6. Combine all the C# functions from step 5

Now that the code for each individual API request has been completed the last part is to write the code that combines all of the requests so that they match the actions metioned in part 1. Below shows the code:

static void Main(string[] args)
{
    const string accountId = "{Account ID}";
    const string environmentId = "Environment ID";
    const string processId = "{Process ID}";
    const string notes = "{Deployment Note}";
    SimpleJson.CurrentJsonSerializerStrategy = new BoomiApiSerializerStrategy();

    RestClient client = new RestClient("https://api.boomi.com/")
    {
        Authenticator = new HttpBasicAuthenticator("{Dell Boomi Account User Name}", "{Dell Boomi Account Password}")
    };

    ProcessEnvironmentAttachmentQueryResult queryResult = QueryProcessEnvironmentAttachment(client, accountId, environmentId);

    if (queryResult.NumberOfResults  x.ProcessId != processId))
    {
        CreateProcessEnvironmentAttachment(client, accountId, environmentId, processId);
    }

    CreateDeployment(client, accountId, environmentId, processId, notes);
}

In the code above we first query the environment attachments and use the results to check to see if we should attach the process to attachment. Once the check is done we then proceed with the process deployment. One thing to make a note of is that we are using a custom JSON serializer in order to serialize our POCOs into a valid JSON format. The next optional section will explain how to build that class.

Step 7. Build a custom JSON Serializer (OPTIONAL)

In the application’s current state if we attempt to execute the program the API should return a HTTP 400 (Bad Request) response. The reason for this is because the default RESTSharp JSON serializer does not convert the model’s pascal case property names into camel case. One way to overcome this is by changing all of the property names so that they are in camel case. In most cases this solutioni isn’t ideal as it will create tight coupling between the property name the json request. A better solution to resolve this issue would be to create a custom serializer.

One thing to note is that while most of the JSON properties are in camel case not all of them are. One specific instance of this is the “QueryFilter” JSON property name which is actually in pascal case. So in the custom serializer there needs to be a condition to leave “QueryFilter” property name in pascal case. The code for the custom serializer is below:

using RestSharp;

namespace BoomiApiRESTDeploy
{
    class BoomiApiSerializerStrategy : PocoJsonSerializerStrategy
    {
        protected override string MapClrMemberNameToJsonFieldName(string clrPropertyName)
        {
            //Only convert Pascal Case to Camel Case if the property name isn't "QueryFilter" because that is the only json property name that isn't camel case.
            var jsonFieldName = clrPropertyName;

            if (!string.IsNullOrEmpty(clrPropertyName) && clrPropertyName != "QueryFilter")
            {
                jsonFieldName = char.ToLower(clrPropertyName[0]) + clrPropertyName.Substring(1);
            }

            return jsonFieldName;
        }
    }
}

Summary

The main objective of this blog post was to show how to programmatically deploy your Boomi processes but another objective was to show that you do not have to be slowed down by Boomi’s user interface and that the AtomSphere API offers some very powerful capabilities that you can use to help facilitate and/or automate some very tedious and time consuming tasks. You should now have a comprehensive guide on how to programmatically deploy your desired processes. While the application built in this blog post is merely just a console app if need be, you could wrap this code in a windows service and perhaps do nightly builds to your DEV environment or even wrap the code with a custom user interface.

Dell Boomi AtomSphere

The Dell Boomi AtomSphere integration platform is a shared-everything, multi-tenant platform that supports cloud-to-cloud, SaaS-to-SaaS, cloud-to-on-premises, on-premises-to-on-premises and B2B integration. Boomi AtomSphere supports real-time integration and elastically scales to meet high-volume needs in mobile, batch (ETL) and EDI environments. Easily accessed via a browser, it delivers an impressive range of integration, master data management (MDM) and platform extension capabilities.

Tallan Integration Solutions for Dell Boomi
Tallan is a certified Dell Boomi Partner specializing in iPaaS platform integrations. We specialize in Integrations using EDI and Dell Boomi as the iPaaS platform of choice. Leverage Tallan’s vast integration experience for your AtomSphere platform needs.  Our certified architects and developers provide the expertise, best practices, and guidance to deliver a successful integration solution.

We hope this guide will help you in your use of AtomSphere. If you have any questions or comments, or need assistance with any Integrations or development questions, please contact us at integrations@tallan.com.

No comments

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

\\\