Last Updated on 30/05/2021 by Patryk Bandurski
Once we develop and deploy our MuleSoft applications, it is a good idea to test the connectivity. Is the calling system able to reach our API and receive a response? In this article, I will focus on the case when I expose API to Salesforce. I will use the Salesforce playground that is available on the trailhead.salesforce.com website. Let’s see what we need to take into consideration when we expose our API via CloudHub and Shared Load Balancer.
Architecture
I deploy all the Mule applications on CloudHub. I didn’t purchase a Dedicated Load Balancer. Therefore, I will stick with the Shared Load Balancer (SLB). The scenario is depicted below. As you can see, I expose API for Salesforce using HTTPS protocols.
MuleSoft application preparation
Environment considerations
Port configuration
In order to run your application on CloudHub via Shared Load Balancer you are obligated to specify one of two values:
- http.port or 8081
- https.port or 8082
Anything else is prohibited, and your application won’t work properly.
Shared Load Balancer
In the article Enable dedicated load balancer under own domain, I mentioned how DLB works. This time, however, we use SLB. So how it works? Our APIs are published under https://[app-name].[region].cloudhub.io and this is translated to https://mule-worker-[app-name].[region].cloudhub.io:8082. As in the example below. What is crucial to see is that the SLB has a CA-signed certificate for subdomains of cloudhub.io, whereas my application must be signed with a self-sign certificate.
TLS configuration
As I mentioned previously, I expose my API via HTTPS protocol. To do this, Mule expects TLS configuration. In my scenario, I need to use the self-signed certificate as I do not own the cloudhub.io domain or subdomain. Below you can see a screenshot from the KeyStore Explorer application. Using it, I have generated key pair and saved as a keystore file of type JCEKS.
Implementation
As the logic of our service is not relevant in our case, I will skip this part. It can be a simple Transform Message that returns a fixed response. What is essential, from the connectivity perspective, is the listener configuration.
HTTPS Listener
In order to expose our service over HTTPS, I set inline the TLS context. As you can see below, in line 5 I refer to https.port. Of course, you do not need to define this property in your property files. It is automatically populated by the CloudHub.
<http:listener-config name="HTTPS_Listener_config"
doc:name="HTTPS Listener config">
<http:listener-connection protocol="HTTPS"
host="0.0.0.0"
port="${https.port}" >
<tls:context>
<tls:key-store type="jceks"
path="keystore.jceks"
alias="mule"
keyPassword="${secure::https.keystore.key}"
password="${secure::https.keystore.password}" />
</tls:context>
</http:listener-connection>
</http:listener-config>
Salesforce APEX class
Okay, we already wrote the application. It is time for a connectivity test. Is Salesforce able to consume my service? To do this, I write a simple APEX class to call our service. The first thing to do is to register a remote site.
Register remote site
Before we try to connect with our MuleSoft application we need to register URI, so Salesforce enable outbound traffic.
- Once you login to your Salesforce click Setup
- Click Service Setup
- Next, find Remote Site Settings configuration
- Click New Remote Site
We need to provide at Remote Site Name and Remote Site URL. As we are using the SLB, the application name is located in the subdomain. That means that we need to create as many entries as many Mule applications we are going to consume. Below I have registered exchange-portal-xapi application on dev environment.
APEX class in Developer Console
Let’s open Salesforce Developer Console.
- Click Setup
- From the dropdown pick Developer Console
- From the menu choose Debug and then Open Execute Anonymous Window
- Copy below code into the Execute Anonymous window:
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://dev-exchange-portal-xapi.us-e2.cloudhub.io/api/v1/exchange-rates');
request.setMethod('GET');
HttpResponse response = http.send(request);
// Deserializes the JSON string into collections of primitive data types.
Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
Map<String, Object> rates = (Map<String, Object>) results.get('rates');
Map<String, Object> eur = (Map<String, Object>) rates.get('EURGBP');
System.debug(eur.get('rate'));
What does this code do? We are going to call the GET operation on https://dev-exchange-portal-xapi.us-e2.cloudhub.io/api/v1/exchange-rates (line 3, 4). We make a call and wait for the response in line 6. Next, we do response validation. I extract rates.EURGBP.rate and log it in the console.
To verify if the call works, click Execute. If some significant failure occurs, you should see a popup window. The output from the execution is opened in the new tab in the Developer Console. As you can see on the screenshot below, I checked Debug Only to narrow down the logs, and I see value 0.891724 that was extracted from the response.
Success it works. Salesforce team can now easily connect to our MuleSoft APIs.
Summary
As you can see, verifying if Salesforce can reach our service exposed on CloudHub is a cinch. I published API over HTTPS via Shared Load Balancer. Therefore the subdomain was signed with valid CA Authority. Salesforce did not get any problem to call API. In the next article, I will try to do a similar thing—however, this time having Dedicated Load Balancer in place.