How to create an API call using REST in Mendix

I recall my first project required numerous GETS and SETS of data between SAP and the application I was developing. Fortunately, a member of the team was a ‘core developer’ versed in Java and many other languages. He took those requirements and ran with them while I and others focused on the business workflows and front-end of the application.

The configuration of the app was a bit different in that the client didn’t want to use SAP’s Web Services, but instead connect Mendix to an API server that would manage security and connections between SAP and it via Remote Function Calls, or RFC’s. I understood everything about the application...except the magic of the API call. Remember, my background is BI and Analysis: SQL I get but API, JSON, RFC...those were foreign words to me.

As is usual, if I don’t understand something, I push myself to understand it. I decided I would start small and build an application in the sandbox that connected to some weather API’s. I wanted to build a page where I could type in the City and/or State/Province and retrieve information about the current weather and a five day forecast. I had never done anything like this before.

I cranked up a new application using the Mendix 5 template. I immediately went into the Mendix App Store and imported the RestServices, CommunityCommons, and MxModelReflection modules; I knew from that previous application that those would be necessary.

Next, I created a new Module I called “OpenAPI” and created an entity named ‘WeatherDetails’. I later came back and added speed and deg when I realized I could retrieve those from the JSON object. But for now, I knew I wanted those other attributes.

I then created a page to allow the user to enter the CityName and then see the results.

As a result of running the app, my page now looked like this:

The API server I chose to use came from http://api.openweathermap.org. It’s not the quickest in the world but I was here to learn, not optimize.

You’ll notice on the page that there is a “Submit” button next to the City and/or State/Province input box. This is where the magic happens.

Before I could write the Microflow (MF) to get the weather detail, I had to build the domain model entities that would store the returned JSON from the API call. When you call an API, you send it some values as part of a URL string and it returns (in most cases) a JSON object that contains information. Here is an example of the JSON object that gets returned with my first API call to get the current weather:

{"coord":{"lon":-71.06,"lat":42.36},"sys":{"type":3,"id":131353,"message":0.4235,"country":"United States of America","sunrise":1424431964,"sunset":1424470983},"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"base":"cmc stations","main":{"temp":263.25,"humidity":36,"pressure":1013.057,"temp_min":262.55,"temp_max":264.05},"wind":{"speed":4,"gust":8,"deg":248},"snow":{"3h":0.125},"clouds":{"all":24},"dt":1424451575,"id":4930956,"name":"Boston","cod":200}

Next, copy that and search the web for a JSON parser (I used jsonparser.org). The result looks like this:

Much cleaner, right? This hierarchy of folders and attribute names is CRITICAL in your Mendix domain model development. The associations must match the names of those “folders” EXACTLY or it won’t work. From this view, I was able to pick and choose which response variables I wanted to use to populate in my “ForecastDetails” entity. After adding those attributes to my entity, I built the non-persistent domain model that will be populated with the JSON above upon the API call.

First, develop a non-persistent entity for the return to map through. In this example, that is called “CurrentWeatherReturn”. The name of this entity is not important; however, the associations to the linked entities, whose names are also not important, must be named precisely as the JSON returns them. If you look back at that JSON response, you’ll see a folder named ‘sys’ in lower case. Therefore, you create an association to an entity named ‘sys’ so that the deserializeJSON java action call in the microflow knows what to put where. Also, you need to place the attribute name in the linked entity precisely as it appears. Example here is that within the ‘sys’ folder of the JSON object is an attribute called ‘country’ that is a string, so that is what is placed in the linked entity. Repeat this process for each set of response variables.

Now that the domain model is constructed, it’s time to build the microflow that will call the API server with the parameters of the query (County,ST in this application), capture the JSON that is returned, store it in another entity that fits the data view within the page, and refreshes the page.

I named the microflow ‘GET_Weather’ (sorry, Mendix, but I really only use three preceding short-names: GET for retrieves, SET for changing or creating data, and NAV for flows that end by calling a ‘Show Page’ object. All of the other short-hands were too detailed for me to keep track of.) Anyway, let’s walk through it:

Step 1: Create a string variable

The purpose of this one is to remove spaces from the input string and replace them with ‘%20’ so the string is ASCII compliant. This is a nice to have when trying to get the weather for say, Los Angeles.

Step 2: Build the REST URL

Now more commonly, you will set this up in the REST configuration admin page and pass that value here or use a constant. Again, I wasn’t doing this to optimize but rather to learn, so I hard-coded it into this string variable. Notice the parameter values (look for the ‘q=’). One is the City/State name that I made ASCII compliant and the other is the units of measurement I wanted. I found those values when researching this API and tested in the browser to get back the JSON I was looking for, but I get ahead of myself:

Step 3: Create the Object that will accept the JSON response

Simple enough. You’ll need to create this object so the data can be held in memory so that the successive steps can parse it appropriately.

Step 4: “Get” the data from the API server

In the RestServices module, you’ll find a java action call named ‘Get’. For this particular use, since I’m retrieving and not posting, I used this. I passed it the variables I built in the preceding steps as indicated in the image:

Step 5: Parse the data according to the domain model

Now it’s time to use that ‘deserializeJSONToObject’ action call. It’s simply setup as such:

Step 6: Retrieve the ‘sys’ object

Now it’s time to start creating microflow variables that will be used to write into our ‘WeatherDetails’ data view to display on the page.

The entity that you use to create as the “object” to hold the response from the JSON must always be a many-to-one or many-to-many association. The JSON response is expected to contain more than one record.

Because there was only one ‘sys’ object, you’ll notice the association cardinality specified a many to one relation. That is why the retrieve results in a single object.

Step 7: Get ‘weather’

In the next variables case, however, the JSON is structured in that a list of objects could be returned within the ‘weather’ association. That is indicated based on there being a sub-folder in the JSON parser. I don’t know why this particular JSON is written this way but that is beside the point of this blog entry. Since I was attempting to learn, I chose to only populate ‘WeatherDetails’ with the first list object. You can see the ‘WeatherDetails’ change object inside of the iterator loop.

Step 8: Repeat the retrieve for ‘main’ and ‘wind’

Just like you had for ‘sys’, retrieve the associated object for those two entities.

Step 9: Populate the ‘WeatherDetails’ entity

The mappings are listed in this image. In reality, this entity could have easily been non-persistent also but I wasn’t too concerned with doing it the “right” way. Persistence is an entirely different subject. Notice I don’t ‘Commit’ the change only refresh it in the client as a workaround to not have to deal with deleting the record and creating a new one.

Step 10: The Result

After assigning this microflow to that “Submit” button on the form, I get a nice clean result.

If anyone wants I can show the second piece that called a different API returning a list of objects for the five day forecast. It was designed in the same way with the only difference being how the JSON was formatted differently requiring iterators through the return objects.

While I still don’t consider myself an expert in this niche of development, I was able to successfully set up the process steps needed.

 

I hope this helps out someone who, like me at the start of that process, was challenged with the inner-workings of making an API call and integrate disparate data into Mendix.