SDSU CS 696 Emerging Technologies: Distributed Objects
Spring Semester, 1998
ActiveX, DCOM, & JavaBeans

To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 14-May-98

Contents of Doc 36, ActiveX, DCOM, & JavaBeans

  1. References
  2. JavaBeans - More Features
    1. ActiveX Bridge
    2. Glasgow
      1. Runtime Containment and Services
      2. Drag and Drop
      3. JavaBeans Activation Framework
      4. Object Aggregation/Delegation Model
    3. Enterprise beans
    4. InfoBus
  3. ActiveX
    1. COM/DCOM
      1. IUnknown
      2. Monikers
      3. Automation
      4. COM/DCOM Servers
      5. DCOM Overall Architecture
    2. A DCOM-CORBA Example
      1. Corba IDL
      2. DCOM IDL
      3. CORBA C++ Class Interface
      4. CORBA C++ Implementation
      5. DCOM C++ Class Interface
      6. DCOM Server Main
      7. DCOM Client Code
      8. DCOM Object Activation
      9. DCOM Method Invocation

References


COM and DCOM: Microsoft's Vision for Distributed Objects, Roger Sessions, John Wiley & Sons, 1998

Client/Server Progamming with Java and Corba, Orfali & Harkey, John Wiley & Sons, 1997

Essential COM, Don Box, Addison Wesley, 1998

ActiveX Demystified, Chappell & Linthicum, Byte, Sept 1997, pp56-64

DCOM and CORBA Side by Side, Step by Step, and Layer by Layer, by P. Emerald Chung, Yennun Huang, Shalini Yajnik, Deron Liang, Joanne C. Shih, Chung-Yih Wang, Yi-Min Wang
http://www.cs.wustl.edu/~schmidt/submit/Paper.html

Doc 36, ActiveX, DCOM, & JavaBeans Slide # 2

JavaBeans - More Features

ActiveX Bridge


http://java.sun.com/beans/softare/bridge/

The ActiveX bridge allows beans to operate as an ActiveX control and as a VB component

I do not know about the performance, nor how the JVM is activated

Java Serialization does work in the ActiveX world with minor restrictions

Type Mapping between Java and ActiveX
Java TypeOLE Automation Type
booleanVT_BOOL
charVT_UI1
doubleVT_R4
floatVT_R2
intVT_I4
byteVT_I2
shortVT_I2
longVT_I4
java.lang.StringVT_BSTR
java.awt.ColorVT_COLOR
java.awt.FontVT_FONT
othersVT_DISPATCH


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 3

Glasgow


Code-name for the next release of the JavaBeans specification

Documentation can be found at:
http://java.sun.com/beans/glasgow/

Glasgow adds three new types of enhancements to JavaBeans:

Runtime Containment and Services


"This protocol allows developers to nest Beans within other Beans more seamlessly, where the nested Beans can procure additional services at runtime from its environment in a standard fashion. Similarly, it provides a standard mechanism for the environment or containing Bean to extend its capabilities directly to Beans within it."

Will be part of the JDK

Drag and Drop


Will be part of the JDK

Supports Drag & Drop between Java programs and native applications


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 4

JavaBeans Activation Framework


Is a standard extension of the JDK, available now

"With the JavaBeans Activation Framework, Java developers can take advantage of standard services to determine the type of an arbitrary piece of data, encapsulate access to it, discover the operations available on it, and to instantiate the appropriate JavaBeans component to perform said operation(s). For example, if a browser obtained a JPEG image, this framework would enable the browser to identify that stream of data as an JPEG image, and from that type, the browser could locate and instantiate an object that could manipulate, or view that image."

Object Aggregation/Delegation Model


"it has come apparent from much of the feedback from developers that "aggregation" is a much overloaded term that is interpreted by many to solve problems that this proposal does not nor should not address. In light of this observation, we have reconsidered the general utility this facility provides and have decided to defer the delivery of the implementation of this specification until a future (post-Glasgow) JavaBeans release."

Doc 36, ActiveX, DCOM, & JavaBeans Slide # 5

Enterprise beans


Component architecture for building distributed object-oriented business applications in the Java programming language.

Enterprise JavaBeans 1.0 defines two types of enterprise Beans:
Session objects

