|
|
|
|
KB011: Introduction to COM+Topic: Visual FoxPro, Windows 2000Last updated: May 10, 2001Note: Originally presented at the Great Lakes Great Database Workshop 2000. Review of n-tier solutions, COM, and MTSFor many years, we’ve heard about the importance of breaking applications in multiple tiers or services. By splitting the User Interface, Business Rules and Database access, we can easily modify or completely replace one service without affecting the others. Historically, Visual FoxPro applications have been single-tier solutions, even if the data resides on the server. This is because developers have mixed the UI, Business Rules, and data access into one application or even the same form. With the use of SQL Server, we move to a two-tier scenario. The data is normally accessed via ODBC by the use of Remote Views or SQL Pass Through. Stored Procedures are often called on the server and the SQL SELECT statement is resolved before sending any data across the wire. In recent years, limitations of the two-tier, ODBC approach have been a problem for applications with hundreds or thousands of users. The Internet has somewhat solved some of these problems because each user doesn’t maintain a constant connection to the data. However, business rules are still often mixed with the data. In a three-tier solution, the User Interface only displays data and accepts input from the user. There may be some minor data validation, such as ensuring that required fields are populated or limiting the user’s selection via a list box. However, all the actual processing of the data takes place in a separate component that holds all the business rules. Calculations of totals or taxes, validation of data, or the generating of report data are examples of things that occur in the middle-tier business logic. Finally, the data tier is responsible for the reading and writing of data to the data store. The User Interface should never directly access the Data Services, but should go through the Business Services layer to get at the data. This separating of multiple services is what Microsoft calls the Distributed interNetork Architecture, or DNA. The different components of each service can reside on the same or multiple computers, but typically the User Interface resides on the client computer, while the Business and data components reside on an Application Server with the data store on a second server. The way to access these components is via the Component Object Model. COM is a specification that allows components written in different languages to interact with each other. So, we can create a component in VFP that can be accessed from a VB or Delphi application or even from Word or Excel. ActiveX controls are another example of a COM component. When creating a COM component, you need to determine if it should run in-process or out-of-process. An in-process component is compiled as a DLL. It must be hosted by an executable program and runs in its host’s memory space, hence the name in-process, which makes instantiating (running) the component fast. Data is marshaled (passed) across the COM boundary, which is fast. Because the component runs in the same memory space as the application, if the component crashes, it most likely will cause the application to crash too. An out-of-process server is compiled as an EXE. When instantiated, there is some overhead required, such as allocation of memory, process id, etc. This all takes time, which makes instantiation slower than an in-proc server. Also, it takes longer to marshal data across the process boundaries from the application to the component, so it runs slower. However, because the COM server is running in a different memory space than the client application, if the component crashes, the application will quite possibly stay running. Creating a COM component in VFP is quite easy. The OLEPUBLIC keyword tells VFP to compile the code with the proper COM information needed for access from other applications.
When you build the application, you can choose “Win32 executable / COM server (exe)” to create an out-of-process server. To build an in-process server, select either “Single-threaded COM server (dll)” or “Multi-threaded COM server (dll)”. We'll talk about the difference between the two types of DLLs later. After you build your component, you call it using the CreateObject() function.
When you start deploying your COM components on remote servers, you’ll need to access them via DCOM. The D stands for Distributed. Under pure DCOM, you’ll distribute an out-of-process server and setup the calling information on the client computer. Chapter 16 of the VFP “Programmer’s Guide” goes into detail about how to do this. When you install the component on a remote server, the code runs on the server, not on the client workstation. Don’t have any UI in your server because it will display on the server, not the client workstation. Microsoft saw the need for a better way for remote components to run, so they created Microsoft Transaction Server (MTS). MTS solved a number of problems by providing a host for COM DLLs. It also provided a wizard to export an install package for the client that will setup all the DCOM calls for you. Some of the other features of MTS include:
Creating components for use under MTS requires that you think differently about your application design. First, your application should be stateless. This means that your client program should instantiate the component, make calls to a method, and then release the component. The connection to the component should be as short as possible. You should also avoid setting properties. All data should be passed via parameters to the method. You also need to think about threading. We typically think of threading as single or multithreading. VFP creates single-threaded applications. This is like going to the grocery store and only having one check-out stand open. All customers must go through the same line (some would say this is reality <g>). Multi-threading allows your application to split processing into different pieces, all running simultaneously. Using the grocery store example, you can unload parts of your shopping cart into different lines and have all your groceries rung up at the same time. MTS uses a third type of threading, Apartment Model. Again using our grocery store example, customers may choose any open check-out stand, but once you’ve chosen one, you always have to use the same one. Luckily, MTS will open a new line for us when all are used. So, how do we make use of MTS in our VFP components? First, we have to add some code.
The context object contains information about our particular instance of our COM component. Also, note the call to SetComplete(). If we need to abort the transaction, we would call SetAbort() instead. When we build our component, we can’t use “Win32 executable / COM server (exe)”. MTS requires that components be DLLs. That leaves us two choices, single or mult-threaded DLLs. The single-threaded DLL is a good choice when the method call will be very fast or with the possibility that only one user will hit it at the same time. The multi-threaded DLL is not truly multi-threaded. It is apartment-model threaded. Make this choice when the method call is slow or many users will simultaneously call your component. Once you’ve built your component, you install it on the server along with the appropriate VFP runtime libraries. Then, you create an MTS package and import your component using the MTS Explorer. Windows 2000Earlier this year, Microsoft introduced Window 2000. With it came several new services. One of those services is COM+. Basically, COM+ is the next generation of COM. It is also the marrying of COM and MTS. Under Windows NT, MTS ran on top of the operating system. Under Windows 2000, it is integrated into the OS. COM+ not only includes all the features of MTS, it enhances them. There are also new services: Queued Components (QC), Loosely Couple Events (LCE), Object Pooling, and Dynamic Load Balancing. COM+ is only available in Windows 2000. However, Windows 95, 98, Me and NT clients can make use of COM+ components running on a Windows 2000 server. Before getting into COM+ services, we need to discuss some new features in VFP 7.0. These features are required to make use of some of the new COM+ services. The first thing we need to discuss is interface inheritance. VFP has had implementation inheritance since Version 3.0. Under implementation inheritance, the code (or the implementation) in the parent class in inherited by the subclass. Under interface inheritance, only the public interface is inherited. The interface is the methods, parameters, and properties that are available or exposed to the client or subclass. You don’t put any code in the parent class. All the code goes into the subclass. Second, we need to discuss binding. VFP currently uses only late binding. This means that when you instantiate a COM Server, VFP will look up the component information (it’s GUID, method, properties, etc) in the system registry at runtime. Under early binding, all this information is looked up at compile time and built into the executable. COM+ Applications are administered through the Component Services Manager. You’ll find it in the Administrative Tools group in Windows Control Panel. What were called Packages under MTS is now called COM+ Applications.
SecurityCOM+ uses Role-based security, based on Windows 2000 users and groups. A role is a type of user. For example, in a bank, you have tellers, managers, loan officers, etc. Each of these users is in a different role.
You assign the security role to your component using the Component Services Manager. This is called Declarative security. If the user or group is not a member of the role, Windows 2000 will prohibit the component from being instantiated. An error will be returned to the client.
You can also use Programmatic security. COM+ exposes a number of methods that you can call to determine if the user is in a particular role, and then branch processing based on the role. TransactionsTransactions ensure that data is written completely or not at all. Let’s take a look at an invoice. Several tables, including the Invoice Header, Invoice Detail, and Inventory tables all need to be updated. You want to ensure that either all the tables or none of them are updated. A good transaction system must comply with the ACID rule.
Under Visual FoxPro, we can use the BEGIN TRANSACTION, COMMIT/ROLLBACK commands. However, these transactions can only be used on VFP tables that are part of a VFP Database Container. What do we do if the data is on SQL Server, or even multiple servers? COM+ Transaction services can handle this for us. COM+ uses the Microsoft Distributed Transaction Coordinator (MS DTC). The DTC can handle transactions to multiple databases via a two-phase commit process. During the first phase, the DTC asks the database if it can write the data. If all the databases respond “yes”, then in phase two, the DTC tells the databases to commit the changes. If one of the databases responds “no”, then in phase two, the DTC tells the databases to rollback the changes. Keep in mind that under MTS, VFP data could not be included in the transaction. Under COM+, VFP data can be included in the transaction by using a Compensating Resource Manager (discussed later). MTS transactions also have another problem. Using the SetComplete() or SetAbort() methods, you not only committed or aborted the transaction, you also told MTS that you were done using the component. There was no easy way to do one without the other. Under COM+, you can set the Consistency bit (which handles the transaction) and the Done bit (which tells COM+ you’re finished using the component) separately. To do this, you use the new VFP 7.0 GetInterface() function, which does early binding. COM+ has new methods that set these bits:
You set the transaction support for a component using the Component Services Manager and applying one of the following:
Once you’ve set the transaction state for your component, the transaction is handled automatically for you. Typically, you’ll begin the transaction in a Business Services component by using either Requires a transaction or Requires a new transaction. The Data Services component typically Supports transactions.
Compensating Resource ManagersVisual FoxPro data can participate in COM+ transactions by the use of Compensating Resource Managers (CRM). CRMs allow you to easily be in a transaction and are supplied as a pair of COM Servers, the CRM Worker and the CRM Compensator. The CRM Worker performs the main action (for example, the Insert). Note this is phase one of the two-phase transaction. The component uses the new VFP 7.0 enhancements to the CreateObjectEx() function that allow for early binding. The CRM Compensator handles the commit or abort functions. This is phase two of the two-phase commit. The new VFP 7.0 IMPLEMENTS keyword is used to inherit the interface of another components Queued ComponentsQueued Components (QC) allow you to easily write messaging applications. Under Windows NT 4.0, you would have used Microsoft Message Queue Server (MSMQ). MSMQ has it’s own interfaces. You have to write your code specifically to handle MSMQ. Using QC, you can use the same interfaces to your components. COM+ handles the MSMQ messaging. To understand why we would use this type of a service, lets look at an example. Let’s say you go into a convenience store and purchase a candy bar. When the clerk scans the bar code on the wrapper, an inventory table needs to be updated. What happens if that table is at the corporate office across town or in another city and the connection to that office is down? You still want to buy the candy bar. Using Queued Components, this is easy. You make the call to the inventory update component as if you are connected to it. A recorder grabs your message and writes it to an MSMQ queue. MSMQ is transactional and guarantees that your data will get sent on to the server. When the connection to the server comes up, a Listener component on the server, hears the message, and then invokes a Player component to play the message to your Inventory update component. When designing your components, you have to assume that the inventory update component will succeed. You only have one-way messaging. You can only send the message – you don’t get a response. Method parameters can only be sent by value. Loosely Coupled EventsLoosely Coupled Events (LCE) moves the subscription to calls out of your components and into the Event service. Typically, when you call a component, it subscribes to the calls of the caller component. The calling component knows the name of the component it is calling and what its methods and parameters are. This is tight coupling. Under LCE, the calling component sends a message to the Event service. It then handles calling the second component. Using LCEs is easy:
There are two requirements that you need to be aware of. First, the publisher can be a COM server. You can user VFP 6.0 or 7.0 to be the publisher. The subscriber inherits the interface of the publisher. Because of this, you can’t use VFP 6.0, but interface inheritance is supported in VFP 7.0. The publishers and subscribers are setup in the Component Services Manager. Object PoolingMTS looked like it pooled objects because of Just-in-Time activation. This wasn’t really the case. With object pooling, a set number of instances of the object are kept in memory at any one time. This makes instantiation of the object faster because it never needs to be read from disk. VFP cannot participate in Object Pooling. However, you can use Visual C++. Visual Basic 7.0 will also allow you to create pooled objects. Dynamic Load BalancingUnder Dynamic Load Balancing, you can install your component on two or more servers and the one with the least load will run your component when requested. This allows for better scalability and availability. Dynamic Load Balancing is only available on Windows 2000 AppCenter Server. Exporting your COM+ ApplicationThere are two ways to export your COM+ Application. You can export the entire application to another server or you can export the proxy information for client installation. Both of these are done in the Export Wizard in the Component Services Manager. Error HandlingHandling errors is one of the most important things a developer must do. Handling errors in a COM component adds a bit of complexity. First, you should have an error method in your component. This will trigger whenever and an error condition occurs, with one exception. If an error occurs in the Init event, the Error method will not fire. In the Error method, you should include code to log the error. Finally, you should use the COMRETURNERROR( ) function to return the error message to the client application. Looking to the FutureThe future of Microsoft applications is the .Net framework. VFP 7.0 will be able to use .Net services and COM+ plays a vital role in .Net. COM+ will still handle the behind the scenes plumbing for our applications. SummaryUsing COM+ services will allow you to create applications that provide better scalability and response. Developing an application that can make use of these services is easy. Designing your components properly is vital so that you can maximize the use of COM+ services. If you need more information on COM+, you can visit http://www.microsoft.com/com or http://msdn.microsoft.com/library as well as a number of other web sites and books. |
Copyright © 2001-2005, Craig
Berntson. All Rights Reserved.
|