Everything Doesn't Happen at Once: Loosely Coupled Events

<< Click to Display Table of Contents >>

Navigation:  Old Material >

Everything Doesn't Happen at Once: Loosely Coupled Events

Peter Vogel        

If you're running Access on a Windows 2000 computer, you can take advantage of COM+ to build more sophisticated applications. Peter Vogel looks at using Loosely Coupled Events to create applications that run asynchronously.

Not everything in your application has to happen at the same time. In fact, applications that require all of their components to be online and available at the same time are more difficult to maintain and demand more resources than applications that can be segmented. If you can break your application up so that some processing can be "de-coupled" from the rest of the application, you can gain some significant benefits. The object is to have parts of your application run asynchronously, allowing components of your application to respond to requests from the other parts of your system at some convenient time.

For instance, a sales order application might accept orders all day without making any updates to support shipping the goods that have been ordered. Sometime after the sales order system shuts down, the portion of the application that does the shipping updates could run and complete the processing. There are four major benefits to this kind of design:

The order system can continue to run even if the shipping database isn't available.

Contention problems over the data are reduced because updates are deferred until data is available.

Response times on the front end of the system (the user interface) are improved because less is being done during data entry.

Shipping updates can be done during off hours to red0uce demands on hardware.

The last benefit is important because it allows your application to be more scalable. You might have orders being entered at the rate of several dozen per second at your peak hours. However, the de-coupled shipping process could run along behind the order entry process, falling behind during the peaks but catching up with the orders during the slow periods. The load on your computer is distributed more evenly over the day.

QC, LCE, MSMQ

In Windows 2000 with COM+, building this kind of functionality into your Access application is easy. COM+ provides two services that allow you to de-couple portions of your system and implement asynchronous processing: Queued Components (QCs) and Loosely Coupled Events (LCEs).

You can achieve much of the functionality of QCs and LCEs by using Microsoft Message Queue (MSMQ). However, QCs and LCEs let you accomplish the same things as MSMQ with much less effort. To use MSMQ directly, you have to learn how to use the MSMQ objects to create a message and put it on a queue. You also have to create a listener program to process your messages—something that often requires creating an NT service. With QCs and LCEs, you just need a little Visual Basic and, thanks to VBA being the programming language for both Access and Visual Basic, you should feel right at home.

A QC is an object that you can create, call its methods, and release without the object ever actually being loaded into memory. Instead, a message is placed on an MSMQ queue for later processing. At some later time, COM+ will then load the object into memory, call the requested method, and release the object. There are two problems with QCs: You need MSMQ, and you have to initiate processing of the queued messages.

LCEs, on the other hand, are almost a free gift from COM+. You create an LCE object using the New keyword, exactly as you'd create any other object. With the object created, you call the object's methods, passing whatever parameters you want. You then set the object variable to Nothing to destroy the object. After you release the object variable, COM+ will create the object and run the methods you requested. This code creates an LCE, calls a method, and releases it:

Dim objLCE As Ship.LCEComponent

Set objLCE = New Ship.LCEComponent

objLCE.UpdateShip strCustNo, strOrderNo

Set objLCE = Nothing

If this code looks like the code you'd use to call an ordinary component, you're right—it is. From the programmer's point of view, an LCE is indistinguishable from an ordinary component. The LCE can then start up Access and run the de-coupled portion of your application.

There are two limitations with LCEs. The major limitation is design: You must have an application whose components can be run independently of each other. The other limitation is that the communication between your Access application and the LCE is one-way: You can pass data to the LCE, but you can't have the LCE return data to you. After all, by the time the LCE actually runs, your application might have completely shut down.

Creating an LCE