A typical session object has the following characteristics:
A typical EJB server and container provide a scalable runtime environment to execute a large number of session objects concurrently.

Doc 36, ActiveX, DCOM, & JavaBeans Slide # 6
Entity objects

A typical entity object has the following characteristics:
A typical EJB server and container provide a scalable runtime environment for a large number of concurrently active entity objects.

InfoBus


"InfoBus enables dynamic exchange of data between JavaBeans components by defining a small number of interfaces between cooperating Beans and specifying the protocol for use of those interfaces. The protocols are based on a notion of an information bus. All components which implement these interfaces can plug into the bus. As a member of the bus any component can  exchange data with any other component in a structured way, including arrays, tables, and database rowsets."

Doc 36, ActiveX, DCOM, & JavaBeans Slide # 7

ActiveX


In the beginning there was OLE - Object Linking and Embedding

OLE was Microsoft's compound-document technology, which allows a word processor document to contain a spreadsheet table, etc.

The second release (May 93) of OLE (OLE 2) introduced COM - Component Object Model

COM provided a general mechanism for allowing one piece of software to provide services to another piece of software

While OLE 2 used COM, COM was general, hence started to be used in may different ways

Microsoft wanted a brand name for the functionality of COM

The brand name used at first was OLE, so OLE meant anything that use COM

In 1996 the brand name changed to ActiveX

Now OLE means just Object Linking and Embedding

ActiveX covers anything that uses COM
An ActiveX control is just a component like a JavaBean
Distributed COM (DCOM) started in 1996 allows COM to operate across a network


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 8

COM/DCOM


Since DCOM is just using COM across the wire, be boundary between DCOM and COM is not clear

In COM/DCOM we produce DLL's (Dynamic Linked Libraries) for use by other programs
DLL's are in binary format and can be written in any language

COM uses an IDL (interface definition language) to define interfaces to COM objects

MIDL is the Microsoft's IDL compiler

COM IDL is based on the Open Software Foundation Distributed Computing Environment Remote Procedure Call (OSF DCE RPC) IDL, but is modified a bit

A COM interface is more a collection of function calls than the public interface of an object

COM objects can support multiple interfaces

COM IDL does not support multiple inheritance or object state


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 9
Interface Names

Each interface has two names: physical and logical

The developer gives the interface the logical name: MyCalculator

The physical name is a 128-bit value assigned to the interface by the CoCreateGuid method

The 128-bit value is an instance of a Globally Unique Identifier - (GUID)
BDA4A270-A1BA-11d0-8C2C-0080C73925BA

A GUID use to name an interface is called an Interface ID or IID

A GUID use to name an implementation is called a Class ID or CLSID



Doc 36, ActiveX, DCOM, & JavaBeans Slide # 10

IUnknown


This interface must be supported be all COM/DCOM objects
interface IUnknown {
   HRESULT QueryInterface([in] REFIID riid, [out] void **ppv);
   ULONG AddRef( void );
   ULong Release( void )
}


Virtual Table (vtable)
The vtable is an array of function pointers

At run time a client accesses the methods in an interface through the vtable for that interface

A client uses the QueryInerface method to determine which interfaces an object supports

The client never access an interface method directly


AddRef and Release are used for memory management


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 11
COM/DCOM Objects

Also called an Active object

Clients get pointers to interfaces, not a reference or proxy to an object

In CORBA/RMI a client can get a reference to a remote object and "interact" with the "same" object across sessions with the server

This is not the case with COM

Each time a client makes the first reference to an interface, an object that supports the interface is created

If the object uses persistent data, the client needs to tell the object where it is

Monikers


Monikers are used to make activation of objects easier

Monikers are COM objects that will activate a COM object for a client

Since monikers are COM objects the client must provide the file containing the data the moniker needs to create the object

Doc 36, ActiveX, DCOM, & JavaBeans Slide # 12

Automation


Automation is an alternative method of clients invoking functions on a server object

Automation is designed for use with simpler languages like Visual Basic (VB) but works with C++

Originally this was called OLE Automation

Automation does not use vtables it uses dispatch interfaces (dispinterfaces)


Object Definition Language (ODL) is used to define interfaces for automation
dispinterface Dog
   {
   properties:
      [id(0)]   long Age;
   
   methods:
      [id(1)]   long Bark;
      [id(2)]   long Sit;
      [id(3)]   long Run;
   };

