Parameters Examples

July 28, 1998 - Jack Harich - Document Map

There are two types of parameters: those for container nodes and those for worker (Bean) nodes. Below is an example of a typical system root node. This one is for the server system of a 3 tier application.

Container parameters are used to define and "lightly" configure their members. Heaver configuration is done by parameters per member.

Note the Primordial Invocations at the bottom. These are invoked when the node is started. Since this is a system root node, datastore.start() starts the entire system after the BA has initialized the root container members.

All systems have the equivalent of a root container that initializes and starts the system. Most systems have the equivalent of sub-containers that initialize and start subsystems. The advantage of the BA is this is standardized and resuable. This gives a team tremendous infrastructure and built-in discipline.

// _Container.parex - DataServer root
this_Item has:
    IsContainer is: true
    End: this_Item
//========== ItemDefs ==============================
datastore_Item has:
    BeanClassName is: org.jcon.df.Datastore
    // The alias should use the preferred database, which is
    // ATSDR_SybaseProduction or ATSDR_LocalAccessProduction
    Config hasLines:
        setDatabaseFactory(org.jcon.df.DatabaseFactory databaseFactory)
        addDatabaseNameAlias("atsdr", "ATSDR_LocalAccessProduction")
        End: Config
    End: datastore_Item
databaseFactory_Item has:
    BeanClassName is: org.jcon.df.DatabaseFactory
    ParamMarkerItemName is: this
    ParamFileName is: DatabaseFactory.parex
    Config hasLines:
        setSchemaMgr(org.jcon.df.SchemaMgr $schemaMgr)
        setConnectorMgr(org.jcon.df.ConnectorMgr connectorMgr)
        End: Config
    End: databaseFactory_Item
connectorMgr_Item has:
    BeanClassName is: org.jcon.df.ConnectorMgr
    End: connectorMgr_Item
translatorTypes_Item has:
    IsContainer is: true
    End: translatorTypes_Item
schemaMgr_Item has:
    BeanClassName is: org.jcon.df.SchemaMgr
    IsContainer is: true
    End: schemaMgr_Item
// Root getting too large, need to put this in child node
problemHandler_Item has:
    BeanClassName is: org.jcon.util.log.ProblemHandler
    Config hasLines:
        setMarkerClass("gov.cdc.atsdr.server.DataServer")
        setResource("ProblemLog.txt")
        setDisplayProblem(true)
        hookupToGenLib()
        End: Config
    End: problemHandler_Item
//========== Primordial ============================
PrimordialInvocations hasLines:
    datastore.start()
    End: PrimordialInvocations


Below is a smaller container "param". Param is the internal class name for the data structure that parameter text is converted to. Note the preponderance of event links. This is typical. As system size grows the number of event links gets quite large, but diminishes when ContainerServices are used.

This is the param for the node in the Bean Assembler that handles the visual System Tree.

// _Container.parex - The tree module
this_Item has:
    IsContainer is: true
    Config hasLines:
        this.addMessageListener("TreeOpened", ML treeMgr)
        this.addMessageListener("CloseAllTrees", ML treeMgr)
        this.addMessageListener("ParamApplied", ML treeMgr)
        End: Config
    End: this_Item
//========== ItemDefs ==============================
eventRouter_Item has:
    BeanClassName is: org.jcon.ba.system.router.EventRouterBIP
    Config hasLines:
        provideListener("org.jcon.ba.tree.ItemTreeListenerProxy", Object treeMgr)
        End: Config
    End: eventRouter_Item
treeMgr_Item has:
    BeanClassName is: org.jcon.ba.tree.TreeMgr
    Config hasLines:
        addMessageListener("EditParam", ML this)
        addMessageListener("GroupClosed", ML this)
        addMessageListener("EditModule", ML this)
        addMessageListener("InspectItem", ML this)
        addMessageListener("ItemSelected", ML this)
        End: Config
    End: treeMgr_Item
//========== Primordial ============================
PrimordialInvocations hasLines:
    End: PrimordialInvocations


Below is the a worker param used to define how the Data Framework maps logical datatypes to Sybase's native datatypes. Other params define other database types, such as Access, Oracle, Informax, etc. This example shows how well designed parameters can play powerful roles in system design. The objective of this param's design was to allow database independence.

