Anda di halaman 1dari 6

Print Article

Seite 1 von 6

Issue Date: FoxTalk August 1998

Using MTS to Create Multi-tier Client/Server Apps


Jim Falino

Automation server improvements are among the most significant of the exciting new features that have been added to Visual FoxPro 6.0. The fact that VFP automation servers now support apartment-model threading allows products like Microsoft Transaction Server (MTS) to take advantage of this new feature. In this article, Jim will take a look at how to use MTS to create multi-tier client/server applications using VFP COM servers. Doing so will add a degree of power, reusability, and scalability not previously available to the VFP developer.
As a prerequisite to this article, you should read Gary DeWitt's article, "Transactions: Tahoe and Microsoft Transaction Server," in the June 1998 FoxTalk. That article was the final of a three-part series dedicated to working with transactions in VFP, concluding with why you should employ MTS in your VFP 6 applications. In fact, the example ATM application from that issue is being used for this article as well. If you're unfamiliar with how transactions, in general, are implemented in VFP, I suggest you read that series before continuing. Sorry for all the homework, but getting yourself up to speed will enable you to get the most out of this article without me having to be redundant, or repetitive, or repeat the same thing over and over again. So, what is MTS? MTS is a middle-tier runtime service that runs under Windows NT. Its primary function is to take most of the tedious "plumbing" work that's necessary to build a multi-tier, distributed system away from the developer (see Figure 1). MTS does this by providing a -- what else -- COM interface to help simplify the creation, deployment, and administration of client/server applications. That means that you can create MTS components in much the same way that you've been creating COM servers. The difference is that you can then execute those components under the MTS environment so that you can take advantage of its services without having to code them yourself. Figure 1. MTS sits right in the middle of a three-tier client/server application. You can use VFP 6.0 for the user interface tier and/or the business object tier.

The role of MTS in a client/server application If you've already been successfully developing client/server applications in VFP, you might be wondering why you'd need a product like MTS. And those of you who haven't yet created a client/server application are probably even more inquisitive, so this is a good time to learn about one of the tools available to you. The following sections detail the roles MTS performs in a multi-tier system architecture. Component transactions You're already familiar with database transactions (like wrapping a series of TableUpdates with Begin Transaction ... End Transaction to ensure all updates either succeed or fail), but you've probably never given much thought to the concept of transacting components. What this means is that instead of transacting SQL statements, you transact COM objects (or components), with each component having an equal vote in the decision to commit a transaction. MTS coordinates and monitors the transactional state of components that are running under its control, usually while they interact with a data source.

Note!
MTS version 2.0 supports component transactions only when they communicate with a SQL Server or Oracle database. Other database vendors are expected to follow soon. VFP and Access databases aren't supported because they don't externalize distributed transactions. However, if you do need a more portable database, from what I've read about SQL Server 7, it might be just what you're looking for. (You can find an online seminar at www.microsoft.com/seminar/98/SQL7Overview/800x600/ppframe.htm.) Object brokering The MTS runtime sits on the server and fields requests for COM components from multiple clients. When a request is made, MTS creates an environment in which the component can run under and maintain information about it, like the creator, transaction data, access rights, and so forth. Next, it instantiates the object and returns a reference to the client. It will continue to maintain the instance while the client is using it, but it might actually destroy the object if the client doesn't use it for a while. (Don't worry -- MTS automatically creates a new instance when the client resumes its use of the object without the client ever

http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 05.02.06

Print Article

Seite 2 von 6

