2020

Archive for 2020

Recap of 2020

The end of the year is the time to pause, look back, and think about how the year went by. I am very grateful and fortunate to had an opportunity to enjoy a reasonably good time in 2020.

On the personal front

  • We visited our families in India in January. I enjoyed meeting my parents, brother, in-laws, and friends.
  • I did not travel for work and got more time to spend with my wife.
  • I started reading books. As a kid, I was an avid reader. The librarian in my town knew me by name. He would hold the books for me. With job and other things taking precedence over the years, I forgot about the books.
  • I stopped procrastinating about writing this blog. I had some solid excuses like not having enough content to write, poor writing skills, not enough time with work-related travel, etc. I discovered that none of this matters if I can just sit down and write something.
  • I re-started playing Clash of Clans. I enjoyed playing it a few years ago, but got addicted to it and burned out. During the pandemic, I wanted something other than movies to wind down. I downloaded my favorite game again and took it for a spin. I was surprised to find my old clan-mates still playing. Then I realized that I was thinking about this game all wrong. There is no end goal to it. The journey of playing is what makes it enjoyable.
  • I was able to stick to my intermittent fasting routine throughout the year, even during my visit to India.
  • And the best for the last. I was positively surprised by something magic. :)

On the professional front

  • I got promoted to a senior position in the team, started mentoring the team members. By the end of the year, I transitioned to a more exciting role that I am looking forward to in the next year.
  • I continued my learning by becoming a Salesforce Ranger, as well as became a Certified Administrator. I also completed the HL7 FHIR training and became proficient in FHIR.

What are my plans for the next year? I like to keep things simple, so I will continue to do the things I did this year already, but in a more structured way.

Upload Attachments to Salesforce Using MuleSoft

This question comes up occasionally in my conversations with customers. Often there is a need to programmatically upload an attachment (a pdf or an image) file to Salesforce using MuleSoft. If the integration developer is not very familiar with the Salesforce Platform, it usually confusing due to the way Salesforce manages the attachments.

As shown in the following ER diagram, there are multiple entities involved in storing and managing the attachments in Salesforce

ContentDocumentstringIdstringTitlestringPathOnClientdateCreatedDateContentDocumentLinkstringIdreferenceLinkedEntityIdreferenceContentDocumentIdpicklistShareTypepicklistVisibilityAccountstringIdstringAccountNumberContactstringIdstringFirstNamestringLastNamesObjectstringIdstringSomePropertyhaslinkedEntitylinkedEntitylinkedEntity
Things to note:

  • Salesforce attachments are stored in ContentDocument (and ContentVersion) objects.
    • The ContentDocument object is used to retrieve, query, update and delete the latest version of a document.
    • The ContentVersion object is used to create, query, retrieve, search, edit, and update a specific version of a Salesforce CRM Content document.
  • The attachment is stored in ContentDocument (Or ContentVersion) and linked to any sObject (Contact, Account etc) via ContentDocumentLink Object
  • Thus, to successfully upload an attachment to Salesforce following needs to happen
    • Upsert an attachment (file) to ContentDocument/ContentVersion object
    • Query the ContentDocument/ContentVersion to get the ContentDocumentId
    • Use the ContentDocumentId to link to your sObject (Account, Lead Opportunity, etc) by upserting the relationship in the ContentDocumentLink object

Following flow chart shows the general approach to upload an attachment to Salesforce:

Start
Get file
Prepare ContentDocument

Create
ContentDocument
Get ContentDocument Id
Prepare ContentDocumentLink

Create
ContentDocumentLink
End

