BBjNamespace

Description

In BBj 3.0 and higher, BBjNamespace provides a mechanism by which two or more BBj programs that are running in the same BBjServices can share data. It also provides methods that allow a program to be notified when that shared data is modified by some other program.

There are three types of BBjNamespaces, each with their own naming convention, level of visibility, and life cycle, with differences in scope and de-allocation of the shared memory.

  • Generic BBjNamespace - scope is global; memory is automatically freed when there are no longer any references.

  • Group BBjNamespace - scope is parent-children (group) interpreter (SCALLED or newBBjSession()) sessions; memory is automatically de-allocated when the group no longer exists

  • Global BBjNamespace - scope is global BBjServices or JVM wide; de-allocation only happens when items are removed from the namespace or restart of BBjServices (no automatic de-allocation)

Generic BBjNamespace

A generic BBjNamespace (see also BBjEnterpiseNamespace) may be obtained by any BBj program through a call to one of the following methods:

BBjAPI::getNamespace(string prefix, string suffix, boolean createIfNeeded)

BBjAPI::getExistingNamespace(string name)

BBjAPI::getNewNamespace(string prefix)

A BBjNamespace will remain in memory as long as there are any references to that BBjNamespace.

When a BBj session retrieves a generic BBjNamespace, the BBj session maintains a reference to that BBjNamespace for the lifetime of the BBj session. This is true even if the program itself does not assign that BBjNamespace to a variable.

A BBjNamespace can be placed into a different BBjNamespace or into an ObjectTable. Both of these actions add a reference to the BBjNamespace. So the BBjNamespace will be held in memory as long as it remains in another BBjNamespace that is held in memory or remains in an ObjectTable that is held in memory.

If a BBj session retrieves a BBjNamespace from a BBjNamespace or from an ObjectTable and then assigns the retrieved BBjNamespace to a variable, the variable acts as a reference to the BBjNamespace and that BBjNamespace will remain in memory as long as it is referenced by any variable in any BBj session.

Group BBjNamespace

A group BBjNamespace (see also BBjEnterpiseNamespace) is associated with a session group. A session group contains the session that was started by calling bbj. Except when running in a TermConsole, the session group also contains any BBj session that was created by a member of the group through calls to SCALL, BACKGROUND or newBBjSession(). When running in a TermConsole, every BBj session will have a unique group containing only one session.

All the BBj sessions within a given session group may access the same group BBjNamespace. The session BBjNamespace is obtained through a call to:

BBjAPI::getGroupNamespace()

Each BBj session in a BBj session group maintains a reference to the Group BBjNamespace for that group. A Group BBjNamespace will remain in memory until all BBj sessions in the BBj session group are terminated.

Global BBjNamespace

The global BBjNamespace (see also BBjEnterpiseNamespace) is global to the JVM that is running BBjServices. A BBj program can obtain the global BBNamespace through a call to:

BBjAPI::getGlobalNamespace()

The global BBjNamespace is unique in that it will persist even after all BBj sessions have terminated. This means that NamedVariables whose values have been set through the global BBjNamespace will be accessible until the BBjServices are terminated.

Using BBjNamespace Methods

The name of any BBjNamespace may be obtained by calling the method:

BBjNamespace::getName()

The NamedVariables within a BBjNamespace may be set and retrieved by calling the methods:

BBjNamespace::getValue(string varName)

BBjNamespace::setValue(string varName, Object value)

BBjNamespace::setValue(string varName, Object value, long timeoutMillis)

The value of a NamedVariable within a BBjNamespace may be locked/unlocked through calls to:

BBjNamespace::removeLock(string varName)

BBjNamespace::setLock(string varName, long timeoutMillis)

A BBj program may register/unregister to be notified when the value of a NamedVariable within a BBjNamespace has changed through calls to the methods:

BBjNamespace::setCallbackForVariable(string varName, string callback)

BBjNamespace::setCallbackForVariable(string varName, CustomObject customObj, string methodName)

BBjNamespace::setCallbackForVariableChange(string varName, string callback)