The MKTYPELIB compiler compiles ODL

Doc 36, ActiveX, DCOM, & JavaBeans Slide # 13

The implementation class needs to implement the IUnknown and IDispatch interface

IDispatch interface which contains the following methods:
Invoke maps an dispID to a method call or property access
GetIDsOfNames converts text names of properties and methods to dispIDs
GetTypeInfoCount returns whether there is type information available for this dispinterface
GetTypeInfo returns metadata that describes the interface


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 14

COM/DCOM Servers


DCOM has three types of servers:

In-process
Executes in the same process space as their clients
Implemented as DLL's

Local servers
Executes in a separate process from their clients on the same machine
Clients use the Lightweight RPC (LRPC) mechanism to communicate with a local server
Local servers implemented as .EXE's

Remote Servers
Executes in a separate process on a remote machine and possibly on a different operating system
Clients use RPC mechanism to communicate with a remote server


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 15
What is a COM/DCOM Server?

A COM/DCOM server is a DLL or EXE that supports one or more server objects

A COM/DCOM server must:

Implement a class factory interface
Server must implement a factory with the IClassFactory interface for each supported class (CLSID) in the server
If the class supports licensing, then server must use the IClassFactory2 interface

Register the classes it supports
For each CLSID it must create one or more entries that provide the pathname to the server DLL or EXE

Initialize the DCOM Library
Use the CoInitiallize method to initialize COM/DCOM
The Co stands for COM

Verify that the library is of a compatible version
Call CoBuildVersion

Provide an unloading mechanism
Server needs to have a way to terminate it self when there are no active clients for its objects

Uninitialize the DCOM library
Call CoUninilialize


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 16

DCOM Overall Architecture



Picture taken from:

DCOM and CORBA Side by Side, Step by Step, and Layer by Layer, by P. Emerald Chung, Yennun Huang, Shalini Yajnik, Deron Liang, Joanne C. Shih, Chung-Yih Wang, Yi-Min Wang
http://www.cs.wustl.edu/~schmidt/submit/Paper.html


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 17

A DCOM-CORBA Example


This example, code and images are taken directly from :

DCOM and CORBA Side by Side, Step by Step, and Layer by Layer, by P. Emerald Chung, Yennun Huang, Shalini Yajnik, Deron Liang, Joanne C. Shih, Chung-Yih Wang, Yi-Min Wang
http://www.cs.wustl.edu/~schmidt/submit/Paper.html

Implement in CORBA and DCOM a Grid object

The grid object maintains a two-dimensional grid of integers

Grid has two interfaces
One to access the elements of the grid
One to reset the elements of the grid

Corba IDL

interface grid1 
{
   long get(in short n, in short m);
   void set(in short n, in short m, in long value);
};


interface grid2 
{
   void reset(in long value);
};

// multiple inheritance of interfaces
interface grid: grid1, grid2 
{
};


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 18

DCOM IDL

// uuid and definition of IGrid1
[  object, 
   uuid(3CFDB283-CCC5-11D0-BA0B-00A0C90DF8BC),
   helpstring("IGrid1 Interface"),
   pointer_default(unique)
]

interface IGrid1 : IUnknown      {
   import "unknwn.idl";
   HRESULT get([in] SHORT n, [in] SHORT m, [out] LONG *value);
   HRESULT set([in] SHORT n, [in] SHORT m, [in] LONG value);
};

// uuid and definition of IGrid2
[   object, 
    uuid(3CFDB284-CCC5-11D0-BA0B-00A0C90DF8BC),
    helpstring("IGrid2 Interface"),
    pointer_default(unique) 
]

interface IGrid2 : IUnknown      {
    import "unknwn.idl";
    HRESULT reset([in] LONG value);
};

