PreviousOLE Automation (Windows 95 and Windows NT) Descriptions of OO Run-time SwitchesNext"

Chapter 36: SOM (OS/2)

SOM is IBM's object oriented programming technology for building, packaging and manipulating binary class libraries. SOM supports a full object model, including inheritance and class methods and data. It provides facilities for implementing objects and performing operations on the objects (such as memory management, messaging and distribution) in a language-neutral way.

36.1 Overview

SOM clients can send messages to any SOM object. With Object COBOL you can write both SOM objects and clients.

The SOM support is documented in three main sections:

The Object COBOL and SOM object models are similar, and support most of the same features. The main difference is the way the two object models define classes and metaclasses (see the section below).

36.1.1 Classes and Metaclasses

Each Object COBOL class defines an instance object (between the Object and End Object headers) and a class object (between the Class-Object and End Class-Object headers). This is explained in more detail in the chapter Class Programs. There is only ever one instance of each class object, which you can think of as a controller for all instances of the class. It maintains information applicable to all instances of that class, and contains class-methods to control the instances (for example, a method to create a new instance).

SOM also defines a class object, but it is known as the metaclass for that class. In Direct-To-SOM Object COBOL, the name of the metaclass is derived from the name of the class itself by prepending 'M_' to the name. For example, a class called account has a metaclass called M_account.

When you are using Object COBOL to access SOM objects, you don't need to think about the metaclass, as Object COBOL always selects the metaclass when appropriate (when you send a message to the class object).

You do need to be aware of the metaclass if you need to use a class written in Object COBOL from another language that needs to know the name of the metaclass of a class. The IDL generated by the Direct-To-SOM preprocessor also contains references to the metaclass of a class.

36.1.2 Software Requirements

Before using the SOM support described in this documentation, you need the following software:

36.2 Writing SOM clients

From an Object COBOL program you can:

A SOM object can be written in a different language to the client. It defines the types and formats of data which can be sent between clients and objects. Any data sent to SOM objects from Object COBOL programs is type-coerced according to the rules outlined in the section SOM Type Coercion Rules.

>>To write a SOM client

  1. Map each SOM class to an Object COBOL proxy class in the CLASS-CONTROL paragraph. Give the SOM class an Object COBOL class-name, and specify that it is in the SOM domain, using a statement of the form:
    class-name is class "$SOM$som-name"

    where som-name is the name of the SOM class - SOM class names are case-sensitive. For example, to use the SOM class account:

     class-control.
     Account is class "$SOM$account"

  2. You can now send messages to the SOM class as though it were an Object COBOL object. Send the class its constructor message to create new instances.

    The example below creates an instance of the SOM class account.

     class-control.
     Account is class "$SOM$account" 
     ...
     .
     working-storage section.
     01 wsAccount               object reference.
     ...
     procedure division.
     invoke account "SOMnew" returning wsAccount

  3. To access the attributes of a SOM class or object, use the "_get_attribute" and "_set_attribute" messages, where attribute is the name of the attribute you want access.

    For example, you can query the value of the balance attribute by sending the "_get_balance" message, and alter it by sending the "_set_balance" attribute. Parameters up to four bytes in length are passed by value; parameters greater than four bytes in length are passed by reference. You need to declare parameters correctly for the data type of attribute. The coercion rules used by Object COBOL Direct-to-SOM support to map COBOL data types to SOM data types are described in the section SOM Type Coercion Rules.

    The first example below retrieves attribute number from SOM object anObject:

    object-storage section.
    01 aNumber                  pic 9(4) comp-5.
    procedure division.
    ...
    invoke anObject "_get_number" returning aNumber

The data item is not more than four bytes long, so it is returned by value. In the next example, the data item is returned by reference. Object COBOL detects that an address is being returned, and makes the necessary adjustment. For example the code below still results in the value for attribute longnumber being put into anotherNumber:

object-storage section.
    01 anotherNumber    pic 9(9).
    procedure division.
    ...
    invoke anObject "_get_longnumber" returning anotherNumber