BBjNamespace::setCallbackForVariableChange(string varName, CustomObject customObj, string methodName)

BBjNamespace::setCallbackForNamespace(string callback)

BBjNamespace::setCallbackForNamespace(string customObj, string methodName)

BBjNamespace::setCallbackForNamespaceChange(string callback)

BBjNamespace::setCallbackForNamespaceChange(CustomObject customObj, string methodName)

BBjNamespace::removeCallbackForVariable(string varName)

BBjNamespace::removeCallbackForVariableChange(string varName)

BBjNamespace::removeCallbackForNamespace()

BBjNamespace::removeCallbackForNamespaceChange()

A BBj program may enable/disable all callbacks that the BBj session has registered on a BBj program by calling:

BBjNamespace::enableCallbacks(int enable)

Creation

BBjAPI > BBjNamespace

The BBjNamespace object is created through the following BBjAPI object methods:

Return Value

Method

BBjNamespace

getExistingNamespace(string name)

BBjNamespace

getGlobalNamespace()

BBjNamespace

getGroupNamespace()

BBjNamespace

getNamespace(string prefixName, string BaseName, int createIfNeeded)

BBjNamespace

getNewNamespace(string prefixName)

 

Methods of BBjNamespace

Return Value

Method

void

clear()

java.util.HashMap

cloneMap()

void

enableCallbacks(int enable)

BBjVector

getKeys()

string

getName()

BBjObject

getValue(string name)

void

removeCallbackForNamespace()

void

removeCallbackForNamespaceChange()

void

removeCallbackForVariable(string varName)

void

removeCallbackForVariableChange(string varName)

void

removeLock()

void

removeLock(string varName)

void

setCallbackForNamespace(string callback)

void

setCallbackForNamespace(CustomObject custObj, string methodName)

void

setCallbackForNamespaceChange(string callback)

void

setCallbackForNamespaceChange(CustomObject custObj, string methodName)

void

setCallbackForVariable(string varName, string callback)

void

setCallbackForVariable(string varName, CustomObject custObj, string methodName)

void

setCallbackForVariableChange(string varName, string callback)

void

setCallbackForVariableChange(string varName, CustomObject custObj, string methodName)

void

setLock(string name, long timeoutMillis)

void

setValue(string name, object value)

void

setValue(string name, object value, long timeoutMillis)

void

removeValue(string name)

void

removeValue(string name, long timeoutMillis)

Remarks

Objects passed to other BBj sessions via the BBjNamespace objects are passed by reference.

When multiple BBj interpreters share data via BBjNamespace, many Java objects are unsafe for concurrent modification. The developer is responsible, in this multiple-thread environment, for utilizing locks to prevent accidental unsynchronized access to the object.

See Accessing Objects from Different Interpreters for restrictions on usage of BBj objects shared via BBjNamespaces.

Example

rem 'namespace.bbj

sysgui = unt
open (sysgui)"X0"
api! = BBjAPI()
sysgui! = api!.getSysGui()

rem 'retrieve a namespace, get value of count
if api!.isInMDI()
    sharedNS! = api!.getGroupNamespace()
    prefix$ = "basis.eng.test.namespace"
else
    if (argc < 2) then
        rem 'run from command line with no namespace name
        prefix$ = "basis.eng.test.namespace"
        sharedNSName$ = "test"
        sharedNS! = api!.getNamespace(prefix$, sharedNSName$, 1)
    else
        rem 'run from command line with a namespace name
        prefix$ = argv(1)
        sharedNSName$ = "test"
        sharedNS! = api!.getNamespace(prefix$, sharedNSName$, 1)
    endif
endif

rem 'retrieve count from sharedNS! and use it to create our name
count = sharedNS!.getValue("count", err = setCount)
privateNS! = api!.getNewNamespace(prefix$)
privateNS!.setValue("count",0)
name$ = "client-" + privateNS!.getName()

rem 'retrieve position from sharedNS! and increment it
sharedNS!.setLock("x", 500, err = onLocked)
x = sharedNS!.getValue("x", err = setXY)
sharedNS!.setValue("x", x+50)
sharedNS!.removeLock("x")
sharedNS!.setLock("y", 500, err = onLocked)
y = sharedNS!.getValue("y", err = setXY)
sharedNS!.setValue("y", y+50)
sharedNS!.removeLock("y")