// uuid and definition of type library
[   uuid(3CFDB281-CCC5-11D0-BA0B-00A0C90DF8BC),
version(1.0),
helpstring("grid 1.0 Type Library)
]
library GRIDLib
{
importlib("stdole32.tlb");
// uuid and definition of class
[   uuid(3CFDB287-CCC5-11D0-BA0B-00A0C90DF8BC),
    helpstring("Grid Class")
]
// multiple interfaces
coclass CGrid
{   [default] interface IGrid1;
    interface IGrid2;
};
};


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 19

CORBA C++ Class Interface

include "grid.hh" // IDL-generated interface header file


class grid_i : public gridBOAImpl {
public:
   virtual CORBA::Long get(CORBA::Short n, CORBA::Short m,
         CORBA::Environment &env);
   virtual void set(CORBA::Short n, CORBA::Short m, 
         CORBA::Long value, CORBA::Environment &env);

   virtual void reset(CORBA::Long value, 
                 CORBA::Environment &env);
   grid_i(CORBA::Short h, CORBA::Short w);
   virtual ~grid_i();

private:
   CORBA::Long **m_a;      
   CORBA::Short m_height, m_width;   
};


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 20

CORBA C++ Implementation

#include "grid_i.h"

CORBA::Long grid_i::get(CORBA::Short n, CORBA::Short m, 
                CORBA::Environment &) {          
   return m_a[n][m];
}

void grid_i::set(CORBA::Short n, CORBA::Short m, 
         CORBA::Long value, CORBA::Environment &) {
   m_a[n][m] = value;
}

void grid_i::reset(CORBA::Long value, CORBA::Environment &) {
   short n, m;
   for (n = 0; n < m_height; n++) 
      for (m = 0; m < m_width; m++) 
         m_a[n][m]=value;
   return;
}

grid_i::grid_i(CORBA::Short h, CORBA::Short w) {
   m_height=h;   // set up height
   m_width=w;    // set up width
   m_a = new CORBA::Long* [h];
   for (int i = 0; i < h; i++ ) 
      m_a[i] = new CORBA::Long[w];
}

grid_i::~grid_i () {
   for (int i = 0; i < m_height; i++) 
      delete[] m_a[i];
   delete[] m_a;
}


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 21

DCOM C++ Class Interface

#include "grid.h" // IDL-generated interface header file

class CClassFactory : public IClassFactory {
   public:
      // IUnknown
      STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
      STDMETHODIMP_(ULONG) AddRef(void)  { return 1; };
      STDMETHODIMP_(ULONG) Release(void) { return 1; }

      // IClassFactory
      STDMETHODIMP CreateInstance(LPUNKNOWN punkOuter, 
       REFIID iid, void **ppv);
      STDMETHODIMP LockServer(BOOL fLock) 
           { return E_FAIL; };
};

class CGrid : public IGrid1, public IGrid2 {
   public:
      // IUnknown
      STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
      STDMETHODIMP_(ULONG) AddRef(void)  
         { return InterlockedIncrement(&m_cRef); }
      STDMETHODIMP_(ULONG) Release(void) 
         { if (InterlockedDecrement(&m_cRef) == 0) 
            { delete this; return 0; }
         return 1; 
         }
      // IGrid1
      STDMETHODIMP get(IN SHORT n, IN SHORT m, 
       OUT LONG *value);
      STDMETHODIMP set(IN SHORT n, IN SHORT m, 
       IN LONG value);
      // IGrid2
      STDMETHODIMP reset(IN LONG value);

      CGrid(SHORT h, SHORT w);
      ~CGrid();
   private:
      LONG  m_cRef, **m_a;
      SHORT m_height, m_width;
};


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 22

#include "cgrid.h"

STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void** ppv) {
      if (riid == IID_IClassFactory || riid == IID_IUnknown) {
        *ppv = (IClassFactory *) this; 
        AddRef(); return S_OK;
      }
      *ppv = NULL;
      return E_NOINTERFACE;
      }

STDMETHODIMP
CClassFactory::CreateInstance(LPUNKNOWN p, REFIID riid, void** ppv) {
      IGrid1* punk = (IGrid1*) new CGrid(100, 100);
      HRESULT hr = punk->QueryInterface(riid, ppv);
      punk->Release();
      return hr;
      }

STDMETHODIMP CGrid::QueryInterface(REFIID riid, void** ppv) {
      if (riid == IID_IUnknown || riid == IID_IGrid1) 
        *ppv = (IGrid1*) this;
      else if (riid == IID_IGrid2) *ppv = (IGrid2*) this;
      else { *ppv = NULL; return E_NOINTERFACE; }  
      AddRef(); return S_OK;
           }  