Mule DSL code to achieve this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    <sub-flow name="Upload Attachment">
        <ee:transform 
            doc:name="Prepare ContentDocument">
            <ee:message>
            <ee:set-payload>
            <![CDATA[%dw 2.0
                output application/java
                ---
                [
                    {
                        Title: "filename" //Replace this with actual filename,
                        PathOnClient: "filename" //Replace this with the path on storage system
                        VersionData: payload.content as Binary {class: "byte[]"}
                        //This is the attachment content
                    }
                ]
                ]]>
            </ee:set-payload>
            </ee:message>
        </ee:transform>
        <salesforce:create type="ContentVersion"
            doc:name="Create ContentDocument"
            config-ref="Salesforce_Config"/>
        <ee:transform doc:name="Get Attachment Id">
            <ee:variables>
                <ee:set-variable variableName="contentVersionId">
                    <![CDATA[%dw 2.0
                    output application/java
                    ---
                    payload[0].id
                    ]]>
                </ee:set-variable>
            </ee:variables>
        </ee:transform>
        <salesforce:query 
            doc:name="Get ContentDocumentId"
            config-ref="Salesforce_Config">
            <salesforce:salesforce-query>
                SELECT ContentDocumentId From ContentVersion Where Id = ':contentVersionId'
            </salesforce:salesforce-query>
            <salesforce:parameters>
            <![CDATA[#[
                output application/java
                ---
                {
                    "contentVersionId" : vars.contentVersionId
                }
            ]
            ]]>
            </salesforce:parameters>
        </salesforce:query>
        <ee:transform doc:name="Prepare ContentDocumentLink">
            <ee:message>
                <ee:set-payload>
                    <![CDATA[%dw 2.0
                    output application/java
                    ---
                    [
                        {
                            LinkedEntityId: vars.accountId,
                            ContentDocumentId: payload[0].ContentDocumentId,
                            ShareType: "I"
                        }
                    ]
                    ]]>
                </ee:set-payload>
            </ee:message>
        </ee:transform>
        <salesforce:create 
            doc:name="Create ContentDocumentLink"
            config-ref="Salesforce_Config"
            type="ContentDocumentLink" />
    </sub-flow>

With this approach you can easily upload attachments to Salesforce.

MuleSoft Capacity Explanation for Noobs and CXOs

I was talking to a C-level executive the other day and he asked me to explain how does MuleSoft’s capacity/sizing across various deployment models work. Given I always wear my technical hat I jumped right into the concept of cores and virtual cores and containers (and Kubernetes!) and did a pretty bad job. Fortunately, that executive was very accomodating and somewhat understood what I was talking about. Nevertheless, I should’ve done better.

I was thinking about this conversation over the next couple of days and decided to explain it to my wife - who is very non-technical.

Think of MuleSoft as a specialty cookie store. Or even better, think of Salesforce as a big giant grocery store, with a bakery section called ‘MuleSoft’. MuleSoft specializes in cookies. They offer 3 types of options to buy their fantastic product.

  • Cloudhub: Pre-baked cookies, these come in boxes. Very light and crispy. Rightfully branded as ‘Cloudhub’. You can buy as many boxes as you want. Each box contains 10 cookies. This means with one box you can feed 10 guests. If you have more guests coming over, or some guests are unusually hungry you can buy more boxes. There is also an allergen/gluten free version of pre-baked cookies for government guests.
  • Hybrid: A cookie dough to bake your cookies in your oven. The cookie dough is branded as ‘On-premise / Hybrid’. You can decide how big (or small) each cookie can be. You can make as many cookies as you want with the dough. (No more 10 cookies per box restriction!). Of course, some guests will find your ridiculously small sized cookies unappetizing (or funny).
  • Runtime Fabric: After some guests complained that pre-baked cookies were too big, and ‘make your own cookies’ unappetizing. MuleSoft started offering ‘Runtime Fabric’ branded cookie dough. You still have to bake your cookies, but the sizes of cookies are standardized. They won’t look funny.

Made to Stick and the Curse of Knowledge

I recently read “Made to Stick” by Chip Heath and Dan Heath. It was a fun and quick read. While I liked their framework of SUCCESs (Simple, Unexpected, Concrete, Credible, Emotional, Stories) to get the idea to stick, I thoroughly enjoyed the explanation of the Curse of Knowledge. The curse of knowledge occurs when a knowledgeable individual/expert assumes that the others have the background to understand a specific concept. 

According to Chip and Dan, In general, getting your message across has two stages - the Answer Stage, and the Telling Others Stage. In the Answer Stage, you use your expertise to arrive at the idea that you want to share. This involves studying the material and becoming capable of answering. However, the same factors that worked to your advantage in the Answer Stage will backfire on you during the Telling Others stage. To get the answer, you need expertise, but you can’t dissociate expertise from the Curse of Knowledge. You know things that others don’t know, and you can’t remember what it was like not to know those things. So when you start sharing the answer, you’ll tend to communicate as if your audience were you. 

This reminds me of another news I read a long time ago about an audio illusion. Once our brains know what to expect to hear, they do, even if, in reality, it is impossible.