Windows Phone Change Resiliency – Javascript

In the previous post, I discussed how you can use XPath to solve a lot of resiliency issues with external dependencies. In this post, I will show how to use Javascript (through JINT) to write parts of your code in such a way that you can fix or bugs, or even change functionality on the fly.

A little background…

JINT is an open-source project that allows you to run interpreted Javascript inside .NET applications. The Javascript is pretty standard and the developers did a truly outstanding job at it. One of the neat features in the engine is that it can interact with the host (your app) and call into managed code inside it – including the instantiation of objects and so on, essentially providing a bridge between the JS code and your managed code. A few months ago, a gentleman by the name of Joel Martinez releaseda ported version of JINT for Windows Phone. A bit after, we fixed up the bridge (which was busted) to work properly, allowing you to hook events in objects, call generics and interact with large portions of the CLR..

Theoretically, it would have been easier to use something like CodeDom to grab C# code off the server and compile/run it. Sadly, the WP platform does not support this assembly and so an alternative needs to be found.

Using JINT to run rudimentary expressions

In the previous post, an example was given where an XPath expression was used to create a URI. The expression was fairly simple and allowed the developer to easily create customized versions of the URI. However, what if the simple expression language of XPath is not enough? Here’s a refresher on what the XPath was like:

XPath
  1. concat(‘http://weather.yahooapis.com/forecastrss?w=’, substring(‘{0}’, 0, 5))

It takes the original zip code ({0}) the app passes to the URI and modifies it to be a sub-string, taking the first 5 characters.

What if, instead of ZipCodes, the service (or a new service you find yourself needing to connect to) suddenly requires a different code – some code that is be mapped to zip codes by the service?

Creating an XPath that will match thousands of numbers will probably not work – it will be too cumbersome for the processor to run. For this, you need a somewhat more robust mechanism instead. In this case, you can decide to use a Javascript fragment to do your calculation. Whereas before we were passing an XPath string to the parser, we will now pass a Javascript fragment to the engine and use the result. Here’s the original Javascript (before the modification needs to take place):

Originat JS code
  1. return “http://weather.yahooapis.com/forecastrss?w=” + “{0}”

After you discover the problem, you will need to change the script to the following – part of which you will need to probably generate on your machine (note, the double squiggly braces ({{) are needed since this string will go through String.Format() and if you don’t have it, the formatting function gets confused)

Javascript Mapper
  1. var oldValue = {0};
  2. var newValue;
  3. switch (oldValue)
  4. {{
  5. Case 20023: newValue = 11111;
  6. Case 20024: newValue = 22212;
  7. // ….
  8. }}
  9. return “http://weather.yahooapis.com/forecastrss?w=” + newValue;
  10. Using the JINT engine is fairly easy:
  11. public object RunScript(string script)
  12. {
  13. JintEngine engine = new JintEngine(Options.Ecmascript5);
  14. engine.AllowClr(true);
  15. engine.DisableSecurity();
  16. return engine.Run(script);
  17. }

Voila – override the original script from your server and your app is fixed!!

But wait.. Won’t it be slow?

Yes – this specific example will probably be pretty slow if there are thousands of numbers 1360893_18747736to map. However, an app that’s slow for a few days (until you submit an update) is vastly preferable to an app that does not work or crashes.

In some cases, the logic employed is going to be so complicated that you will be pressed to find an alternative, but in most cases you should be fine.

Wrapping more complex logic

In all the previous examples (the XPath ones in the previous post and the Javascript ones here), I showed you how, by having an entry point (the expression for the URI), and XPaths, you can essentially customize the various calls you make in your app.

One thing I have not touched on yet is customizing flow.

In the example just given in this post, I had to create a fairly large Javascript expression to map Zip codes to some other code. Assume that that logic, of doing the mapping, is actually encapsulated in another web-service call – however, since my flow is rigid (I make a call in managed code to a single entry point, and then I parse the results coming from that entry point in a certain way), I cannot just “add” another asynchronous call in the middle to call the mapping service.

However, since the JINT engine is a full-blown Javascript engine, it should be possible to encapsulate the entire logic in Javascript and thus run the code partly in managed and partly in native.

Wrapping javascript code in a managed object

My suggestion is that when you employ this mechanism, you create a managed wrapper object that will take care of running the script and doing all the back-and-forth translations. The sample code you will be able to download contains a helper class that does some of the work for you.

This is what the structure looks like with relation to which object resides where (on the left) and a sequence diagram that shows the flow of the calls (click to see a bigger image):

Change-Diagram1Change-Diagram2

For the example shown, the wrapper class simply looks like this:

Code Snippet
  1. public class WeatherGetter : ScriptObjectWrapper
  2. {
  3. public WeatherGetter(string script) : base(script)
  4. {
  5. }
  6. protected override string FactoryFunction
  7. {
  8. get { return “createWeatherGetter”; }
  9. }
  10. public void GetWeather(string id, Action<int, Exception> callback)
  11. {
  12. CallWrappedFunction(“getWeather”, id, callback);
  13. }
  14. }

The important bit you need to do is tell the wrapper what function creates your wrapped JS object (FactoryFunction()). Everything else is taken care of by the class.

For each capability the wrapped JS code has, you should create a helper method that will do the invocation for you (though you can always call CallWrappedFunction()directly).

In this case, we are creating a GetWeather() wrapper that takes the id to pass to the service (the zip code, or whatever). The second parameter is a delegate that returns an integer and an Exception parameter, if something goes wrong.

Finally – the actual JS code…

The following is, again, the javascript code that will drive the actual flow. The point is that you embed the initial script you know works in your app, but allow yourself to update the code by using a server (that you fully control!) to download updates, if they are needed. The code is fairly involved – there are comments embedded in the code you should really look at as well as some general information about the code after the sample.

Code Snippet
  1. // Factory function – will be called by the wrapper to create the object.
  2. function createWeatherGetter()
  3. {
  4. return new weatherGetter();
  5. }
  6. // Our wrapped object
  7. function weatherGetter()
  8. {
  9. // The wrapper field will be set to the C# wrapper object – that way, if needed, the developer can
  10. // call back to the C# object containing it. Not used in this example.
  11. this.wrapper = null;
  12. // This is the method on the object that will be called by the wrapper.
  13. // id = the ID to pass into the URI.
  14. // callback = the delegate to call once the operation is done.
  15. this.getWeather = function(id, callback)
  16. {
  17. // Create a .NET WebClient instance.
  18. var client = new System.Net.WebClient();
  19. var uri = new System.Uri(‘http://weather.yahooapis.com/forecastrss?w=&#8217; + id);
  20. // Add an event that will be fired when download is done.
  21. client.add_DownloadStringCompleted(function(s, args)
  22. {
  23. var ex = args.Error;
  24. var temp = 0;
  25. // If there were no exceptions, we can process the call.
  26. if (ex == null)
  27. {
  28. var xml = args.Result;
  29. // Create an XDocument to use
  30. var doc = System.Xml.Linq.XDocument.Parse(xml, System.Xml.Linq.LoadOptions.None);
  31. var ns = System.Xml.Linq.XNamespace.Get(‘http://xml.weather.yahoo.com/ns/rss/1.0&#8217;);
  32. // Find the ‘condition’ element.
  33. var conditionElements = doc.Root.Descendants(ns.GetName(‘condition’));
  34. var conditionElement = System.Linq.Enumerable.FirstOrDefault{System.Xml.Linq.XElement}(conditionElements);
  35. // Extract the attribute ‘temp’ out of the xml.
  36. temp = conditionElement.Attribute(System.Xml.Linq.XName.Get(‘temp’)).Value;
  37. }
  38. // Call the callback – this will invoke whatever the wrapper has as a callback.
  39. callback(temp, ex);
  40. });
  41. // Don’t forget to invoke the actual call that will download the string.
  42. client.DownloadStringAsync(uri);
  43. };
  44. }

A few things worth noticing:

  1. The top function in the JS code is the factory function (we could not find a way of instantiating JS objects through the JINT interface).
  2. The second function is actually a JS object. That JS object gets instantiated and the reference to it is held by the wrapper object (taken care of as part of the ScriptObjectWrapperfunctionality).
  3. The getWeather field holds a function that is responsible for getting data from the server. It takes a callback that will run once the asynchronous operation is over. The first parameter is the result and the second parameter is an Exception (this could have been implemented with an EventArgs-like class as a parameter instead of multiple parameters).
  4. Notice that for making http requests, the code does not use XMLHttpRequest – that class is not present by default in JINT. Instead, it’s simply uses .NET’s WebClientclass. It could have used any other class as well.
  5. Registering and unregistering with event is done through methods called add_[EventName]() and remove_[EventName]()respectively. All you need to do is pass in the callback you want to register.
  6. I chose to use System.Xml.Linqhere simply to show that it’s possible – the code would have been simpler had I decided to use XPath.
  7. Extension methods do not work in JINT. To use them, you need to call them directly (in the example given, the calls to Linq are done through System.Linq.Enumerable on which we call the static FirstOrDefault()method), with the instance on which you want to operate being passed as the first parameter.
  8. A note on how generics are used: To call a generic method (or instantiate a generic class), you need to use a special non-standard syntax to specify all the types that the generic takes as a parameter – there’s no deduction-by-type that is done a’la C#. If you take a look at the call to FirstOrDefault(), you will see that the actual call looks like this:
    System.Linq.Enumerable.FirstOrDefault{System.Xml.Linq.XElement}(collection);
    The specializing types need to be passed to the class or method call via the squiggly parenthesis.

Any tweak you now want to do, you can do directly by changing just the javascript code. For example, if the flow of getting the data you need now takes two async calls to two different services, you can simply add another async step to the JS code and call the callback once both network calls are done.

How easy is it to write the JS code?

It can become hairy – I won’t lie. The JINT engine, while a fine piece of code, had a ton of bugs in it when it comes to the bridge between CLR and JS. I have fixed a lot of these bugs, but I keep finding more bugs all the time. A lot of things can be worked around by using different calls right in the javascript (for example, in the generics bugs had not been fixed, you could laboriously use the IEnumerable methods directly to interrogate the returned nodes).

We have found the following to be the most common developer errors when writing JS code (that is, errors in the JS you feed JINT rather than JINT bugs) – so I suggest you be especially watchful for these:

  1. Slipping and forgetting to pass the full .NET name (including namespace) when calling into static methods/creating classes.
  2. Passing incorrect types (JS is untyped, and so JINT does it’s best to find the correct overloads and coerce parameters correctly). Sometimes, you may just want to explicitly type the parameters you pass in

However, even if it takes an hour to adjust your JS code calling into a service, it’s still a far cry from the amount of time it will take an app to go through certification and be available for users.

What else can you do with this?

The sky’s the limit really. One thing we do for some of our apps is find areas of the code we know could be sensitive and build an event system around them so we can “hook” into them and fix future issues as they arise. This is akin of being in a shooting range with a blindfold and trying to hit the target in the head – if you are experienced enough and careful enough, you will probably get some in the general vicinity, miss some shots a1111030_19526517nd maybe strike a direct hit or two.

For example, if you find that your settings load/save process can get corrupted under certain cases, you may want to create a static object exposing “BeforeLoadSettings” and “AfterLoadSettings” events. When you release your app, nothing will hook these events. However, you now have the ability to hook these events through JS downloaded from your server and add code to fix future bugs or issues.

We really suggest you do not move large portions of your code to JS for a number of reasons. Not only is JINT incredibly slow when compared to compiled code running in the CLR, it’s also much harder to write with no intellisense or anything. Areas that are written in JS should really be thought up in advance and surgically added to the app. If large swaths of your app are written in JS/Jint, you are going to have a bad time.

Which brings us to the next point…

Performance and Security

JINT is not fast. It’s not slow enough that code such as the above will be noticeably slow or anything, but the more code you have in JINT, the more it does, the slower and choppier your app will become. We HIGHLY suggest that any tight loops or complicated calculations be written in C# with the option of falling back to Javascript if an issue happens (until the next update that will fix the issue).

Incredibly important: Remember that code running in Javascript runs as your app – make sure that your Javascript is loaded from a secure server only you have access to.

If your JS code does not need access to CLR objects, you can turn off CLR functionality and expose only the specific objects you want, allowing you finer control over what’s exposed.

What’s next?

The next post will show more advanced techniques that can be used with XPath and a few that can be used with Javascript to make your apps more adaptable. The post after that will give you all the downloads and everything else you will need to put all this information into practice.

Advertisements
This entry was posted in Dev, Resilient, Uncategorized, WindowsPhone. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s