by George Cross,
Senior Technical Advisor, Borland C++/JBuilder Developer Support
with contributions by. . .
Kevin Scardina
Win32 Advisor, Borland C++ Developer Support
This arrangement has been used for some time in the practise of computing where data is stored on machines running a database management system (DBMS), typically an SQL DBMS, such as Interbase, Oracle, Sybase, MSSQL, Informix. Access and manipulation of the data is performed by applications running on client workstations. Both display logic and business logic are contained within the client application.
In order to maximize reusability of the same business logic in other client applications and to make client applications smaller, the concept of an application middle-tier evolved:
In this 3-tier model, the business logic is contained in a separate application, often running on a separate machine, accessible by multiple clients. Client applications now only contain the display logic and call to methods on the middle-tier for retrieval and manipulation of the data. The middle-tier is responsible for executing client requests and fetching data from and resolving data to the DBMS. The middle-tier should, like the DBMS, be able to service multiple clients simultaneously while maintaining synchronization and integrity of the data in coordination with the DBMS.
Applications can be embedded in HTML a number of ways:
Unlike Java applets, ActiveX controls have no such restriction. They are simply DLLs which Internet Explorer loads and executes at runtime. They have full access to the client's system and any network to which it is connected. For this reason, when you load an HTML page with an embedded ActiveX control in Internet Explorer, you are alerted as to whether you trust this control and whether you wish to continue.
Multi-tier applications are frequently deployed across the Internet. Consequently at least one firewall normally needs to be transgressed in communication between one of the tiers. Often an enterprise makes part of their corporate database and perhaps a middle-tier application available to the public over the Internet. So a corporate firewall would normally separate the client application from middle-tier and DBMS. Furthermore, if a particular user happens to be running the client application from within another corporate LAN, there would then normally be two firewalls separating the client application from the middle-tier and DBMS.
There are five common firewall configurations:
The International Standards Organization established the Open Systems Interconnection model to overcome incompatabilities between the networking schemes of different computer vendors. This standard describes the flow of data from an end-user application down to the network cable, when communicating across a network. Each layer defines specific services it provides in progressing data along to the next layer. It is intended that implementations of a particular layer be independent from implementations of its adjacent layers. This is so that in communication between two computers, the data that a layer works with is exactly the same data with which the same layer on the other computer worked.
I will discuss the Network, Transport and Session layers. The remainder can be reviewed in the Windows NT Networking Guide, from the Windows NT Resource Kit, MS Press.
In general, transport protocols in Windows provide the services of both the Network and the Transport layers. The transport protocols provide the following services.
Alternatively, since it is common that server applications can serve multiple clients simultaneously, some lookup methods provide mapping not only to a particular file on a machine, but to the process if that file has already been executed and is present in memory on the server machine.
The following is a decription of the common naming service methods.
A URL contains a protocol, machine name, domain name and file name. It has the form, for example, http://www.inprise.com/techpubs/index.html, where the request is for the file techpubs/index.html at the domain inprise.com on the machine www using HTTP protocol.
To give you an idea, here is the IDL script for the Smart Stub example which comes with the Visibroker for C++, in Borland C++Builder 3 Enterprise.
Surely there is much documentation on IDL, but I would like to mention there is a good short tutorial on CORBA IDL in the Visibroker Training material.
As shown the diagram above, DCOM is implemented on RPC. This is Microsoft's implementation based on the OSF DCE standard. The RPC in Windows is completely interoperable with RPC on HP's Unix, IBM's AIX® and any other DCE RPC facilities . The RPC in Windows can conveniently operate over several transport protocols: NetBIOS, Sockets, or named pipes. You can see that DCOM extends COM - an architecture and facility for objects communicating on the same machine. This aspect of DCOM facilitates simple conversion of a COM application to an application distributed across the network.
DCOM communication operates roughly as follows:
Similarily automation server applications can provide single or multiple use objects. An automation server can instantiate a new instance of an automation object for each controller, or it can create one instance of an object and instruct DCOM to supply that instance to all controllers which invoke the object.
CORBA is a standard developed by the the Object Management Group, a standards consortium comprised of representatives from a host of industry participants. For ORBs like Visibroker's, which are fully CORBA 2.0 compiliant, registered CORBA 2.0 compiliant objects are fully accessible regardless of the tool with which they were built. CORBA is consequently platform independent as well.
As shown in the diagram above, CORBA uses IIOP as the session protocol, as per OMG specification. IIOP itself was also developed by the OMG as part of the CORBA specification. (The Visibroker ORB uses TCP/IP as the transport protocol for IIOP.)
CORBA communication operates roughly as follows:
These are all a one needs to develop a multi-tier application using Midas. The Midas product by itself is what you would need when you actually proceed to deploy your application. Aside from the same components and utilities which come with C++Builder C/S and Delphi C/S, Midas includes a runtime install program and runtime licences needed for applications which use the Midas components. If you only want to develop and test an application built with Midas, C++Builder C/S or Delphi C/S is all you would need. C++Builder 3 Enterprise included the runtime install and licences for Midas.
C++Builder 3 ships with the full Microsoft Active Template Library. You will find the classes for this library collected entirely in the directory include\atl. They are predominantly header files as the classes are predominantly C++ template classes. If templates are new to you, you might want to review them in Stroustroupe [1997].
The ATL has been designed for compactness and efficiency of execution. Being written using C++ templates, code is generated at compile time based only upon the interfaces you request. This eliminates the predicament prevalent with other class libraries where your COM server ends up carrying about superfluous code. This is precipitated by the class library having been written with aspirations of being all things for all projects. By using the ATL you can be assured that standard implementations you might be using have been well designed by OLE experts, offering you the assurance your OLE code will be procedurally optimized.
The Automation Object requires you have a project open already. The idea is that you can start with any application you have already developed and expose its functionality to other applications using COM. Once you have done that, providing access to other applications across the network is simply a matter of configuring DCOM using the Windows administration tools.
The Type Library Editor provides a graphical user interface as an alternative to typing IDL statements in a text file. Using the Type Library Editor, you describe the automation object you wish to expose. The terminology for this is, defining the interface. You describe methods and properties that your object will offer. Instead of generating a text file containing IDL statements which you would then have to compile yourself in order to generate the C++ declarations, the Type Library Editor performs this step for you. It also generates a .tlb file which is a binary representation of your automation interface that is used by controllers at runtime to inspect your automation server. Both the C++ declarations and the .tlb file are generated when you click the Refresh button. The Register button will actually attempt to compile your application so that the Type Library Editor can run it with the parameter /RegServer. This will induce execution of the code which will add the type library to the Windows registry and associate it with your server application. This registration code was generated when you added an Automation Object to your application.
Upon clicking the Refresh button, the following files will be added to your projct. These are the default names.
Now we need to add the class which will act as a proxy for our automation object running in the automation server. The class is called ISampleObjectDisp and is declared and implemented in files SimpleServer_TLB.h/.cpp. To add this class to our controller project, select Project|Import Type Library and double click on SimpleServer Library.
We are by no means obligated to call BindDefault when our controller application initializes. We can call it any time.
This concludes the tutorial on creating and deploying a trivial two-tier DCOM application. Surely this can not provide a solution for enterprise applications but it will get you started in programming with DCOM. One could keep building on the steps presented here and have the server call to other automation servers and thus a create multi-tiered DCOM application. One the common objectives of multi-tiered development, however, is to have a DBMS on one of the tiers. One of the easiest ways to accomplish this is to use Midas® technology and distributed datasets.
A DCOM server specifies its threading model in its call to CoInitializeEx. However, in-process COM servers by design never calls CoInitializeEx. So the threading model for an in-process COM server is specified in the registry in the string titled ThreadingModel under the InprocServer32 key under the entry for the server's CLSID. For example:
Accordingly, ATL offers the macros:
Introduction
Many companies these days want to avail their corporate data to clients enmass. HTTP servers connected to the Internet, for example, is one common technique through which this is accomplished. The ubiquity of web browsers can account for this, as they require no deployment or configuration at the client side. Applications which execute across two or more machines are commonly termed 'Multi-tier' and DCOM and CORBA are two predominant, rapidly evolving technologies which facilitate development of such. This paper is about software development using these two technologies in Borland C++Builder 3.
Distributed Computing Fundamentals
Distributed computing in general describes the coordination of processing amongst physically distinct and geographically isolated computational units. It forms the basis of several disciplines including distributed databases, operating system clusters, transaction processing, simple networked file systems. This section discusses a few fundamentals of distributed computing pertinent to multi-tier applications in particular.
Multi-tier Scenarios
First let's look at a few common scenarios for multi-tier applications. The simplest and perhaps most common scenario is client/server:
The 3-tier model leads naturally into a multi-tier model by realising that the middle tier can easily be chained into multiple applications providing business logic executing across multiple machines.
Note:
HTML-Embedded Clients
With the advent of the web, client applications can now be simplified to be downloaded on demand and run within an HTML browser. The advantages are clear:
The first advantage, no client-side configuration, is also often gained by using a stand-alone client application deployed on a standard fileserver. Clients on the network connect to the fileserver and run the client executable directly from a shared volume. Such a solution however is not cross-platform. A different version of the application would have to be available for every different OS clients might be using. (Well, alright, DCOM isn't cross platform either, but we will return to that later). This is also not a suitable solution for WANs with a large number of public users. The time it takes to download and execute an application embedded within a browser is fractional compared to the time it would take to download and execute a Windows application with comparable features, user interface, etc. Clients simply wouldn't want to wait each time they run your client application.
Easier access == More Users == More Hits == More $$$, or at least more Advertisers calling for you to display their banner on your website.
Applets can't initiate conversations with anything but the HTTP server. Middleware like DataGateway®, GateKeeper®, or a CORBA server, can run on the HTTP server and access other server machines. If your applet is to connect directly to a machine other than the one from which it is downloaded, you have to make it trusted (which means working with signed applets and the Netscape or Microsoft security API). As depicted in the figure below, the HTML browser downloads an applet from the HTTP server. The applet is launched within the JVM of of the browser and can communicate only with the same machine running the HTTP server. A Corba server, for example, could be made available on this machine however, and it can make calls to any machine and return results to the applet.
Firewall Scenarios
A firewall is conceptual term used to describe a configuration of one or more computers and routers which act as a security mechanism for data communications between a LAN and WAN, such as the Internet.
Please see the Visibroker Training for a good discussion of these configurations. Below are some diagrams of common scenarios with firewalls and HTML embedded clients.
Transport Protocols and Session Protocols
There is often confusion between network transport protocols and session protocols. A review of the ISO's OSI model will aid in illustrating the differences.
Common transport protocols are as follows:
Other protocols which we commonly hear in multi-tier application development such as HTTP, IIOP, RPC and Sockets provide the services of the Session layer. Session protocols provide the following services.
Common session layer protocols used in multi-tier application development are:
Naming Services
At some point, a client application will leave its local machine and venture out on the network in search of a server application. Depending on the session protocol, one of several different naming and lookup methods will be used. Each constitutes the same underlying task: lookup in a simple database which maps the name of a server application to an actual file and/or process on a physical machine somewhere on the network. Some methods can resolve a name to any one of several possible machines offering redundancy or even load balancing for multiple requests of the same server application. In the figure below, the four requests for server application 'Foo' are satisfied by three different server machines which have 'Foo' available as registered in the naming service.
Load Balancing and Fail-Over Safety
Two major benefits of applications which execute across multiple machines are the opportunity to implement Load Balancing and Fail-Over Safety.
These features don't always come free for the programmer. Although the development technology which you are using might make it easier often there is some programming work to be done, contingent upon the task being implemented. This is especially true for fail-over safety.
IDL
Multi-tiered architecture is part of the movement in software engineering toward object oriented design. It is very convenient for software engineers to compliment an object oriented model with multi-tier architecture - units of functional service or requirement can be formulated into groups of objects, and those objects can be allocated to separate physical computational devices. There are many programming languages which support ojbect oriented design: C++, Java, Borland Pascal, Smalltalk, Visual Basic and of course TASM's Object Assembly.
What is object oriented design? Put all programming languages aside for a moment. Picture two connected computers, A and B. Imagine A wants to ask B to do some processing. You could imagine A calling a function on B, passing data in arguments. Now, collect several related functions and data items on B and create an object. Call the functions methods, and the data items properties. Now picture A grabbing a handle on that object, filling the object's properties with values and calling it's methods. Now express your application architecture as collections and hierarchies of objects in this fashion. This is the essence of object-oriented design. (There are three primary concepts in OOD: encapsulation, inheritance and polymorphism. An excellent source for these can be found in Calvert [1998] or Thorpe [1997])
The Open Software Foundation developed as part of their Distributed Computing Environment specification, the Interface Description Language(IDL). It is a language for describing object models independently from a programming language. Both DCOM and CORBA have adopted IDL to acheive language independence. Normally when developing an application which will use DCOM or CORBA, you will first design using objects, defining them in IDL. You will then use your esteemed development tool of choice to process your IDL script and generate declarations for your objects in the programming language you will be using. You will then proceed to implement the methods of those objects in that programming language.
The actual syntax for IDL can varies between that for DCOM and that for CORBA. The former is called MS IDL, the latter CORBA IDL. The difference is due to the differences DCOM and CORBA technologies. Borland Delphi 4 is one tool which bridges these differences somewhat in its ability to expose CORBA objects as DCOM objects.
// Smart Stub example
interface Dictionary {
typedef string KeyType;
typedef string DefinitionType;
typedef sequence
What is DCOM?
DCOM stands for Distributed Common Object Model. It defines an architecture for distributed applications and offers services about the presentation level of the OSI model described above. It is Microsoft's proprietary technology and is part of the Windows OS. There are third parties which have ported DCOM to the Unix platform, but for the most part, DCOM is used for developing Windows-only applications.
There are numerous variations on how server applications and their automation objects are instantiated. Server applications can be Single Use or Multiple Use. Single Use means DCOM will create one process of the server application per controller which wishes to use it. Multiple Use means DCOM will only create one process in total, no matter how many controllers request to instantiates object within it.What is CORBA?
CORBA stands for Common Object Request Broker Architecture. Like DCOM, CORBA also defines an architecture for distributed applications. Presentation level CORBA services, called the Object Request Broker (ORB), are part of the Visibroker products. There are other vendors besides Inprise, who provide an ORB as part of their CORBA solutions.
As with DCOM, there are numerous variations on this sequence. For example, objects which have not yet been created and are not currently loaded in memory, running and awaiting a connection, can be activated by the ORB in cooperation with an activation daemon upon request for the object by a client. Clients can also request to bind to an object on a particular machine, in a particular process, regardless of other available instances of that object elsewhere on the network.
Comparison of DCOM and CORBA
Here is a little chart exhibiting the favor of CORBA.
Cross-Platform?
Cross-Language?
DCOM
No
Yes
Corba
Yes
Yes
Java/RMI
Yes
No
Inprise Products for Multi-tier Application Development
The array of products offered by Inprise for multi-tier application development is complex such that most Inprise employees themselves are confused.
There are other products for distributed application development from Inprise including ITS®, AppCenter®, Connect for SAP®, and the AS/400 line of development tools.
The Visibroker product line is the most recent addition to Inprise offerings for multi-tiered development. The Visibroker was acquired through the merger of Borland and Visigenics, early 1998. Specifically it is the industry leading solution for CORBA development. It includes the following products,
Presently the Visibroker is available for Sun Solaris®, and Microsoft Windows®. The Visibroker ORB uses TCP/IP as the transport protocol for IIOP.
This is available separately and with C++Builder 3 Enterprise. It provides the basic CORBA 2.0 compliant ORB, an IDL to C++ compiler and a series of other runtime and diagnostic utilities. The ORB is constituted by a series of libraries to be linked to your application and a daemon called Smart Agent® which provides basic, proprietary naming service for objects. Smart Agent also provides fail-over safety and load balancing.
This is the Java complement of the C++ version. This comes with the Client/Server edition of JBuilder.
These are fully CORBA 2.0 compliant services. They come with C++Builder 3 Enterprise. They are not included with JBuilder Client/Server.
Mostly all the Midas components and utilites come with the Client/Server editions of C++Builder and Delphi: Remote DataBroker, Business ObjectBroker, ConstraintBroker.
This is a product acquired when Borland merged with Open Environment Corp. in 1996. Entera is a full featured, robust middleware product which enables you to develop fully DCE RPC compliant servers and clients. You will definitely want to consider Entera if you are doing serious RPC development and require scalable, multi-platform application servers and DBMS access. I was quite impressed by Entera when researching it for this whitepaper.
This product also came from Open Environment Corp. It is an alternative to DCOM. If you have OLEnterprise, you don't need DCOM on your system. You can take regular COM applications and distribute them easily across Win95 and WinNT machines. OLEnterprise also provides fault-tolerance and load balancing. Of course, being from Open Environment Corp, COM applications can talk to RPC servers built with Entera. OLEnterprise comes with C++Builder 3 Client/Server and has no additional fees for distribution. It is a great solution for small to mid sized distributed applcations which can benefit from the ease of deployment and additional features that DCOM fails to offer. Calvert [1998] chapter 27 has a good section, complete with code sample, on the topic of OLEnterprise.
DCOM Application Development
In this section we will first give a brief overview of developing a DCOM applicaion. Next we will do a quick step through developing and deploying a trivial DCOM application. Finally we will discuss Borland's Midas technology and how it uses DCOM to provide real-world solutions for Inprise customers.DCOM Application Framework in C++Builder 3
With C++Builder 3, developers have more choices than ever before. OCF and MFC are both included with the product. In addition, the C++Builder 3 Object Repository has sevaral wizards, ActiveX Control, ActiveForm, Automation Object and several other templates for COM and ActiveX development. These items make use of both the Visual Component Library (VCL) for windowing support and the Microsoft Active Template Library (ATL) for OLE support. The two libraries are connected by a couple of classes known as ATLVCL. The ATLVCL classes are packaged in the following files.
The advantages of this powerful combination are lightweight, web-enabled OLE support coupled with the RAD functionality of the VCL. It also allows us to leverage our existing VCL code base and with but a few clicks of the wizard, expose it as an ActiveX control or Automation Object.
Overview of Developing a DCOM Application in C++Builder 3
When developing a DCOM application in C++Builder, you will use the Automation Object from the Object Repository. You open the Object Repository using File|New and selecting the ActiveX property page.
Automation Object in the Object Repository is not the only alternative for developing COM servers in C++Builder 3. It is the fastest. You are perfectly at liberty to use any of ATL, MFC, OCF or the OLE API, all of which come with BCB3. For a more complete discussion of these frameworks and their history in the Borland C++ product line, please refer to chapter 28 in Calvert [1998].
When you create a new Automation Object, you are first prompted for the name you would like to give to the object, and then the Type Library Editor appears.
A Simple DCOM Server in C++Builder 3
private:
long intdata;
WideString strdata;
Do so by right clicking in the .cpp file and selecting Open Source/Hdr. Add the declarations to the class TSampleObjectImpl.
WideString is inherited from Delphi's WideString, and is simply a wrapper for BSTRs, which are used often in COM for passing strings. BSTRs are simply wchar_t pointers (wchar_t*) which have the length of the string stored two bytes before the address pointed to by the wchar_t*. In order to take a regular character string pointed to by a char*, simply call MultiByteToWideChar, followed by SysAllocString. Voila, you will have your original string in a BSTR. When you want to free up the memory pointed to by the BSTR, simply call SysFreeString. In our TSampleObjectImpl class, we could easily use a straight BSTR and call the OLE API functions just mentioned to initialize it ourselves. But the WideString class saves us code statements by doing it for us. We could also use the CComBSTR class, which is part of the ATL. With C++Builder 3, you have many options!
*Value = intdata;
if ((static_cast
Notice we use WideString's overloaded BSTR cast operator to check if strdata is null. If it is not, we copy the pointer value contained in the WideString, strdata, to the memory location pointed to by Value. If it is null, we throw a C++ exception.
intdata = Value;
strdata = Value;
char buf[128];
wsprintf(buf,
"The values are: \n\t intdata=%ld \n\t strdata=%ls",
intdata,
strdata.c_bstr());
MessageBox(NULL, buf, "SimpleServer::ShowProperties", MB_OK);
Here we simply stream the values of intdata and strdata into a message string which we display in a Windows message box. We have to pass the wchar_t* returned by c_bstr() since the variable parameter list of wsprintf will not invoke the BSTR conversion operator of our WideString, strdata.
A Simple DCOM Client in C++Builder 3
Now we can build the trivial DCOM controller application which will invoke our trivial automation server. The controller will set and get both properties NumericValue and StringValue, and invoke the ShowProperties method. We will create the controller application as project within our SimpleDCOM project group.
#include "SimpleServer_Project_TLB.h"
private: // User declarations
ISampleObjectDisp* pSO;
pSO = new ISampleObjectDisp();
pSO->BindDefault();
This is the code which will instantiate a proxy object for us. The ensuing call to BindDefault() actually makes the DCOM request to launch the automation server and invoke the automation object, storing a reference to it in the proxy object.
delete pSO;
Label1->Caption = pSO->NumericValue;
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Label1->Caption = pSO->NumericValue;
}
//---------------------------------------------------------
void __fastcall TForm2::FormDestroy(TObject *Sender)
{
delete pSO;
}
//--------------------------------------------------------
void __fastcall TForm2::Button2Click(TObject *Sender)
{
Label2->Caption = pSO->StringValue;
}
//-------------------------------------------------------
void __fastcall TForm2::Edit1Exit(TObject *Sender)
{
pSO->NumericValue = (Edit1->Text).ToInt();
}
//------------------------------------------------------
void __fastcall TForm2::Edit2Exit(TObject *Sender)
{
pSO->StringValue = WideString(Edit2->Text).Detach();
}
//-----------------------------------------------------
void __fastcall TForm2::Button3Click(TObject *Sender)
{
pSO->ShowProperties();
}
Notice the call the WideString.Detach() when setting the value for the StringValue property. This ensures only one copy of the temporary WideString is created.Deploying SimpleDCOM
So our trivial application is working great on one machine. Now let's split up the automation server and controller. In Calvert [1998] chapter 16, expert Charlie dicusses in detail how to successfully deploy a DCOM server on a Win95 machine and how to sucessfully connect to a DCOM server from a Win95 client. For the sake of brevity and simplicity, I will describe the steps for deploying our SimpleDCOM application across WinNT 4.0 machines. Do please consider Calvert's book the autoritative source for all the nefarious Win95 - DCOM issues.
Now DCOM is configured to launch SimpleServer.exe when controllers from other machines request the services of SampleObject. As for configuring controller applications were to find their automation servers, this can be done in a two ways.
Clearly both have their advantages. The first allows the server to be relocated without recompiling the controller application. The second does not require any configuration on the client machine. Probably the best solution would be to have the SimpleClient.exe run from a shared drive on the LAN, and have it call CreateRemote() passing the server machine name as read from an .ini file. Then there would be no configuration on the client side, and the administrator would only have to update the one .ini file on the single copy of the SimpleClient application which exists on the shared drive.
DCOM Threading Models
The ATL supports the concept of COM thread models. A thread model ascertains the manner in which threads in an OLE client are permitted to make method calls on an OLE server. Specifying a thread model is required so that the methods in an OLE server may be accessed safely by concurrent threads. It is also necessary so that the overhead of concurrency management can be foregone and performance times greatly improved if only a single thread is in the scenario.
HKEY_CLASSES_ROOT
CLSID
{8b3dea42-77dd-f9f9-8d48-000032ccad71}
InprocServer32
ThreadingModel="Apartment"
Don Box really has some great articles in Microsoft Systems Journal which discuss thread models in detail, but in a nutshell, there are four:
For maximum efficiency, both client and server should employ compatible threading models. If they are not, for example a client running in MTA invoking an Apartment threaded server, DCOM will impose marshalling and performance could be crippled by several hundred factors.
_ATL_SINGLE_THREADED
_ATL_APARTMENT_THREADED
_ATL_FREE_THREADED
ATLVCL does not support the Free threading model, and uses the Apartment model by default. Microsoft documentation recommends the Apartment model and it is quite evident their perspective is from that of Internet Explorer being the client. Webpages which host ActiveX controls will be fastest if no DCOM marshalling be imposed and no concurrency management be necessitated.
Using DCOM in Midas® Technology
In Calvert [1998], Charlie shows how to create distributed datasets both with and without the Midas components. Time permitting, we will step through creating distributed datasets without Midas in the live presentation. Although the Midas components are part of the Client/Server edition of C++Builder 3, the licences which must be procured from Inprise in order to deploy your completed application might be considered costly. Such would be the case if the developer was willing to implement and manage the significantly larger code base required if the power of Midas is forgone. In most enterprise development however, the power and flexibility of Midas would be well worth the distribution licences.
The combination of C++ Builder 3 and Visibroker allows programs to create scalable cross platform business solutions. This article goes though the steps one would take when creating a CORBA application in the C++ Builder 3.0 environment using Visibroker's tools and libraries. To illustrate the steps I have chosen to write a simple Fortune Teller application. The client queries the server though CORBA to get the users Fortune for the day.
This paper is divided into three major sections:
//file fortune.idl
interface Fortune{
void GetFortune (out string msg);
};
The IDL keyword interface is used to tell the IDL compiler that this is the objects interface. Then the functions that this interface is going to use are specified. In this example there is only one member function for our Fortune interface, GetFortune. This function is going to pass in a buffer that the function will fill, that is why the IDL keyword out is placed in front of the parameter. If the function took in a parameter that would only be used by the function and not used as a result, the IDL keyword in would be placed in front of the parameter. Furthermore, if the function took in a parameter that was going to both be used by the function and used to return a value the keyword inout would be placed in front of the parameter.
Once the IDL file is written it needs to be compiled into the skeleton and stub using the Visibroker tool idl2cpp. The best way to do this is to create a batch file that will run idl2cpp on the IDL file with the correct flags for C++ Builder. Place this batch file as the first node in a ProjectGroup. Here are the steps to do this in a BCB 3 project.
interface Fortune{ void GetFortune (out string msg); };
If the files are not created, try running the .bat file from the command prompt. Be sure vbroker\bin is in the system path and that the current default directory is the same one as where the .idl file. You can select File|Open, browse to the directory of the .idl file, then press Cancel to ensure this.
NOTE: ORB.DLL is the single threaded version of the Visibroker ORB. ORB_R.DLL is the multi-threaded version. ORB.LIB and ORB_R.LIB are their respective import libraries.
#includeclass FortuneImpl: public _sk_Fortune{ void GetFortune(char*& _msg); };
#include "FortuneImpl.h" char* fortunes[] = { "Your love life will improve in the next 10 days.", "Take a chance with a new lover.", "Death of someone close is near in your future.", "You will be successful at anything you do.", "Watch out for wolves in sheeps clothing.", "Don't forget to stop and smell the roses", "If you stop to think, don't forget to start again." "You will have a good day.", }; void FortuneImpl::GetFortune(char*& _msg) { int n; randomize(); n=rand()%8; _msg=CORBA::string_dup(fortunes[n]); }
Select File|New Unit from the menu. Save the unit as FortuneThread.cpp/.h. Now add the following class declaration in the header file.
class FortuneThread : public TThread { public: FortuneThread (bool inactive = false) : TThread (inactive) {} void __fastcall Execute (void); };
NOTE:You might want to be careful when using the TThread class and stateful functions of the C RTL. We noticed TThread merely calls Win32 APICreateThread
. The C RTL is henceforthe not initialized as_beginthreadNT
would do. So, if you are going to be using stateful C RTL functions likestrtok
, be sure not to use TThread, but some method which calls_beginthreadNT
instead. Please see system.pas in the VCL source to verify this for yourself if you would like.
#include "FortuneThread.h" #include "FortuneImpl.h" #include "FortuneServerMainForm.h" extern TForm1* Form1; int foo; char* const * bar; void __fastcall FortuneThread :: Execute (void){ try{ CORBA::ORB_ptr orb = CORBA::ORB_init (foo, bar); //initialize the ORB Form1->Memo1->Lines->Add ("Object Request Broker Initialized"); CORBA::BOA_ptr boa = orb->BOA_init (foo, bar); //initialize the BOA Form1->Memo1->Lines->Add ("Basic Object Adaptor Initialized"); //create a new fortune object FortuneImpl fortune ("ft"); //Export the new object boa->obj_is_ready (&fortune); Form1->Memo1->Lines->Add ("Object created and exported"); Form1->Memo1->Lines->Add ("Object is ready!!"); //wait for incoming requests boa->impl_is_ready(); } catch (const CORBA::Exception &e){ ShowMessage (String (e._name()) + ": " + String (e._repository_id ())); } }
void __fastcall TForm1::Button1Click(TObject *Sender) { new FortuneThread (false); }
try{ CORBA::ORB_ptr orb= CORBA::ORB_init(foo, bar); Fortune_var fortune = Fortune::_bind(); char* pszFortune; fortune->GetFortune(pszFortune); Memo1->Lines->Add(String(pszFortune)); CORBA::string_free(pszFortune); } catch(const CORBA::Exception& e){ ShowMessage(String(e._name()) + "; " + String(e._repository_id())); }
Click here to download the Fortune Teller source.
- Thread-Per-Session
- Depricated as of Visibroker 3.0. Use Thread Pooling instead. Specified when initializing the Basic Object Adapter,
CORBA::BOA_ptr boa = orb->BOA_init(argc,argv,"TSession");- Thread Pooling
- Much more performant than Thread-Per-Session. Default if no threading model is specified and the multi-threaded ORB is linked (orb_r.dll).
CORBA::BOA_ptr boa = orb->BOA_init(argc,argv,"TPool");- Single
- All requests by all clients are handled only one at a time. Quite inefficient. Specified by linking to the single-threaded ORB (orb.dll)
The topics on Firewalls, Midas, and CORBA Application Development are not quite complete as of this edition. They will be discussed in full in the live presentation and will be completed shortly after BorCon98. Please look for the updated edition of this whitepaper on the post conference CD or on my website. You questions and comments are always welcome also. Please do contact me at gcross@apsoft.com. Thank you for visiting this presentation !
References
Biography
George Cross, 32, is a senior advisor in Borland C++ Developer Support where he has worked for two and a half years. He was born and raised in Vancouver, British Columbia, and holds a Bachelor of Computer Science from Simon Fraser University. Prior to coming to Borland, he taught computer science at ABAC University in Bangkok, Thailand and then worked in Phoenix, Arizona as a software engineer on Modem Share®, a product now sold by Artisoft International. He enjoys mountain biking about the Santa Cruz countryside, laying by the company pool, cutting out early for golf, skimboarding and surfing. Recent subjects of interest include ActiveX, Corba, UML, Java (he has been known to sneak on the JBuilder support line) and Knuth's Fundamental Algorithms. George can be reached at www.apsoft.com/~gcross.
Kevin Stanley Scardina, 22, is a C++ Developer Support Engineer at Inprise, and Computer Science student at the University of California at Santa Cruz. His work related interests include CORBA, ActiveX, and OO design. Outside of work Kevin enjoys reading, playing fetch with his cat Peanut, beating the drums, and just about anything else that can lead to a good time. Kevin can be reached at www2.ucsc.edu/people/kid01