In a previous blog post, I described the high level architecture of microservices
running in a Docker container. This blog post describes (again at a high level) the behind-the-scenes implementation of how a we render the output of a microservice back to the client’s browser. We’ll use the Weather Underground API for acquiring our current weather conditions.
First, let’s start with a semantic address:
public class ST_Address : ISemanticType { public string Address1 { get; set; } public string Address2 { get; set; } public ST_City City { get; set; } public ST_State State { get; set; } public ST_Zip Zip { get; set; } public ST_Address() { City = new ST_City(); State = new ST_State(); Zip = new ST_Zip(); }
Note that there are other semantics involved here (ST_City
, ST_State
, and ST_Zip
) which we won’t go into here. We’ll populate the ST_Address
with the two pieces that Weather Underground requires, city and state, and then publish this type to the docker container:
http://192.168.99.100:5001/publishSemanticType? semanticTypeName=ST_Address&instanceJson= { "City": {"City":"Hudson"}, "State": {"State":"NY"} }
The microservice, in HOPE terminology, is a “receptor” that is interested in
the type ST_Address
. As implemented in C# (fragment):
public class WeatherForecast : IReceptor { public void Process(ISemanticProcessor proc, IMembrane membrane, ST_Address address) { string json = Http.Get("http://api.wunderground.com/api/[yourapikey]/forecast/q/" + address.State.State + "/" + address.City.City + ".json"); var data = WeatherUnderground.FromJson(json); var statForecast = data.Forecast.Simpleforecast.Forecastday.Select(d => new { Month = d.Date.Monthname, Day = d.Date.Day, Weekday = d.Date.Weekday, High = d.High.Fahrenheit, Low = d.Low.Fahrenheit, Conditions = d.Conditions, IconUrl = d.IconUrl, MaxWind = d.Maxwind.Mph, }).ToList(); // ... // Building the day and night detail forecast is not shown. // ... Response result = new Response() { HopeResultWrapper = new WeatherResult() { StatForecast = statForecast, DayForecast = daySummaryForecast, NightForecast = nightSummaryForecast, } }; // Call back to the host with the result. RestCall.Post("http://192.168.0.2/hope/result", result); } }
The response is associated with an XML file that determines the rendering.
Here’s a fragment showing just the first to rows (the day and the icon) of
rendering definition:
HOPE renders this into HTML and sends the HTML over an HTML5 websocket to the browser where the page defines this tag:
and on receiving the message from host, executes this Javascript:
ws.onmessage = function (wsevt) { var msg = wsevt.data; $("#appContent").empty(); $("#appContent").append(msg); };
The result is rendered on the browser like this:
By changing the rendering to a VerticalGrid
we instead get:
By changing the rendering XML definition again (not shown, it’s quite long) we can show the results from all three collections — stat, day, and night — to render a more detailed forecast.
Of course, in real life, you’ll want to render the results of many microservices. We’ll look at how that works soon!