STDMETHODIMP CGrid::get(IN SHORT n, IN SHORT m, OUT LONG* value) {
       *value = m_a[n][m];
       return S_OK;
      }

STDMETHODIMP CGrid::set(IN SHORT n, IN SHORT m, IN LONG value) {
       m_a[n][m] = value;
       return S_OK;
      }


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 23

STDMETHODIMP CGrid::reset(IN LONG value) {
       SHORT n, m;
       for (n=0; n < m_height; n++) 
         for (m=0; m < m_width; m++)
           m_a[n][m] = value;
       return S_OK;
      }

           CGrid::CGrid(SHORT h, SHORT w) {
   m_height = h; 
   m_width= w;
   m_a = new LONG*[m_height];
   for (int i=0; i < m_height; i++) 
       m_a[i] = new LONG[m_width];
   m_cRef = 1;
   }

extern HANDLE hevtDone;

CGrid::~CGrid () {
   for (int i=0; i < m_height; i++) 
       delete[] m_a[i];
   delete[] m_a;
   SetEvent(hevtDone);
   }


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 24

DCOM Server Main

HANDLE hevtDone;

void main()
{
   // Event used to signal this main thread 
   hevtDone = CreateEvent(NULL, FALSE, FALSE, NULL);
   hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
   CClassFactory* pcf = new CClassFactory;
   hr = CoRegisterClassObject(CLSID_CGrid, pcf,
   CLSCTX_SERVER,  REGCLS_MULTIPLEUSE , &dwRegister);
   // Wait until the event is set by CGrid::~CGrid()
   WaitForSingleObject(hevtDone, INFINITE);
   CloseHandle(hevtDone);
   CoUninitialize();
}

DCOM Client Code

#include "grid.h"

void main(int argc, char**argv)
{
   IGrid1      *pIGrid1;
   IGrid2      *pIGrid2;
   LONG value;

   CoInitialize(NULL);    // initialize COM
   CoCreateInstance(CLSID_CGrid, NULL, CLSCTX_SERVER, 
      IID_IGrid1, (void**) &pIGrid1);
   pIGrid1->get(0, 0, &value);
   pIGrid1->QueryInterface(IID_IGrid2, (void**) &pIGrid2);
   pIGrid1->Release();
   pIGrid2->reset(value+1);
   pIGrid2->Release();
   CoUninitialize();
}


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 25

DCOM Object Activation

(1.) Client calls COM library's CoCreateInstance() with CLSID_Grid and IID_IGrid1.

(2.) COM infrastructure starts an object server for CLSID_Grid.

(3.) As shown in the server main program, server creates class factories for all supported CLSIDs, and calls CoRegisterClassObject() to register each factory.

Server blocks on waiting for, for example, an event to be set to signal that the server is no longer needed. Incoming client requests will be served by other threads.

(4.) COM obtains the IClassFactory pointer to the CLSID_Grid factory, and invokes CreateInstance() on it.

(5.) In CreateInstance(), server creates an object instance and makes a QueryInterface() call to obtain an interface pointer to the IID_IGrid1 interface.

(6.) COM returns the interface pointer as pIGrid1 to the client.


Doc 36, ActiveX, DCOM, & JavaBeans Slide # 26

DCOM Method Invocation


[1.] Client calls pIGrid1->get() which eventually invokes CGrid::get() in the server.

[2.] To obtain a pointer to another interface IID_IGrid2 of the same object instance, client calls pIGrid1->QueryInterface() which invokes CGrid::QueryInterface.

[3.] When finishing using pIGrid1, client calls pIGrid1->Release() (which may not invoke CGrid::Release()).

[4.] Client calls pIGrid2->reset() which invokes CGrid::reset.

[5.] Client calls pIGrid2->Release() which invokes CGrid::Release().

DCOM Object Activation/Method Invocation
Picture taken from:

DCOM and CORBA Side by Side, Step by Step, and Layer by Layer, by P. Emerald Chung, Yennun Huang, Shalini Yajnik, Deron Liang, Joanne C. Shih, Chung-Yih Wang, Yi-Min Wang
http://www.cs.wustl.edu/~schmidt/submit/Paper.html

Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.

visitors since 14-May-98