// TranslatorTypeSybase.parex - for TranslatorType
//
Name is: Sybase
AutomaticTimeStamp is: true
//
// Nulls not allowed by default so return indicator
NullAllowed is: null
//
// "Format" or exact value such as "NULL"
NullDateValue is: Format
//
// Values are ColumnDefType, DatabaseDatatype, FormatPrefix,
//    and FormatSuffix 

ColumnDefTypes hasLines:
    MID,        money,          $,      None
    TimeStamp,  timestamp,      None,   None
    String,     varchar(254),   ',      '
    Mask,       varchar(254),   ',      '
    Code,       varchar(254),   ',      '
    Integer,    int,            None,   None
    Boolean,    bit,            None,   None
    Memo,       text,           ',      '
    Date,       smalldatetime,  ',      '
    Year,       int,            None,   None
    Money,      money,          $,      None
    End: ColumnDefTypes


Below is the UserSys entity param. Note the ease with which we can express what to do. The param is very readable, even by those who have never seen it before. One goal of the Param Engine was to allow non-programmers to easily edit raw parameter text.

Note the "Type" key/value. These are the logical datatypes, such as String, that are used in the above param to map logical to native datatypes. The Data Framework exposes only logical datatypes to business objects.

// The UserSys entity. Represents a person who is allowed
// to use the system. "UserSys" chosen for name since
// "User" is a Sybase reserved word.
// @author Jack Harich
Name is: UserSys
UniqueIndexes hasLines:
    UserID
    End: UniqueIndexes
DescriptionColumnNames is: LastName, FirstName
EntityListener is: gov.cdc.atsdr.server.EntityValidator
Columns has:
    UserID has:
        Type is: String
        MaxLength is: 10
        Required is: true
        UpperCase is: true
        End: UserID
    Password has:
        Type is: String
        MaxLength is: 10
        Required is: true
        End: Password
    AdminCode has:
        Type is: String
        DisplayName is: Admin Code
        MaxLength is: 7
        Required is: true
        UpperCase is: true
        End: AdminCode
    IsAdmin has:
        Type is: Boolean
        DisplayName is: Is Admin
        Required is: true
        Default is: false
        End: IsAdmin
    SSN has:
        Type is: Mask
        Mask is: 999-99-9999
        End: SSN
    FirstName has:
        Type is: String
        DisplayName is: First Name
        MaxLength is: 20
        Required is: true
        UpperCase is: true
        End: FirstName
    MiddleInitial has:
        Type is: String
        DisplayName is: Initial
        MaxLength is: 1
        UpperCase is: true
        End: MiddleInitial
    LastName has:
        Type is: String
        DisplayName is: Last Name
        MaxLength is: 20
        Required is: true
        UpperCase is: true
        End: LastName
    LastLogon has:
        Type is: Date
        DisplayName is: Last Logon Date
        Required is: true
        End: LastLogon
    UserProfileMID has:
        Type is: MID
        DisplayName is: User Profile
        LinkEntityName is: UserProfile
        End: UserProfileMID
    End: Columns


That's the basics of text parameters. Once you have lots of them additional infrastructure is needed.

Suppose deep in a Param you have a value that varies. We call this a setting. An example is the current fiscal year, which is used by a number of components to filter data. We handle this by replacing the setting when the Param is used. For example:

FilterLine is: FiscalYear = [[Awards.CurrentFiscalYear]]

Would after replacement become:

FilterLine is: FiscalYear = 1997

Settings can be modified at runtime by the user. The next time a parameter using that setting is used, the new setting value is used.

Suppose you want to reuse an entire system and change a bunch of parameter values. The BA comes with a reusable approach to this that is, guess what, parameter driven. An example would be too long to put here. What you do is define via parameters what you wish to change, and then run ConfigParameters.


As you can see, parameters can express a wide variety of behavioral reguirements. While the above examples are oriented toward editing a relational database, parameters can handle other domains just as well. We have merely chosen the Data Framework, which is built on top of the Bean Assembler, as the first serious use of the BA since so many apps are database apps.

A really cool aspect of parameters is they are language independent, with the small exception of embedded class names. They are also implementation independent, which decouples the "what" from the "how". Thus a single system can use different reusables and a single param to, for example, have a system behave differently depending on user skill level. This is much harder with other approaches.

And now we move into the controversial. Parameters are a much better approach to specialization than inheritance over 50% of the time. Enough said.