Most people start out with using the following syntax to make a service call:
When the foo.bar service is invoked, a response will be returned some time in the future, and then the callback function is called. It gets interesting when the service is not available, or when we pass invalid parameters to the service call. How to deal with exceptions?
When using service calls as shown above, the default error you will see will resemble the following message:
Admittedly, this message is not very useful. All it says is that something went wrong. However, it also tells you to add an exception handler to get a more detailed explanation. Following this advise, you might be tempted to rewrite your service call to look like this:
It would seem like the right thing to do. Call a service. When something bad happens, handle the exception. However, service calls consist of two steps. First, you send out the service request, which is really dealt with in the "call" part of the statement. The service request is sent over the wire, and control immediately continues to the next line. No exceptions will happen at this point, as you can assume we will always be able to send the request over the wire. Now, when the response comes back in the future, the callback is invoked. If the server responds with an error message instead, we have no real place to report the error to the code. This is why we have a special syntax on the call statement looking like this:
Now, each time the service is unresponsive, or the server complains about our parameters being incorrect, the handleException function will be called, and we can take evasive actions.
With that in mind, service debugging is already much easier. However, it is still hard to see what request body we sent out, what actual reponse headers we received, etc. In some cases, you actually will need to inspect those to deal with pesky third party services that have a particular way of having to be set up. One example would be a service that establishes a connection in a login screen, and returns a cookie in the response header. In future calls, you are then expected to pass in that same cookie as part of your request parameters. We need a tool to easily inspect and spy upon the services being sent by a Rich UI application. Tools like Firebug help, but it happens to be that it is not too hard to do this directly in Rich UI itself.
To explain our approach to a Service Monitor, let's show the intended end result first:
The Service Monitor shows an extra bar at the top of your application. Each green icon represents a successful service call, and a red icon shows a failed attempt. When you click on one of the green or red icons, a dialog box opens which you can drag around the screen:
The dialog shows the details of the service call. You will see things like the method being used (POST/GET/PUT/UPDATE), the values of the request and response body, the query parameters, and the request and response header. You will also see how long the service took to return. The service monitor is easily added to any application by simply adding a field declaration to your application's RUIhandler:
The three InfoBus events that are now generated by the runtime are received by a piece of UI (see ServiceMonitor.egl, implementing the monitor bar shown above). Actions are taken to respond to these events taking place:
As you can see, if a service call is successful, we will add an OK icon with green background. Otherwise, we add an ERROR icon with red background.
Have fun using this monitor and hopefully you will find it will greatly improve your ability to call any web service out there....