Take a copy of any value returned by reference if you want to keep it. Values returned by reference are eventually overwritten by the Object COBOL SOM support. Make any copy before sending another message through SOM.

36.3 Creating a SOM Class

This section tells you how you can create your own SOM classes, using Object COBOL. The steps below broadly outline creating a SOM class and making it available to other programs:

  1. Write the SOM class.

  2. Compile the SOM class.

  3. Debug the SOM class.

  4. Add the class to the SOM interface repository (this step is not always required).

The following sections cover this process in more detail. If you will be invoking your SOM class from languages other than Object COBOL, you should read the section The Environment Parameter.

36.3.1 Writing a SOM Class

To write a SOM class you:

  1. Declare the class as a SOM class.

  2. Inherit SOM functionality, either from an existing SOM class, or from SOMObject (part of the SOM kernel).

  3. Decide which parts of your object data will be available as SOM attributes.

36.3.1.1 Declaring a SOM Class

You identify a class as a SOM class in the Class-Control paragraph . A class declares all classes it uses, including itself, in the Class-Control paragraph. The declaration for a SOM class is in the form:

classname is class "$SOM$somname"

classname The name by which you refer to the class in application code
somname The name by which the class is known to SOM. This name is case-sensitive.

For example, suppose you have a class called account that you want to be a SOM class. The Class-Control paragraph looks like this:

class-control.
account is class "$SOM$account"
...

36.3.1.2 Inheriting SOM Functionality

Object COBOL's basic SOM functionality is provided by class SOMObject. All Object COBOL SOM classes must inherit from SOMObject, either directly, or by inheriting from a class which inherits SOM functionality. You also have to declare the superclass in the Class-Control paragraph. For example, the Class-Id header and Class-control paragraph for the SOM Account class look like this:

 class-id. Account inherits from class SomObject.

 class-control.
 account is class "$SOM$account" 
 SomObject is class "$SOM$SOMObject"

To write a SavingsAccount SOM class which inherits from Account, code:

class-id. SavingsAccount inherits from class Account.
class-control.
account is class "$SOM$account"
SavingsAccount is class $SOM$saccount".

Method names in SOM are case-sensitive. When you override a method in a subclass, ensure the name of the overriding method case-matches the name of the original method in the superclass. Otherwise the SOM compiler reports an error when you give it the IDL generated for your new class, saying that it can't find the overridden method in the base class. Use lower-case for new method names defined in Object COBOL classes.

36.3.1.3 Declaring SOM Attributes

A SOM attribute is a data item whose value is accessed through "get" and "set" accessor methods. SOM classes do not inherit direct access to their parent classes data, so the only way to access the data is through the accesor methods. This also provides for distribution of objects, since if an object resides on a remote machine somewhere, it is unreasonable to expect to access that object's data directly.

Object COBOL SOM classes define SOM attributes as object data in the Object-Storage Section. The first data item defined in Object-Storage is treated as a SOM attribute. If the first data item is a group item, then all its subordinate data items are treated as attributes.

When you compile an Object COBOL SOM class, a preprocessor generates the accessor "_get_" and "_set_" methods for each attribute. The table below shows some examples:

Object-Storage Section Attributes Accessor methods
01 attribute1 pic 9(4) comp-5. attribute1 _get_attribute1
_set_attribute1
01 attribute1 pic 9(4) comp-5.
01 attribute2 pic 9(9).
attribute1 _get_attribute1
_set_attribute1
01 instance-data.
03 attribute1 pic 9(4) comp-5.
03 attribute2 pic 9(9).
attribute1
attribute2
_get_attribute1
_set_attribute1
_get_attribute2
_set_attribute2
01 instance-data.
03 attribute1 pic 9(4) comp-5.
03 attribute2 pic 9(9).
01 private-data pic x(4).
attribute1
attribute2
_get_attribute1
_set_attribute1
_get_attribute2
_set_attribute2

The last example shows a mixture of attribute data and data that is private to the class. Attribute1 and attribute2 are true attributes and the preprocessor generates accessor functions for them, but private-data is remains private to the object itself, so it can't be accessed from any method not belonging to the class.