rem 'create window
window! = sysgui!.addWindow(x,y,300,200,name$)

rem 'add some static text fields
window!.addStaticText(101,5,50,290,30,"sharedCount:   ")
window!.addStaticText(102,5,70,290,30,"privateCount: ")

rem 'add buttons and callbacks
plus! = window!.addButton(1,5,10,90,30,"Increment")
minus! = window!.addButton(2,105,10,90,30,"Decrement")
break! = window!.addButton(3,5,110,90,30,"Break")
sharedCount! = window!.addStaticText(103,200,50,290,15,str(count))
privateCount! = window!.addStaticText(104,200,70,290,15,str(0))
break!.setCallback(break!.ON_BUTTON_PUSH,"onBreak")

rem 'set callback for controls
plus!.setCallback(plus!.ON_BUTTON_PUSH, "onPlus")
minus!.setCallback(plus!.ON_BUTTON_PUSH, "onMinus")
window!.setCallback(window!.ON_ACTIVATE, "onActivate")

rem 'set callback that is to be called when count changes
sharedNS!.setCallbackForVariable("count", "showCount")
privateNS!.setCallbackForVariable("count", "showCount")

rem 'call onActivate to set tell others we have activated
gosub onActivate
callback(ON_CLOSE,done,sysgui!.getContext())

rem 'if running in MDI, register a callback for MDI closing
if api!.isInMDI()
    mdi! = api!.getMDI()
    mdi!.registerMDIClosingCallback("mdiClosingCallback")
endif
process_events

rem 'our callbacks
onPlus:
    sharedNS!.setLock("count",1500,err = onLocked)
    sharedNS!.setValue("count", 1 + sharedNS!.getValue("count"))
    sharedNS!.removeLock("count")
    privateNS!.setLock("count",1500,err = onLocked)
    privateNS!.setValue("count", 1 + privateNS!.getValue("count"))
    privateNS!.removeLock("count")
return

onMinus:
    sharedNS!.setLock("count",1500,err = onLocked)
    sharedNS!.setValue("count", -1 + sharedNS!.getValue("count"))
    sharedNS!.removeLock("count")
    privateNS!.setLock("count",1500,err = onLocked)
    privateNS!.setValue("count", -1 + privateNS!.getValue("count"))
    privateNS!.removeLock("count")
return

onActivate:
    sharedNS!.setValue("activeClientNS", privateNS!.getName())
    sharedNS!.setValue("activeClientName",name$)
return

showCount:
    sharedcount!.setText(str(sharedNS!.getValue("count")))
    privatecount!.setText(str(privateNS!.getValue("count")))
return

onBreak:
    escape
return

done:
release

setXY:
    x = 100
    y = 100
    sharedNS!.setValue("x", x)
    sharedNS!.setValue("y", y)
retry

setCount:
    count = 0
    sharedNS!.setValue("count", count)
retry

onLocked:
    print "lock error"
    escape
retry

rem 'callback to be run when MDI attempts to close
mdiClosingCallback:
    print 'EE', 'ask'("MDI is attempting to close",3,"What do you want to do?","Veto close:1","Accept close:2","release:3")
    print 'BE'
    read(0,siz = 1,err = askCancelled)response
    print "answer is " , response
    print 'BE'
    switch response
        case 1
            mdi!.vetoMDIClose()
            break
        case 2
            mdi!.approveMDIClose()
            break
        case 3
            gosub done
            break
    swend
return

askCancelled:
    print "ask was cancelled or else closeAll() timed out"
    mdi!.approveMDIClose(err=*next)
return

See Also

BBjAPI

BBj Object Variables

BBj Object Assignment

BBj Object Error Handling

BBj Object Operators

Accessing Objects From Different Interpreters

BBjEnterpriseNamespace

BBjNamespaceEvent

See the BBj Object Diagram for an illustration of the relationship between BBj Objects.