Creating an LCE is relatively straightforward. First, in Visual Basic, you must create an ActiveX DLL project. I gave my project the name Ship. You then need to use a Class module to define the interface that your LCE will implement. Defining the interface begins by giving the Class module the name that you want to use for your LCE (in my case, that's LCEComponent). The next step is to write the methods that make up the LCE's interface. A method is just a subroutine, declared as Public, in a Class module. This code declares the UpdateShip method that I used in my sample code:

Public Subroutine UpdateShip( _

 ByVal CustomerNumber As String, _

 ByVal OrderNumber As String)

 

End Sub

To support the limitations of an LCE, the method must be a subroutine (because an LCE can't return a value), and its parameters must be declared ByVal instead of the default ByRef (again, because values can't be returned from the LCE).

You don't put your code in the Class module that defines your interface. While that Class module is the one that your application will use when working with your LCE, you actually put the code for the methods for your LCE in a separate Class. While your application refers to the Class with the interface, when it comes time to execute your LCE's code, COM+ will load the Class module with the code and execute it.

LCEs separate the code from the interface for a simple reason: It allows you to execute several different routines when an application calls a single LCE method. COM+ will load and execute all of the different implementations of any LCE interface. This leads to another way of using LCEs.

When you write an application, you can define an LCE and have your application call it but never write the code that will execute. Instead, other developers who want to integrate with your application can write code to be run when your application calls the methods of an LCE. When your application calls the methods of the LCE, none, one, or many components that implement that interface may execute. Using LCEs allows others to integrate their processing with your application.

Implementing an LCE interface is easy to do. First, you add another Class module to your Visual Basic project. You then add an Implements statement to the new Class module that tells Visual Basic that you want to implement your LCE interface. Since the name that I gave the Class module that defined my LCE interface was LCEComponent, this is the line I use:

Implements LCEComponent

The next step is to add the methods of the interface to the new Class module. These methods must include the name of the interface that they're to implement. To implement the UpdateShip method that I defined in the LCEComponent Class module, I'd write this code:

Public Subroutine LCEComponent_UpdateShip( _

 ByVal CustomerNumber As String, _

 ByVal OrderNumber As String)

 

End Sub

Finally, you add the code that implements your method to the Class module that implements the LCE interface. The name of this Class doesn't matter because your application never uses it directly (I called mine Ship1). Assuming that the code to do the shipping updates is already part of my Access application, the only thing that I needed to do is call the appropriate routines in my Access project. Sample code to load Access, open an MDB file, and call a subroutine in the project would look like this (you'll need to add Access to your Visual Basic project's References list to make this work):

Dim acc As Access.Application

Set acc = New Access.Application

acc.OpenCurrentDatabase "LCEDemo.MDB"

acc.Run LCEDemo.PurchaseUpdate _

      CustomerNumber, OrderNumber

acc.CloseCurrentDatabase

acc.Quit

Set acc = Nothing

The two parts of the application are now de-coupled. The front end of the application will call the UpdateShip method of the LCEComponent, passing whatever information is required. Sometime after that, all of the Class modules that implement the LCE interface will be loaded into memory and executed. The sample code that calls the PurchaseUpdate routine in the LCEDemo method will then execute the back end of the database, using the information passed from the front end.

Setting up an LCE

All through this article, I've been telling you that an LCE component looks exactly like a standard Visual Basic object. And it does—to the programmer. However, to make the component an LCE, it must be set up in Windows 2000 Component Services. It's the process of setting the component up in Component Services that converts a standard ActiveX DLL into an LCE.

To begin, select Start | Programs | Administrative Tools | Component Services. Expand Component Services to see the Computers folder, expand the Computers folder to see My Computer, and then expand that item to see the COM+ Applications folder (see Figure 1). Right-click on the COM+ Applications folder and select New | Application to start creating a COM+ application for your LCE. Just click the Next button in the Wizard that appears, select Create an Empty Application on the second screen, and give your application a name.

200101_pv1 Figure 1

After your application is created, right-click on the Components folder that it will contain and select New | Component. The Wizard that appears will walk you through the process of adding your LCE to the application. After clicking on the Next button, the second form in the Wizard will offer you three choices. Selecting "Install new event class(es)" lets you set up an LCE. Clicking on that button brings up the screen that will let you add DLLs to your application. Since I had a single DLL that contained both my interface definition and my implementation, I only needed to add it. In Figure 2, you can see the result of adding the DLL I've described here.

200101_pv2 Figure 2

After your component has been added, you'll see entries for your interface class and for the classes that implemented your interface. You can expand the interface class to reveal a Subscriptions folder, where you'll specify which objects to execute when some application calls your LCE interface. To assign components to the interface, right-click on the interface object's Subscriptions folder and select New | Subscription. This final Wizard will let you first select the LCE interface and then select all of the components to be run when the interface is called. With that, your application is ready to run asynchronously.

The benefits of de-coupling the parts of your application can be valuable. Even if you don't want to implement your LCE, just calling an LCE in your application can allow others to integrate their processing with your application. And, as you've seen, thanks to COM+ and Windows 2000, making it all happen is simple.

Download is called 101VOGEL.zip is stored in the Silver Collection on this page