36.3.1.4 Updating Object COBOL SOM Classes

SOM enables you to keep binary compatibility between releases of a class, through the concept of a release order. The release order for a SOM class is simply a list of the methods that class supports, including any accessor methods for the attributes. The list controls the order in which methods appear in an object's method table. If the same order is maintained between releases, later revisions of the class are binary compatible with earlier versions. If the order changes, the class is no longer compatible with previous versions.

Object COBOL defines the release order for a SOM class as follows:

This example shows the release order for a simple Object COBOL Account class. An outline for the Account class is shown below:

class-id. account inherits SOMObject.
object section.
class-control.
account is class "$SOM$account"
SOMObject is class "$SOM$SOMObject".

class-object.
object-storage section.
01 nextAccountnumber    pic 99.
method-id. "openaccount"....
end method "openaccount".

end class-object.

object.
object-storage section.
01 instance-data.
  03 balance    pic 9(4)v99.
  03 accountname    pic x(80).

method-id. "deposit".
...
end method "deposit".

method-id. "withdraw".
...
end method "withdraw".

end object.

end class.

The SOM metaclass M_account has the following release order (SOM metaclasses are explained in the section Classes and Metaclasses:

  1. "_get_nextaccountnumber"

  2. "_set_nextaccountnumber"

  3. "openaccount"

The class account has this release order:

  1. "_get_balance"

  2. "_set_balance"

  3. "_get_accountname"

  4. "_set_accountname"

  5. "deposit"

  6. "withdraw"

To preserve the release order after the initial release of a class, you should not add any more data items that will be treated as attributes. Any new methods that you add should be added after all existing class methods or instance methods. You can declare more instance or class data provided that the data is not treated as attributes (see the section Declaring SOM Attributes for more information). You can also add new "_get_" and "_set_" methods to the end of the class to simulate new attributes.

The example below shows changes to the account class which simulate a new attribute, dateopened:

class-id. account inherits SOMObject.
object section.
class-control.
account is class "$SOM$account"
SOMObject is class "$SOM$SOMObject".

class-object.
object-storage section.
01 nextaccountnumber    pic 99.

method-id. "openaccount".
...
end method "openaccount".

end class-object.

object.
object-storage section.
01 instance-data.
  03 balance    pic 9(4)v99.
  03 accountname    pic x(80).
01 dateopened   pic 9(8).

method-id. "deposit".
...
end method "deposit".

method-id. "withdraw".
...
end method "withdraw".

method-id. "_get_dateopened".
...
end method "_get_dateopened".

method-id. "_set_dateopened".
...
end method "_set_dateopened".

end object.
end class.

36.3.2 Compiling a SOM Class

To use an Object COBOL class as a SOM class, you need to:

You do not need to define an interface using SOM Interface Definition Language (IDL) for Object COBOL SOM classes. Mfdts analyses the Object COBOL class definition and generates the necessary bindings to enable SOM to create objects and invoke methods on objects implemented in Object COBOL. Using cbllink to link the resulting files produces a SOM class in .dll format.

36.3.2.1 Using the mfdts Preprocessor

Before you compile an Object COBOL class using mfdts, you need to ensure that your Object COBOL code is correctly structured. The mfdts preprocessor does not accept all the syntax variants for Object COBOL classes that the checker does. The preprocessor requires you to use the preferred format for structuring Object COBOL programs, which is to use Class-Object/End Class-Object headers to delimit the class object.

The source code below shows the correct structure:

class-id. account inherits SOMObject.
object section.
class-control.
account is class "$SOM$account"
SOMObject is class "$SOM$SOMObject".

class-object.
...
end class-object.

object.
...
end object.
end class.

The preprocessor gets information from the SOM Interface Repository about the superclass and metaclass of the class you are compiling. Before compiling a class, you must ensure that the SOM Interface Repository has up-to-date information about its superclass (see the section The SOM Interface Repository). Otherwise, the preprocessor makes assumptions which can cause the class to be built incorrectly. If the interface repository is not up-to-date the preprocessor does not detect overridden methods, and assumes that the parent of the metaclass is SOMClass, rather than a class derived from SOMClass.

You can now compile the class using the preprocessor. You must set the following directives to compile a SOM program:

Directive
Description
p(mfdts) run the mfdts preprocessor
case Preserve case of entrypoints
mfoo Enable Micro Focus OO extensions

To compile an Object COBOL class for SOM, enter the following at the OS/2 command prompt:

cobol filename case mfoo p(mfdts); 

where filename is the .cbl source code file.

The compiler and preprocessor output the following set of output files:

filename.obj Object code
filename.eom Helper file used by cbllink for linking
filename.rts Helper file used by cbllink for linking
sclassname.obj SOM bindings. The filename on OS/2 HPFS is sclassname.obj. On FAT file systems, which only allow eight characters for the filename, the classname is truncated to seven characters.

Enter p(mfdts) as the last compiler directive. Any directives following p(mfdts) are treated as directives to the preprocessor - these are listed in the section below.

36.3.2.1.1 Directives for mfdts

You can change mfdts preprocessor behavior using the additional directives listed in the table below. Enter directives after p(mfdts) on the compiler command line.

mftds Directive
Behavior
noattr Do not generate attribute accessor methods for any data items in the Object-Storage section.
idl Generate an IDL file describing the class. The IDL file will have the name filename.idl.
debug Compile the class for debugging with Animator. Debugging is covered in the section Debugging SOM Classes.

For example:

cobol somacnt case mfoo p(mfdts) debug; 

This compiles somacnt.cbl as a debuggable SOM class.

36.3.2.2 Linking the SOM Class

The easiest way to link the SOM class into a .dll file for execution is to use cbllink. Enter the following command line to link a file:

cbllink -d -e -ooutput.dll filename.obj mfsom.lib

where the parameters are:

filename The filename of the .obj file produced by the compiler and preprocessor.
output The name for the output .dll file.

The linker outputs output.dll, which is useable as a SOM class. Copy the .dll file into a directory on LIBPATH to enable SOM to load it when required.

36.3.3 Debugging Object COBOL SOM Classes

You can debug Object COBOL classes using Animator V2, in the same way you debug any Object COBOL class. Before debugging, you must compile and link the class for debug. To compile a class for debug, you have to use the ANIM directive for the COBOL compiler, and the DEBUG directive for the mfdts preprocessor. For example, to compile the class in somacnt.cbl for debugging:

cobol somacnt.cbl anim p(mfdts) debug;

This produces an .int file, an .obj file and a .lnk file. You next link the files using cbllink. Specify the target .dll file name, and use the .lnk file as input to cbllink. For example:

cbllink -d -osomacnt.dll @somacnt.lnk mfsom.lib

Put the .dll file in a directory on the OS/2 LIBPATH. Put the .int and .idy files in the current directory, or in a directory specified on the COBDIR environment variable path.

If you are using another Object COBOL program to access the Object COBOL class, debug the Object COBOL program using Animator V2. When you execute INVOKE statements which send messages to the SOM class, you can animate through the SOM class code.

If you are using a program written in a different language to access the Object COBOL class, set the COBOL run-time switch +A. You can set this using the COBSW environment variable:

set cobsw=+a

Then execute the program which accesses the the Object COBOL SOM class (you can either run it normally, or use the debugger for the language it is written in). When the program first sends a message to an Object COBOL SOM class compiled for debugging, Animator starts automatically, and you can execute the SOM class from there.

36.3.4 Adding a Class to the SOM Interface Repository

The SOM interface repository is a database of SOM classes available to a particular host. It contains details of classnames, class relationships (for example parent, child and metaclass), methods supported by each class, attributes supported by each class and other SOM specific information such as whether the class is an OIDL class or not.

Any language which links to SOM classes dynamically (this includes Object COBOL) looks for information in the SOM interface repository to find out where the class is and how to call it. If the details for a particular class cannot be located in the interface repository, Object COBOL continues to run but makes the following assumptions about the class or method it is trying to call:

Remote classes being accessed through DSOM can only be used if their details are in the interface repository. The DSOM kernel needs to know the number and type of parameters for each method in order to package them and pass them to the remote site.

You can add a class to the interface repository using the som compiler, sc, and the .idl file for the class. Type the following command to add the details of the class in filename.idl to the interface repository:

sc -sir -u filename.idl

You can view the contents of the interface repository using the irdump utility. Both sc and irdump are supplied with the SOM Object Developer's Toolkit available from IBM. For more details, see the documentation in the toolkit.

36.3.5 The Environment Parameter

The Direct-To-SOM preprocessor by default generates classes that are CORBA compliant. This means that each method defined by the class expects a pointer to an Environment structure as the first parameter. You don't need to include any references to this parameter in your code as the Object COBOL runtime processes it as needed. You need to supply the environment parameter if you are invoking an Object COBOL SOM class from another language, as the receiving method expects it.

In SOM terms, all Object COBOL Direct-To-SOM classes are callstyle IDL rather than callstyle OIDL.

36.4 SOM Type Coercion Rules

SOM has a limited set of data types, which are a subset of the data types available to COBOL programmers. Object COBOL Direct-to-SOM support coerces data between COBOL and SOM data types automatically. The table below summarizes the rules for mapping COBOL data types to SOM IDL data types:

COBOL datatype
IDL equivalent
PIC 9(n) char [n]
comp-1 float
pic x comp-5 char
pic x(2) comp-5 short
pic x(4) comp-5 long
pic x(n) char [n]
pointer string
other char [n]
where n = length of data item.
The data remains in its original binary form.

36.5 Distributed SOM (DSOM)

Distributed SOM (DSOM) enables you to access objects across address spaces, either on the same machine (Workstation DSOM) or on a number of networked machines (Workgroup DSOM). Once the DSOM environment has been correctly set up, Object COBOL programs can use DSOM facilities with the minimum of changes to source code.

This documentation covers the minimum information needed to use Object COBOL with DSOM; for full information on the DSOM environment, see the chapter DSOM in the SOM Objects Developers Toolkit Users Guide supplied with the SOM Objects Developers Toolkit.

A machine that is going to run DSOM needs to have the DSOM daemon (called somdd.exe) active. The daemon controls the communications between objects wherever they are situated. The daemon is also responsible for starting up the appropriate servers that create classes as requested by applications.

The DSOM implementation repository is a database containing details about the servers which are available and the classes of object which each server can create. The repository stores the following information about each server:

Every machine that is to take part in DSOM communications needs access to an implementation repository with the same information, since the unique IDs for a given machine need to be consistent. For example, machine A needs to know that machine B has unique ID uidB, and machine B also needs to know that its unique ID is uidB otherwise DSOM will fail to establish a connection.

There are two possible ways to achieve this:

The second method is preferable because any changes can be applied centrally and are immediately available to all DSOM participating machines.

DSOM also makes use of the SOM interface repository (see the section SOM Interface Repository). DSOM needs the information in the interface repository to correctly package up, send, and unpackage parameters during invocation of a method on a remote object. The interface repository must be kept updated with the correct information for each class in a DSOM environment.


Note: The SOM interface repository can be distributed through a number of files, potentially on different machines. SOM finds the files by searching through the list in the SOMIR environment variable. Consult your SOM documentation for more information.


36.5.1 Changes to Object COBOL Programs for DSOM

Once you have set up the implementation repository with details of available servers and the classes each server supports, and the interface repository on both the client and server machines has been populated with details about the classes, there is very little to change in the Object COBOL program to distribute it via DSOM.

Distribution of classes is controlled by entries in the Class-Control paragraph of the Object COBOL program or class. For a non-distributed SOM class called account, the class control section looks like this:

 class-control.
    account is class "$SOM$account".

You can make this a remote class by including the name of a DSOM server as the first part of the class-name mapping, separated from the class name by a period. For example, if the server known as theBank hosts objects of class account, then the Class-Control paragraph now reads:

 class-control.
    remoteaccount is class "$SOM$theBank.account".

The DSOM framework takes care of resolving exactly where the theBank server resides, establishing a connection with it, creating the necessary objects and returning handles to them.

DSOM enables you to have more than one server supporting the same class of objects. In this case, you can select a particular server to host objects of that class, or you can ask DSOM to use the first server it finds which supports the specified class of objects. To do this, specify a server name of '*' in the Class-Control paragraph. For example:

 class-control.
     remoteaccount is class "$SOM$*.account".


Note: DSOM requires class objects themselves to be resident on both the client and server machines, otherwise the class load operation will fail. For any classes that are to be used remotely, the methods provided by the classes should be expressed in lower case in the accompanying IDL file.


36.6 SOM Framework Support

This section provides information on some functions provided by the SOM framework. They are made available to you through an Object COBOL class, somsup. This class exists in the native Object COBOL domain (it is not a SOM class itself), and to use it in your programs or classes, include the following entry in the Class-Control paragraph:

somsup is class "somsup"

All somsup methods are class methods, which are detailed below.


getEnvironment

Returns the address of the SOM global environment structure.

Syntax:
invoke somsup "getEnvironment" 
                            returning theEnvironment
Parameters:

theEnvironment POINTER

On Exit:

theEnvironment Pointer to the SOM environment structure


getPersistentId

Returns a DSOM persistent ID for a remote object. The id is a null terminated text string.

Syntax:
invoke somsup "getPersistentId" using anObject 
                            returning aPersistentId
Parameters:

anObject OBJECT REFERENCE
aPersistentId POINTER

On Entry:

anObject The object for which the persistent ID is required.

On Exit:

aPersistentId Pointer to the null-terminated persistent id string.

Remarks:

If the supplied object reference is not a remote object, the returned persistent ID will be null.


getObjectFromPersistentId

Returns an object reference to a remote object, given the persistent ID for the remote object.

invoke somsup "getObjectFromPersistentId" 
                                  using aPersistentId
                              returning anObject 
Parameters:

aPersistentId POINTER
anObject OBJECT REFERENCE

On Entry:

aPersistentId Pointer to the null-terminated persistent id string for which the object is required.

On Exit:

anObject Object reference to the remote object.


initWorkplaceShell

Performs the initialization to enable an Object COBOL program to interact with the OS/2 Workplace Shell, treating it as a DSOM server.

Syntax:
invoke somsup "initWorkplaceShell"


preloadClass

Creates the class object for the named class. This is needed when object references to a remote class are obtained, but the class has not previously been referenced on the local machine (for example, when programming the Workplace Shell on OS/2).

invoke somsup "preloadClass" using className
Parameters:

className POINTER

On Entry:

className Pointer to the null-terminated classname to create.


getCobolObject

This method returns an Object COBOL object reference for a given SOM object reference. You only see SOM object references in your Object COBOL programs if you make direct API calls to SOM. Whenever you get an object reference back as the result of an INVOKE, the Object COBOL run-time does this mapping automatically for you.

invoke somsup "getCobolObject" using aSomObject
                           returning aCobolObject
Parameters:

aSomObject OBJECT REFERENCE
anObject OBJECT REFERENCE

On Entry :

aSomObject The SOM object reference of the object.

On Exit:

anObject The Object COBOL object reference for the same object.


36.7 Troubleshooting Guide

This section contains a list of possible symptoms of problems you may encounter whilst using the Direct-To-SOM Object COBOL software. For each problem, a possible cause and suggested solution is provided.

 Load Failure file "classname"
classname ClassInfo not found
unresolved method when trying to call attribute accessor functions
Methods can be invoked on a local SOM class, but fail when the class is distributed
DSOM refuses to start a remote server


Copyright © 1999 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names used herein are protected by international law.

PreviousOLE Automation (Windows 95 and Windows NT) Descriptions of OO Run-time SwitchesNext"