losing its reference.) The great benefit of object brokering is that it doesn't matter to the client where the objects reside; it's up to MTS to find the component and run it under its control, usually in a transaction. Resource pooling MTS can automatically pool threads and database connections. Thread pooling is necessary when you allow multiple clients to access the same component. Normally, you'd have to code the thread management, but MTS handles this for you. Database connection pooling allows your application to scale to a large number of users by enabling multiple clients to reuse a finite pool of connections to the data source. MTS coordinates the communication between the component and the data source automatically. User-definable, role-based security model MTS encourages the use of a role-based security model whereby collections of Windows NT users and groups are logically assembled into roles like Data Entry Clerk, Human Resources, and Salesperson. When a developer creates a component, he or she can do so with these roles in mind, changing the behavior of the component based on who's calling it. Since roles are applied to the package level, an MTS administrator, after reviewing the component, can define what package the component belongs to by using the Transaction Server Explorer. Administration of business tier configuration Using the Transaction Server Explorer, you can add MTS components and set their properties, specify where components will run (on the local server or another remote server), see the status of active components, and create roles for security. Transaction Server Explorer is also fully scriptable so that all functionality can be done programmatically. Benefits of using a COM business services layer If you attended this year's VFP Developers Conference in Orlando, I'm sure you made the same observations I did -component development and distributed processing using COM, DCOM, ODBC, ADO, RDS, OOP, and MTS is the future. To prove my point about distributed database development, you just need to look at the course descriptions. Of the 40 sessions, eight were dedicated specifically to development with COM, eight were about client/server development, nine were about object-oriented programming, and of the remaining 15, there were four or five that touched on these topics as well. That's 88 percent of the conference! So, if you're still writing file server applications using local tables and procedural coding techniques, you're falling behind the game. I don't mean to imply that there's not a place for these types of applications, but if you don't at least experiment with these new paradigms, you might find out the hard way that your competitor has. So you must protect yourself. A component-based, distributed, client/server application, where the presentation tier, the business logic tier, and the data source tier have each been physically (or even just logically) separated, has the following benefits:

n Language independence -- COM objects can be written in many languages, including each of the development tools n Location independence -- No code changes would be required if you decided to deploy your COM objects:
-- in the same process as the client machine (in-process DLL) -- in a separate process on the client machine (out-of-process EXE) -- on a remote machine via DCOM (used to have to be an EXE, but not with MTS) n Code reusability -- Any COM-aware client application can access the same COM business services (ASP, VFP, VB, C++, J++). So you can have multiple applications (perhaps departmental systems) sharing a single, business services layer. n Single point of administration -- You're relieved of the burden of updating every client machine when new code needs to be implemented if your components reside on a server. While it's true that your business objects can instead reside on the client, the whole idea behind MTS is to create a powerful, scalable middle tier. in Visual Studio. And components of different languages can easily co-exist in the same application.

Setting up shop MTS used to sell as a standalone product, but now it ships with Windows NT. To install the latest release of MTS -- version 2.0 -- you must install the Windows NT 4.0 Option Pack (available at www.microsoft.com/windows/downloads/contents/Products/NT4OptPk). The Option Pack contains a suite of NT services and tools like Internet Information Server, Certificate Server, Index Server, and Data Access Components (like ADO and RDS), as well as Transaction Server. This will also force you to first install Windows NT Service Pack 3 and Internet Explorer 4.01, both of which are Good Things to have. Once the Option Pack is installed, you should have a new subdirectory called \MTS beneath the directory in which you chose to install (mine is located in C:\Program Files\MTS). Find this directory in Windows Explorer and launch the file: C:\Program Files\MTS\mtxexp.msc. This is the Transaction Server Explorer: your single, graphical interface for creating, deploying, and administering MTS components. In order to follow the rest of the article, you should download the accompanying Download file . I've extracted mine to \FOXTALK\AUG 98. After you do so, see the tip, "Registering Your COM DLL," before continuing. To set up the data source, you need to do the following: 1. Ensure that the SQL Server, MTS, and MS DTC services are running by looking for SQLSERVR.EXE, MTX.EXE, and MSDTC.EXE in the NT Task Manager, respectively. 2. Ensure that the SQL Server Pubs sample database has been set up in SQL Server.

http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 05.02.06

Print Article

Seite 3 von 6

3. Be sure that there's a MTSSamples.dsn file DSN. (This is installed with MTS 2 if you install the samples.) Call SQLConnect () from VFP to test this. 4. Call the CreateAccount() function in CreateAccount.prg that's been provided. This will connect to SQL Server and create a new table "account" in the Pubs database and insert two records. Account 1 is "Checking" in my sample, and Account 2 is "Savings." Both accounts have a beginning balance of 1,000. The amount columns are integers, so you won't be able to store values to the right of the decimal point. After you've done this, you're ready to add the MTS components to the server. I'll be walking you through the install of the MTS components next.

Tip: Registering Your COM DLL


