March 5, 2007

Using a Simple File Mutex to Integrate Complex Disparate Applications

As a Windows developer, one of the most challenging (and fun) tasks I sometimes get to do is integrating multiple disparate applications so they can communicate with one another. Most of the time this involves blending a .NET application with an automation application and doing the regular COM interop one would expect. However, occasionally something more interesting comes along. One such occasion popped up recently for me, as I had to design and implement a solution to integrate our mainframe terminal emulation client with an intranet web application.

The main goal of this particular project was to provide a way to pre-fill an existing web form application with data from a mainframe screen. Normally, the user would have to read the appropriate data from the mainframe screen, manually enter the data into the web form, submit the form, and return to the mainframe terminal and key in a simple log entry indicating that the process was complete. Obviously, due to the nature of jumping back and forth between applications and doing data entry, this was a very tedious and error-prone activity.

To understand the scenario a bit better, it's critical to know how the two systems work. The existing web application which does most of the business logic in this entire process is just a traditional dynamic web application; it works pretty much like any other form-based web application you have seen before. On the other hand, our terminal emulation environment may seem a bit unusual to some of you; it is basically a Windows client program connected via our internal network to our legacy system. From a software development perspective, this emulator is more than just a typical dumb terminal; it also provides a handy automation environment in which we can produce macros for screen-scraping data, automating keyboard commands, and executing other Windows-related tasks. However, it's important to note that it is definitely not a web interface by any means, so integrating it with web applications is not entirely straightforward.

In order to get these two applications to work together, I needed to devise a way for them to communicate with each other in a very simple manner. So, like any interop activity, I had to determine the level at which both programs could communicate. Since both environments are quite different from each other, I had to go down to the level where they were both in common—the operating system, in particular, the file system. Basically, both environments have the ability to read and write files, so I opted to use a simple mechanism, which I will call a file mutex, to communicate between the two applications.

Here's the complete process flow that I came up with:

  1. The user clicks a button on the appropriate screen of the terminal emulation client to initiate an automation macro.
  2. The automation macro creates a new file mutex simply by creating a uniquely named temp file on the file system.
  3. The automation macro kicks off a new Internet Explorer session via a shell command, passing all the screen-scraped data and the mutex identifier (the temp file path) in the query string.
  4. The automation macro is then temporarily put to sleep, while it waits for the mutex to be released.
  5. The user completes the Internet Explorer web form and clicks submit, passing the mutex identifier yet again in a hidden form field to the associated confirmation page for this web form.
  6. Internet Explorer displays a successful confirmation screen and releases the mutex by deleting the temp file. (A custom client-side ActiveX object had to be installed in Internet Explorer at this stage to perform the file deletion since this is out of the scope of JavaScript.)
  7. While waiting, the automation macro now sees that the mutex has been released and can then automatically write the appropriate log entry on the mainframe system.

And that's all there is to it! In case you're curious about the ActiveX object in step six, it is a very simple custom VB6 automation object (only ten lines of code) that deletes the temp file passed to it as an argument. Nothing fancy there. But that's the whole point.


Ed Brannin said...

I haven't done VB6 in a while, and never automation, so I don't really know what I'm talking about here -- but ten lines to delete a filename argument?

Python, Ruby, etc. have spoiled me ;-)
import sys

Also, thank you for that icon set -- a couple of them will come in quite useful for a certain wxPython app I'm developing right now...

Marc of the Web said...

That's the whole point, Ed. :-) It's generally pretty trivial in any programming language to delete a file. I could've used any language that supported an automation interface. That's why this works well as a makeshift mutex in a multiplatform environment.

To be fair to VB6, the code to actually delete a file is less than ten; it's more like three. In my count, I was also including the method signature, retrieving the user's temp directory, checking that the file exists, and returning a boolean result about whether or not the method succeeded.

' The IDE imports the namespace nicely for me.
Dim oFso As New FileSystemObject
oFso.DeleteFile sFilePath

I would guess that you can do automation with Python or other similar languages if you'd like. I'm not familiar myself, but I'd bet there are libraries designed to do just that in most popular languages. Remember, the concepts are always more important than the language itself.