“What’s the version of your Mule API?” you might be asked one day.
On the surface, you would think it’s such a trivial question, but if you think again, you would know there is much to more to the story.
The truth is, there are a few “versions” of the same Mule API depending on what you’re referring to.
In theory, an API version is the version of the API interface. The interface definition is a contract that declares what the API can and shall do. MuleSoft uses RAML to define the API interface. There is a “version” attribute in RAML file specifies the version of the API.
RAML is the equivalent of WSDL in the SOAP world, or IDL for Java RMI. Once it is published, it should stay as stable as possible unless you absolutely have to change it, because changes may break existing clients. However, in the real world, we do make changes to the interface. If the interface has changed, the version number should be updated.
In an ideal world, the “version” defined in the RAML should be the single version # we ever use to refer to this API interface anywhere. However, the real world is little bit more complicated.
Let’s take a look at the life journey of an API version and its different incarnations in the Mule world.
When RAML (which should have a version in it) is used to generate an API project, Anypoint studio will use the RAML file to create a skeleton flow of the API project. The RAML file is placed under “src/main/api”, and the API main flow will contain an “apiRouter” flow that routes the HTTP request based on the RAML definition.
For the sake of this discussion, assume the RAML has two REST resource paths.
version: v1 /foo: get: /bar: get:
You can access the API endpoint with something like http://host/myHelloAPI/foo, http://host/myHelloAPI/bar. We will elaborate more about the “myHelloAPI” portion of the URL. Let’s continue for the time being.
What happens if you manually change the RAML file after you published your API already?
If you change the RAML like below and but never bothered to change your flow:
/foo: get: /car: get:
Your project will compile and deploy fine and when you call http://host/myHelloAPI/bar, Mule runtime will balk, and bark at you. That’s not what we want.
Let’s do a somewhat more realistic RAML change like below and you also updated your flow accordingly:
version: v2 /foo: get: /bar: get: /car: get:
After deploying your API, it all runs fine. You are happy. Your previous client still access the API via http://hostname/foo, http://hostname/bar. For the people who know your API’s change, they can access http://hostname/car.
From the URL, the previous clients never know the version has changed. They don’t know they can access new “/car”. That’s not fair!
For the SOAP folks, at least, by convention you can check the WSDL (interface) by calling http://host/myHelloAPI/mysoapservice?wsdl and you can see which version of the interface you are dealing with. In the REST API world, there is no such thing! Why? First of all, unlike the SOAP world, there is no universal definition language of REST API. I hope someone can start a convention like http://host/myHelloAPI/myRestAPI?raml or something like that. The problem is the swagger (OpenAPI) folks will have to invent something different. Of course, there is even WADL folks. Without the established conventions, the closest thing to check the interface is either use the RMAL API Console (if available) or use API portals to check on documentations. Well, I digressed.
Let’s come back to the API version. We see that the “version” in the RAML really intends to declare that the logic version of the API interface. One way to let the clients know which API version they are using is to embed the version in the API URL during the runtime deployment.
Choosing a Global Software Development Partner to Accelerate Your Digital Strategy
To be successful and outpace the competition, you need a software development partner that excels in exactly the type of digital projects you are now faced with accelerating, and in the most cost effective and optimized way possible.
Get the Guide
For example, to differentiate v1 and v2, we can make two deployments of the API as:
http://host/myFooAPI/v1/foo and http://host/myFooAPI/v2/foo (please note for on-prem deployment, each project may decide whether to include “myFooAPI” as part of the endpoint URL)
If you deploy to cloudhub, you can do http://myFooAPI.cloudhub.com/v1/foo and http://myFooAPI.cloudhub.io/v2/foo
I think you get the point. We just need to insert “v1” or “v2” somewhere in the API endpoint URL so clients know which version they are calling. (In case you are wondering what happens when you have multiple environments, hold on to it, we’ll talk about that below).
Yeah, everything is honkey dory now. Before you go out to celebrate, you have to be aware of one important implication by inserting “v1”, “v2” in the URL: there is nothing to prevent someone to deploy “v1” of the API, and name it “v2”. All of these conventions have to be followed up with a manual or quasi-automatic process and with developer discipline to ensure “what-you-see-is-what-you-get” for the clients.
Let’s sum up what we got so far before we plunge into the other hole of API versions.
- Each API interface has a version. That is the version declared in the RAML “version” attribute.
- Developers should stay true to this API version either in the implementation or in the deployment URL.
Now, let’s move on to the multiple environments. Once you get a RAML defined in the APIM console. You more than likely need to deploy the API implementation to more than one environment. However, unlike Mule Runtime Manager, the Mule API Management Console does not have the concept of environment, such as “DEV”, “QA” or “PROD”. The APIs are “managed” across all environments the same way. Therefore, to differentiate “myHelloAPI /v1/” for DEV, QA or PROD environments, developers need to add more “technical versions” for the same logic API version “v1”. In the Mule APIM view, the same API version may have a picture like:
- myFooAPI-v1 (the logical version v1 declared in RAML)
Please note the version “myFooAPI-v1-dev” is purely for API management purpose, that’s why I call it a “technical version”. For the curious mind, this is the version that appears in the source code
<api-platform-gw:api apiName=“![p[‘api.name’]]” version=“![p[‘api.version’]]“ apikitRef=“proxy-config” flowRef=“proxy” doc:name=“API Autodiscovery”/>
There is no compiler level enforcement of this “technical version” to be consistent with the “logic version” in the associated RAML file. Again, developers need to be disciplined to ensure the versions (for example “v1”) appear consistently in both places!
Finally, keep in mind, when deploying the actual API to Cloudhub, no one can stop you from deploying the application to an endpoint like http://myBarAPI-v99.cloudhub.io. All I can recommend is please select a meaningful name like http://myFooAPI-dev.cloudhub.io/v1, so the API users will have a better idea of your true API version.
OK, it is time to lasso in all versions of the Mule API now.
A Mule API version may have three incarnations:
- The logical API version that is declared in the RAML file with the “version” attribute. This should be the true interface version for the API.
- The version that appears in an API service end such as http://host/myFooAPI/v1 or http://myFooAPI-dev.cloudhub.io/v1 should be consistent with the RAML logic version.
- Each deployment environment has a “technical version”, they are strictly used for APIM purpose, these are the same versions as they appear <api-platform
Here is a summary of the Mule API version table:
|Deployment Endpoint URL|
For the “version” column:
row #1 the version that appears in your design document. I call this the logic version.
row #2 this is the RAML version, it is same logic version as in your design doc.
row #3 – #5, these are what I call the technical versions, you better name them consistently with the RAML logic version. Unfortunately, no one can prevent you from naming them “myHelloAPI-v99-dev”, just please do not do that!
For “tag” column:
row #3 – #5: these are the technical versions in your API source code. They are supposed to be the same as the “version” column. You can change the “API version” in the API management console, . Again, don’t do that please!
For “on-prem” and “cloudhub” columns:
row #3 – #5: they should be named consistently as in the previous columns. If you name them differently, I give up. That’s your prerogative after all. But don’t do that, please!
There can be another variation of the API version. On the API management console, you can actually add or change the versions for each platform to anything you like. Please let’s keep it the same as the technical versions. We have got too many places to mess up!
However, I would amiss if I don’t mention the version that appear on the API portal site. Let’s keep that one as the “logical version”. We publish official documents there, and label it as “v1” to link to the official site for the logical version of the API.
Here is a screenshot of example Mule API versions.
There you go, that’s my tale on the Mule API versions.