If you haven't already registered your DLL, you have two options: 1) Execute the RegSvr32 program from a DOS prompt by issuing the following: regsvr32 <full path and DLL name, including extension>; or 2) Rebuild the COM DLL using the VFP Project Manager and check Regenerate Component Ids. New NT services Before I move on, you should take note of two of the NT services that Option Pack installed. Right-click on the Windows toolbar and choose Task Manager. On the Processes tab, you should see two new services called MTX.EXE and MSDTC.EXE; these are the MTS runtime and the Distributed Transaction Coordinator (DTC), respectively. You already know about the MTS runtime, but not the DTC. MTS communicates with the DTC to ensure that resource managers like SQL Server reach a consistent decision on whether the transaction should commit or abort. The DTC is the "brains" behind MTS's ability to transact distributed components (hence, the name!). It works with MTS to enforce ACID requirements on transactions with, potentially, multiple data sources -even of different types. So, it's actually possible to commit a transaction that updates a SQL Server database and an Oracle database atomically. That's pretty cool, but a more practical example might be to use transactions to get the databases of remote offices in synch with that of the central office. Prior to MTS, it's never been easy to be absolutely positive that, for example, an insert to the central office's database and a delete to the remote office database were either both successful or failed, and subsequently committed or rolled back. Installing the Bank of Dad package If it's not already clear, the goal here is to take the COM components you've already developed in your tool of choice and install them on the server so that they can run under MTS control. You can practice this by installing Gary's Bank of Dad package, using the Transaction Server Explorer. (Again, these files are available in the accompanying Download file .) To do this, you need to know what packages and components are. Packages As you might recall, the VFPAcct DLL Gary created in the June issue has two form classes: Account and ATM. (Form classes were used because it's still the only class in VFP that can create a private data session <sigh>.) Since these two classes will most often be used in conjunction with one another, it makes sense to keep them logically grouped together. MTS encourages this type of architecture by offering many benefits to using packages: sets of functionally related components.

n All components within an MTS package execute in the same server process, which provides performance gains. n User-defined security can be established at the package level so that developers can write components with business n Packages can be easily exported for subsequent import at another site.
logic in mind and not database schema.

The Account and ATM components are perfect candidates for a package, so I'll show how to create one: 1. The first thing you need to do is click on Packages Installed in Transaction Server Explorer. Then right-click and choose New to add a new package. You're then given two options: Install a pre-built package, or Create an empty package. Choose to create an empty package; later, I'll show how to export a package for subsequent import. 2. When you click Next, you'll be prompted for a name for the Package. Call it "Bank of Dad." Click Next again, and you'll be asked to choose the NT security account for the package to run under. You can use the default, interactive user, or you can click Browse to choose an NT user or group. For our purposes, leave the default as is. After you click Finish, you should see the new package in the right pane of Transaction Server Explorer (see Figure 2). Figure 2. Transaction Server Explorer--a Snap-In to the Microsoft Management Console--is used to install packages, configure components, and administer security.

Now that you have a new package, there are a few properties that you should be aware of. Right-click on the Bank of Dad

http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 05.02.06

Print Article

Seite 4 von 6

