Scott Hernandez
Vertigo Software, Inc.
November 1999
Summary: This article describes how the Fitch & Mather Stocks 2000 (FMStocks 2000) core components were ported from the original FMStocks 1.0 code, while explaining how and why new technologies were added to these components. (9 printed pages)
What Is the Core of Fitch & Mather Stocks 2000?
Migrating to Windows 2000
Using the COM+ Services 1.0 Type Library
Implementing IObjectConstruct
Redesigning the Core for Future Development
Using the Server Script Object Tag
Summary
About the Author
For More Information
The core components were created for the original FM Stocks 1.0 sample. Core components include the FMStocks Business Logic and data access layers.
Important This article assumes the reader is familiar with the FMStocks 1.0 architecture. Complete documentation for Fitch & Mather Stocks 1.0 can be found at “Fitch & Mather Stocks: Start Here.”
In the following discussion, you will see a comparison between FMStocks 1.0 and the core components of FMStocks 2000. There are very few differences in the core components.
The FMStocks 2000 core components contain all of the services necessary for the core Web application. In later articles, we will address how we use these core services to quickly add new features to our application. In particular, we will be able to reuse our general data access component so that future SQL-based data access layers need not reimplement their own solutions. For more information on this topic, you can skip to Redesigning the Core for Future Development.
Note asterisks (*) in the table below indicate elements that are new or changed for FMStocks 2000.
FMStocks 2000 Core areas |
FMStocks 1.0 | FMStocks 2000 |
Presentation Tier | ASP Pages | ASP Pages* (New style and color scheme.) ISAPI Security Filter* (See other articles.) |
Middle Tier(s): Business Logic | FMStocks_Bus.Account FMStocks_Bus.Broker FMStocks_Bus.Ticker FMStocks_Bus.Version |
FMStocks_Bus.Account FMStocks_Bus.Broker FMStocks_Bus.Ticker FMStocks_Bus.Version* (Additional Methods) New Components for Store* |
Data Access Layer | FMStocks_DB.Account FMStocks_DB.Broker FMStocks_DB.Positions FMStocks_DB.Ticker FMStocks_DB.Tx FMStocks_DB.TxNew FMStocks_DB.Version |
FMStocks_DB.Account FMStocks_DB.Broker FMStocks_DB.Positions FMStocks_DB.Ticker FMStocks_DB.Tx FMStocks_DB.TxNew FMStocks_DB.Version FMStocks_DB.DBHelper* (Replaces functionality from shared database.bas.) New Components for Store* |
Database Tier | 19 Stored Procedures
7 Tables |
30 Stored Procedures* (11 new for Store Shopping Cart.) 10 Tables* |
External Services* | None | Office 2000 Clients
Offline Analysis Tool Windows® CE Client FMStocks Store |
One of our primary goals for migrating FMStocks from Windows NT® 4.0 to Windows 2000 was to create documentation and sample code to be used as a guide. It was important to find out if the FMStocks 1.0 binaries would run on Windows 2000 as they did on Windows NT 4.0. We installed FMStocks 1.0 binaries on a Windows 2000 Server with RC1. We started testing the application and found that everything worked, without any changes.
We started to read the SDK notes for COM+, Windows NT and ADO to see if there were any concerns or suggestions to note. We found a few good suggestions and comments.
The New keyword now supports the current object context to flow other components. In our components, we changed the way we created other components to the following form:
‘ Create the ADO objects
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Set rs = New ADODB.Recordset
Set cmd = New ADODB.Command
Note If you Dim the object as New, the Microsoft Visual Basic® compiler wraps each use of the object with a conditional statement. However, dimensioning and creating the object on two different lines removes this ambiguity from the compile.
When writing components that are located and operate in MTS, now COM+, use ObjectControl’s Active and Deactivate events to indicate when to create and destroy class-level variables, and objects. In Visual Basic, the Class_Initialize procedure is called for each class when the class is created. The Class_Terminate performs a similar function prior to the destruction of the class or component. These functions are similar to the concept of constructors and destructors in nature, but you cannot pass variables during these class events. These class events are called before, and after, the ObjectControl events, corresponding the event.
One of the key advantages for using the ObjectControl events is the ability to monitor when you are in a COM+ application. In the ObjectControl_Activate event, you can get an object context, and the Security Context, for the lifetime of your object. It is suggested that in your ObjectControl_Activate you reference GetObjectContext to store for later use.
Below is an example of the way to test this:
Private Sub Class_Initialize()
PriDebugPrint “Class Initialize”
End Sub
Private Sub ObjectControl_Activate()
PriDebugPrint “ObjectControl Activate”
End Sub
Private Sub ObjectControl_Deactivate()
PriDebugPrint “ObjectControl Deactivate”
End Sub
Private Sub Class_Terminate()
PriDebugPrint “Class Terminate”
End Sub
Debug Results:
Class Initialize
ObjectControl Activate
ObjectControl Deactivate
Class Terminate
Note Visual Basic components cannot be object pooled by COM+ because of the Threading Model, Single Threaded Apartment (STA). The result from the ObjectControl_CanBePooled function is ignored because of this.
For more information about current issues with Class_Initialize see the Microsoft Knowledge Base article Q170156.
The COM+ Type library includes all of the functionality that was in the MTS Type Library while adding many new features such as Queued Components (QC), the Object Construction String, more COM+ Security Objects, and Loosely Coupled Events (LCE). It is the only type library you need to include as you work with these technologies.
Note The COM+ Type Library replaces the MTS Type Library. In fact, the COM+ Type Library CLSID is the same as that of the MTS Type Library. However, once you start developing for a COM+ application using any new COM+ Service, there is no easy way to move the code back to Windows NT 4.0.
IObjectConstruct is a useful interface that COM+ supplies. It allows an administrator to pass a string to components every time they are created. This general feature allows us to remove the FMStocks 1.0 requirement of hard-coding the database connection string and having it passed to the Web application at run time. With the IObjectConstruct interface, the system administrator can configure deployment settings. In fact, the connection string can be changed while the COM+ application is running.
Let’s look at how we implemented our new data access layer helper class to take advantage of this new feature. FMStocks 1.0 uses a function in a module called DATABASE.BAS to hold the database connection string (GetConnectionString()). This solution works fine, but it requires that we rebuild the component if we want to change the connection string. Rebuilding the component makes it less than easy to reconfigure the location of the database at design time.
While developing this function, we tried getting the connection string from the registry, from the Shared Property Manager of our MTS Package, from the calling component (that is, ASP, or the business logic), and even from a configuration file. The IObjectConstruct interface has as a property that solves this problem elegantly for us. The administrative interface that sets the constructor string is shown in Figure 1.
Figure 1. Configuring the constructor string
To help us get multiple parameters from the construction string, we wrote a simple string parser. We chose to use a simple Comma Separated Value (CSV) list with key-value pairs. The code below shows the implementation of IObjectConstruct_Construct for our DBHelper class.
Private Sub IObjectConstruct_Construct(ByVal pCtorObj As Object)
‘eval construction string and find out what the admin wants us to do
Dim arrParams, x As Integer
arrParams = Split(pCtorObj.ConstructString, “,”)
For x = LBound(arrParams) To UBound(arrParams)
Select Case UCase(GetKey(arrParams(x)))
‘should we use a new Connection String?
Case UCase(“ConnectionString”)
m_ConnectionString = GetValue(arrParams(x))
Case UCase(“Server”)
m_DBServer = GetValue(arrParams(x))
End Select
Next
End Sub
Additional places we could have used Object Construction Parameters:
Place | Purpose |
Creating a new account | Set the new balance. |
Placing a trade | Set the commission. |
Disable trading | Shut down trading, but allow portfolio viewing. |
During our architecture review for FMStocks 1.0, we listed the services that we could reuse in future development. The list looked something like this:
Tier | Object(s) | Use |
Presentation (ASP) | Template.asp | This page includes all of the Server-Side Includes (SSI) that we need for any new pages to fit in our Web sites’ general look and feel. |
Business Logic | Account.* | The Account object gives us the ability to Verify a user’s identity, show account balances, and view their current positions. |
Data Access | Account.* | Used by Business Logic. |
Data Access | DBHelper.bas | This object encompasses the functions used to directly access the data provider. |
Database | Accounts Table | Used by components. |
Database | Various Stored Procedures | Used by components for data access. |
FMStocks 1.0 was developed to make a good base for extending. We wanted to create a complete Windows DNA application that could be easily and quickly replicated by developers. We took a hard look after the code was released for any simplification opportunities.
In FMStocks 1.0, we created our objects from ASP by calling Server.CreateObject(). We were very careful to use this function instead of the global CreateObject() call. Server.CreateObject() allowed ASP to instantiate an object whose object context and transaction context could be passed to the new object. It allowed for the object context to flow to any object created on that page.
In FMStocks 2000, we created objects using the HTML object tag. This allows the ASP Script engine to manage when the objects are created and destroyed. It also lets us take advantage of a new error handling feature in Internet Information Server (IIS) 5.0. The new error handling feature allows us to call a central page with any untrapped errors. In our case, if an object isn’t installed on the server, we can catch that error and display a user-friendly and consistent error message indicating that the site is under repair.
Another benefit of object tags: Because we put all of the object tags at the top of the page, it is very easy to open an ASP page and immediately tell which objects are being used.
Note These are server object tags, not to be confused with client object tags.
‘ OBJECT tag example:
‘ Create an ADODB.Connection Object when needed
<OBJECT RUNAT=server PROGID=ADODB.Connection id=conn> </OBJECT>
When ASP encounters an object tag, the object isn’t actually created at that time. The object isn’t actually instantiated until the first method, or property, is called. If you never call the object, then it will never be created. Since you don’t need to manually destroy it, you will always have a valid object for the scope of the page. You will not get an error like “object doesn’t exist” if you use server object tags. This also helps by eliminating the need to create objects that may never be called. Object creation is one of the most costly operations; it is one of the reasons why we use a COM+ Application. Each time we can cut out an unnecessary object creation, we should do it.
Note If you attempt to destroy an object created with the object tag you generate an ASP preprocessor error. ASP will not let you set any object created with the object tag equal to nothing.
While porting FMStocks 1.0 to Windows 2000 and COM+, we learned some important lessons. This article, along with others in this series, is here to guide you to a smooth migration from Windows NT 4.0 and Windows 9.x development into Windows 2000. The lessons we learned are:
Scott Hernandez is a Senior Software Developer at Vertigo Software, Inc. As an MVP, he can be found roaming the Microsoft development newsgroups.
He and other Vertigo developers on FMStocks can be reached at fmstsocks@vertigosoftware.com or on the Web at http://www.vertigosoftware.com/.