With the Exchange Web Services project, I have found a lot of .NET example code that makes connecting to Exchange from .NET a breeze. It's orders of magnitude easier than from Java, and that's to be expected – Microsoft's primary focus is on Microsoft. I do, however, want to make it as easy as possible for people to integrate Exchange into their applications, and from a UI point of view, the easiest way to do this is through .NET.
Providing a .NET control that facilitates this as Open Source is definitely on the to-do list for the Exchange Web Services project, but I was not sure how I would do this for OpenEdge as non-UI controls are not supported and most of the work that the control does is communication with the Exchange Web Service in a multi-threaded configuration on background threads.
On May 5th, Progress temporarily raised the restriction to test the OpenEdge GUI for .NET bridge with controls that have no user-interface so that users can experiment with the controls and determine what types of controls should be supported. My company, Intangere, thus signed up for the program and created a control that mimics the behavior of a proposed Exchange Web Services control. This test has been surprisingly successful, and this article provides some information about the test and the code and a document that describes its use.
Progress would have had logistical issues incorporating an Exchange Web Server into their nightly build simply to test the background functionality that this control will provide. To test the functionality, therefore, I needed to provide Progress with an example that replicates the functionality that I expect to use in the Exchange Web Services architecture.
The model at left graphically demonstrates how the architecture of the code works. The model closely mimics the model for the Subscription and Notification API that I discussed in the Exchange Web Services – Subscriptions and Notifications post that I wrote back on April 26th.
Starting from the right of the diagram, Listener.exe is intended to emulate the functions that are performed by the Microsoft Exchange Web Services API. Specifically, it supports registering subscriptions and notifying the client of "updates" on a background thread. All communication between the client and Listener.exe is by means of .NET objects serialized as XML.
The EWSEmulator Control is a .NET control that has no user interface and performs the function that the Java EWS WebService and the Java HTTP Servlet perform. As such, it is derived from System.ComponentModel.Component and it handles the job of communicating with Listener.exe, both in terms of posting subscription requests, and in terms of receiving notifications. The control receives the notifications on a background thread (the Notification Processor) which deserializes the objects and hands them to the event generator which raises a .NET event on the UI thread.
Receiving the event on the UI thread is one of the most critical components of this control. OpenEdge is single-threaded which means that if an event is raised on anything but the UI thread, it is likely to cause problems for OpenEdge. So the Event Generator's sole function is to marshal all notifications and generate a .NET event on the UI thread.
The User Interface Logic is responsible for registering subscriptions via the embedded EWSEmulator Control, shutting down the Listener service and reacting to events raised by the Event Generator.
So how did the test go?
I'm not going to spend a lot of time telling you about the gory details of the code. You can download the code and a document that describes a lot more about my experience and findings, and you can even run it and look at both the ABL and .NET code. The document is a PDF contained in the zip file.
In a nutshell, though, I was able to duplicate the behavior I was looking for, marshal the events onto the UI thread, and get OpenEdge to react to those events without too much trouble. Section 4.2.2 of the document provides a description of how the marshaling works.
More importantly, I was also able to establish that the volume of data that can be handled by the OpenEdge ABL in this kind of communication was significantly greater than I had thought. I was able to generate upwards of 400 messages per second from Listener.exe and the client handled them without losing any.
Of course, no one in their right mind would expect the client to handle that volume of traffic, especially considering that every event had to be marshaled to the UI thread. But it was encouraging to learn that it was possible.
What this test has proven is that the OpenEdge GUI for .NET is more than capable of supporting background controls, provided they conform to the rule that all threads need to be marshaled to the UI thread before an event is raised.
Also, I made extensive use of the XmlSerializer, HttpListener, HttpWebResponse, and several other streaming classes and had no problem at all with OpenEdge.
I have submitted this code and these findings to Progress Software and hopefully they will be able to lift the restriction on use of non-UI controls with OpenEdge GUI for .NET.
Feel free to download the example code and documentation and mess with it, and please let me have your feedback.