package and choose Properties. The Server Process Shutdown property gives you the option to leave the server running while no one is accessing it, or force it to time out after a specified period of inactivity. The default -- Shut down after being idle for 3 minutes -- is fine for our test, but this could quite possibly be changed depending on your configuration and needs. The Activation tab has another interesting option. It gives you the opportunity to decide whether your component is going to run under an MTS process that the calling client created (Library Package), or in its own process (Server Package). The Utilities Package, containing internal components of MTS, is an example of a package running under the client's (in this case, MTS) process. Most of the user-defined packages that you'll create will be Server Packages, so leave this at its default. Components A component is nothing more than a COM object that can be instantiated. The ATM class of the VFPAcct DLL is an example of a component. You add components to packages by performing the following steps: 1. Right-click on the Component folder under the Bank of Dad package and choose New. (See the tip, "Registering Your COM DLL," if you haven't already done so.) 2. Choose Install New Component(s) and press the Add Files button. 3. Navigate to the location of the VFPAcct DLL and choose Open. You should now see the VFPAcct DLL in the Files to Install window. But there's a problem -- the bottom pane is empty because MTS can't find any components within the DLL. To rectify that, choose Add Files again and select the Type Library file, VFPAcct.tlb. This file contains data that helps object browsers learn about the interface that an object exposes. You should now see the Account and ATM components in the bottom pane (see Figure 3). Figure 3. The Install Component dialog box--you need to include the Type Library as well as the DLL to see the components that will be added to the package.

4. Choosing Finish will add the components to the Bank of Dad package (see Figure 4 ). Note that along with the user-defined exposed methods of each component, you can also see the methods of the IUnknown and IDispatch interfaces, which are requirements of the COM specification. Figure 4. Transaction Server Explorer with the VFPAcct DLL installed as a component of the Bank of Dad package.

After you've installed your components, you must tell MTS which transactional level your components support. To accomplish this, right-click on the Account component and choose Properties. The Transaction tab shows these four transaction level support options:

n Requires a transaction -- This setting tells MTS that the component should always run under a transaction. If the
calling object that instanced this component already started a transaction, this component will run within that transaction. If no transaction was under way when this component was instanced, a new transaction will begin. Most components will use this setting. n Requires a new transaction -- MTS will begin a new transaction when this component is created, even if the calling component has already started one. You choose this level of support when you don't want the success or failure of a child component to affect the success or failure of the called transaction. n Supports transactions -- MTS will only run this component under a transaction if its creator has already started one. Some components don't need a transaction if they're running standalone, but they do if their creator began one. n Does not support transactions -- MTS won't run this component within a transaction. You might use this if you're using MTS solely to build distribution files and/or implement a role-based security model.

Set the Account component's transaction support level to Requires a Transaction to be sure that the Deposit, Withdrawal, CheckBalance, and Post methods either start a new transaction or inherit the one begun by a creator object. Do the same for the ATM component. A simple MTS transaction That's all it takes to create packages and components. To test your work, run the Bank of Dad ATM Machine form, ATM.SCX. Choose the appropriate values to transfer $200 from the Checking account to the Savings account, and then click Submit (see Figure 5). If you've installed everything correctly, you should see the form's Transaction Results pane populated with an informative message. (If you don't, go back to the section "Setting up shop.") Figure 5. Transferring $200 from Checking to Savings using the Bank of Dad ATM Machine form.

http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 05.02.06

Print Article

Seite 5 von 6

The first time you submit a transaction, you probably won't be impressed with the speed at which it executes. On my Pentium 150 with 64M of RAM, it actually took 10 seconds to complete this very simple transaction. (Although a P150 isn't the snappiest of servers, those numbers are still unacceptable.) However, subsequent executions were almost instantaneous. After waiting three minutes -- the Server Shutdown interval we set earlier -- the transaction slowed to about four seconds. Don't get discouraged by this; there are several things to keep in mind here. First, since this is the first time I'm calling SQL Server, an ODBC connection must be established. That connection will be pooled and cached so that subsequent calls will be much faster. This occurs despite the fact that the ATM methods close the remote view, essentially disconnecting from the data source. What you also have to remember is that if these components are sitting on the application server, only the first request for the component by any client will see such poor performance. To test this, simulate another user by running the ATM form in a second session of VFP and submitting a transaction. It should perform as quickly as the first. If you want to run your own benchmarks, you can use the program ATMTest.prg. It runs the same code as the form's Submit, but without a user interface. (Actually, there's a MessageBox at the end, but just replace it with a "?" to output the results to the screen and prevent a wait state.) *-- Program: ATMTest.Prg *-- Purpose: This stub program is an example *-- of a typical ATM application. Account *-- balances are updated by MTS transactional *-- components when they're instanced and *-- passed the appropriate parameters. #Include account.h *-- Change these four variables to see their *-- effect on the checking and savings accounts. nAccount1 = ACCOUNT_CHECKING && from account nAccount2 = ACCOUNT_SAVINGS && to account nType = TYPE_TRANSFER && type of transaction nAmount = 200 && amt of the trans cMessage = "" && summary message oVFPServer = CREATEOBJECT("vfpAcct.atm") *-- Note: The Transfer method can actually do *-- all four types of bank transactions. oVFPServer.Transfer(nAccount1, nAmount, nType, ; nAccount2, @cMessage) *-- Transaction Summary MessageBox(cMessage)

If you call ATMTest.prg in a loop and, at the same time, make the Bank of Dad components in the Transaction Server Explorer visible, you can see the icons spinning. You'll notice that they stop immediately after you destroy all object references to them. This behavior is by design even when the Shutdown Server Process property is set to "Leave running when idle." The spinning icons represent current activity, not whether the component is cached by MTS. Exporting and importing packages MTS makes it very easy to take packages you've built on your development machine and deploy them on another computer. All you need to do is run the Export facility on your package, take the files MTS creates, and run the Import facility on your production application server. Exporting also creates a client installation executable that you run on each client workstation to configure them to run components with DCOM. To export the Bank of Dad package, right-click on it in Transaction Server Explorer and choose Export. In the Export Package dialog box, supply the full path of a temporary folder and a filename for the PAK file that MTS will create (I called mine VFPACCT.PAK). Click Export to start the process. When it's completed, if you check the contents of that folder in Windows Explorer, you'll see three files -- VFPACCT.DLL, VFPACCT.TLB, and VFPACCT.PAK. These files can now be used to install the Bank of Dad package on your production server. To practice importing, right-click on the Bank of Dad package and choose Delete. Then click on Packages Installed and choose New | Install Pre-built Packages. Click Add, and then find the PAK file you've just exported. Accept the rest of the defaults the wizard suggests. When you choose Finish, you should see your package installed again with all of the properties you've previously set. Pretty easy, right? You might have noticed that the Export facility also created a subdirectory called \CLIENTS that contains a file called VFPACCT.EXE. This file can be run on each client workstation to update its registry, enabling it to find the remote components. And if you want this install to be part of a larger client upgrade, you can append a "/q" parameter to a programmatic call to VFPACCT.EXE so that it runs in quiet mode -- without any dialog boxes.

Caution!
http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 05.02.06

Print Article

Seite 6 von 6

Don't run the client executable, VFPACCT.EXE, on the same machine. This is for DCOM configuration, and you obviously don't need that when you're running your client application on the same machine as your server. Benefits of using MTS By using MTS to "wrap" your business objects into one functional unit, you accomplish many things -- some more obvious than others.

n Simplified programming -- MTS takes much of the "plumbing" work out of the hands of the developer. For instance,
the MTS components you create are in-process servers, or DLLs, yet they're being deployed remotely. How can that be? Because they run in the MTS process -- giving you the central administration of DCOM, but with (almost) the speed of COM. Code reusability -- Transactional components can all be written the same way and then used interchangeably. All they need to do is start an MTS transaction, perform their function, and then SetComplete or SetAbort. Centralized administration -- Transaction Server Explorer administers components during both development and deployment, as I've already shown. Scalability -- MTS helps applications scale much higher due to "statelessness" of components. Have you noticed that all methods start a transaction and then either commit or abort it? That means each component performs its role and then cleans up after itself -- leaving no data sessions, tables, cursors, or variables alive. This cuts down on server resources like database connections and leaves the components on the server available to other users. Resource pooling -- MTS components execute very efficiently because the MTS components and connections are pooled by the server: -- Component pooling -- MTS keeps your components in memory even after you've committed or aborted. That way, subsequent calls will be much faster while at the same time allowing you to keep your component stateless. -- Connection pooling -- Every method in which you need access to the data source can start a new connection without the penalty we've always been told connections cause. That's because MTS actually retains your connection information, even though in code you've disconnected. That way, your component doesn't have to worry about maintaining data (again, remaining stateless), yet you benefit by a speedy second and subsequent calls to the server and by not having to use too many resource-intensive, expensive connections.

n n n

Known issues There's one issue with MTS's integration with VFP automation servers: It centers on high-volume concurrency and what it does to scalability. As of this writing, VFP 6 has yet to address the fact that calls to the same DLL from multiple clients will queue until the preceding call has completed. It's difficult to replicate in the ATM example because its methods are so short and I had no problems running the ATMTest program in a loop in multiple sessions. But if the methods did a lot of work, you'd see the other sessions wait for the first session to complete before they can execute. I thought apartment-model threading was supposed to change this behavior, but apparently it hasn't. On the whole, this product performed very well during the course of this article. I only crashed one time, and that was when I tried to Shutdown the server process when I still had an outstanding reference to it. (So, just don't do that.) Additional reading and acknowledgements To learn a lot more about MTS, there's a great book for beginners called Roger Jennings' Database Workshop: Microsoft Transaction Server 2.0, by SAMS Publishing. It's easy to follow and covers just about every feature in MTS, as well as distributed application development concepts. Also check out the MTS Web site at www.microsoft.com/transaction. I'd like to also thank Gary DeWitt for the great work he did with the ATM sample and for setting the foundation for this article; he saved me a lot of headaches. (Hey, better him than me.) Conclusion What I like most about MTS it is that it forces you to think about things like components, statelessness, sharing resources, and reusability -- all the time. Since that's not just the future of database development, but the present, it's best to learn this stuff now. And the fact that this product is, essentially, part of the NT operating system screams volumes as to its place in Microsoft's view of distributed application development. I hope I've shed some light on the use of MTS and stirred some thoughts as to what parts of your application can benefit from its services. I strongly encourage you to give serious consideration to using MTS on your next project.

http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=... 05.02.06

Anda mungkin juga menyukai