[OpenAjaxInterop] hub code changes

Howard Weingram weingram at tibco.com
Tue Dec 9 19:14:44 PST 2008

Thanks, Javier. Comments below.

On 12/9/08 9:55 AM, "Javier H Pedemonte" <pedemont at us.ibm.com> wrote:
> There were to variables called "_containers" and "_cts".  It looks like those
> are supposed to be the same thing, so I changed them all to "_containers".  I
> also changed "_st" to "_subscriptions".

Thank you! You are correct.

> OpenAjax.hub.ManagedHub._state:  Right now, the only values are 1 (active) and
> 2 (disconnected).  Did you have something more in mind for this variable?  If
> not, it would be best to change it to a boolean called "isActive" (or
> something of that nature) -- it makes it clearer what the variable is intended
> for. 

For ManagedHub, a Boolean value called _active would indeed work. The two
states are:

    Initial state. 
    MH.disconnect() has been called. Functions such as subscribe, publish,
    and addContainer and subsequent calls to disconnect will throw
    OpenAjax.hub.Error.Disconnected. MH.isConnected() will return false.

Background (I know you understand this, but some may not):

If we are in the middle of a subscriber's onData callback when we call
disconnect(), the ManagedHub cannot be instantly destroyed. The MH DOES
state DOES immediately change to INACTIVE. After disconnect() returns, the
remainder of the onData callback completes. The publish that triggered the
onData completes (and there might be several levels of nested calls in
callbacks). More API calls might be made in these callbacks. Finally, after
we are safely done with all of our callbacks, cleanup will occur.

For the typical HubClient, there are 4 states. I am going to describe them,
though I realize that this is tangential to your question, because this
provides an answer to one of the open questions that I raised at the face to

    This is the initial state. Connect() has not been called yet.
    It is legal to call connect().
    Operations like subscribe, publish, etc. throw Disconnected.
    disconnect throws Disconnected.
    isConnected() returns false.
    connect() has been called but Container has not yet accepted
    the request. In the truly asynchronous FIM case, it's obvious
    that this is needed. In the Inline case, this state occurs
    while connect() is proceeding, which includes the period of
    time during which the container calls the manager's
    onConnect() callback; in the Inline case, this happens before
    the container returns control to the HubClient.connect
    It is ILLEGAL to call connect(). [perhaps change Disconnected
    error to WrongState Error. Not sure. Maybe add new Error]
    Operations like subscribe, publish, etc. throw Disconnected.
    disconnect is legal and immediately sets state to DISCONNECTED.
    isConnected() returns false.
    connect() has succeeded.
    A subsequent call to connect() throws an exception.
    Operations like subscribe, publish, etc. succeed.
    disconnect is legal. It immediately sets state to DISCONNECTED.
    isConnected() returns true.
    connect, disconnect, publish, subscribe, etc. all throw exceptions.
    isConnected() returns false.
    NOTE: yes, I am saying that state 4 is different from state 1.
    Once the client calls disconnect, that's it; this client can never
    call connect() again. A manager can recreate the container if
    it wants to reinitialize the client.

While some HubClient implementations might have different internal states,
we need to clearly specify the behavior of the API as the client sees it. So
I propose that we standardize that the HubClient API behave as described

> What is the point of the "OpenAjax.hub.SubscriptionHandle = String" line?  If
> SubscriptionHandle is not an object/interface that we define, then I would
> rather that we treat it as an opaque type that is specific to the
> hub/container implementation.

It is an opaque type belonging to the hub (not the container). On the
manager side, a SubscriptionHandle is an opaque value that is returned by
MH.subscribe(), MH.subscribeForClient() and OAH.subscribe(). It is generated
by the ManagedHub rather than by the Container. The container provides a
string subscription ID to the ManagedHub when it calls
MH.subscribeForClient(), but that is not the same as a subscription handle.

On the client side, a SubscriptionHandle is an opaque value returned by
HubClient.subscribe. This SubscriptionHandle might be anything the HubClient
implementer wants it to be.

Bottom line: SubscriptionHandle is an opaque value created and understood
only the Hub instance. I'll remove the line about SubscriptionHandle being

> What are the functions "this._val" and "this._def"?  I can guess, but just
> want to be sure what you had in mind.

I have been using them in my branch. They can be useful for
// Checks whether obj exists and is non-null
// (I use this for parameter validation)
OpenAjax.hub.ManagedHub.prototype._def = function(obj) {
    return ( (typeof obj != "undefined") && (obj != null) );

// if obj exists (and is either null or non-null), returns obj
// if obj does not exist, returns null
OpenAjax.hub.ManagedHub.prototype._val = function(obj) {
    return ( (typeof obj != "undefined") && (obj != null) ) ? obj : null;

We can inline _val. We're only calling it once.

I'm using _def in several places and should probably be using it in several
more to confirm that required parameters are provided, e.g.

> Fixed some issues with how removeContainer() is called.  Also, I made that
> function call Container.remove() before deleting the container.  Do these
> changes seem correct to you?

Yes, it does. Good catch. Thank you.

> In the JSDoc for _sendToClient(), you state that the onPublish() callback
> takes 'null' for the publisher ID if the publisher is a ManagedHub.  However,
> if the user has two or more managed hubs and uses the same onPublish()
> callback, they would not be able to differentiate between the multiple managed
> hubs.  Of course, this is probably a pretty rare use case, so we probably
> don't need to consider it too much.  Just wanted to throw it out there.

The following options are available to us:

1. Tell the programmer to use different scope objects
    (which can be specified in the ManagedHub constructor
    params) to differentiate, or to just use different callbacks.
2. Add a mhub parameter to onPublish and onSubscribe.
3. Add a mandatory hub ID or hub name argument to onPublish/onSubscribe.
    Add a mandatory hub name parameter to ManagedHub(params)
    that the manager must specify when creating a ManagedHub.
    Add a function to get a hub's id. Don't allow duplicate IDs.
    Variations on this theme are possible but are pointless.
4. Make each ManagedHub be a kind of crippled default Container,
    presumably without implementing operations like sendEvent,
    getParameters, etc. Add an operation to all Containers that
    allows the caller to check whether this is just a ManagedHub
    or a real Container, or force the clientID to have a special
    syntax if this is a ManagedHub.
5. Make each ManagedHub CREATE a private special Container to
    use for this kind of thing.

1 works today, and since we agree that the scenario you mentioned will
happen quite infrequently, and that the developer has complete control over
whether it happens or not, I would be happy to leave this as is.

2 would be trivial. I would be fine with doing this.

3 is awkward, and there is no point. If this is necessary, do 2 instead.

4 is extremely awkward. I definitely want to avoid doing this. The old
reference code was somewhat contorted in this area. What we have been
working out here is much simpler and cleaner.

5 ties a specific Container implementation into the base ManagedHub
implementation. I definitely want to avoid doing this.

> I haven't run this code yet, so there are probably some bugs remaining...


Thanks, Javier. I've synced with the updated version.

I have some changes for the inline HubClient. Looks like you've updated it
so I will need to get your changes and see where to go from there.


> Javier H Pedemonte
> _______________________________________________
> interop mailing list
> interop at openajax.org
> http://openajax.org/mailman/listinfo/interop

Howard Weingram      650.846.1000
Principal Architect  TIBCO Software Inc.

TIBCO PageBus(TM) delivers ultra-lightweight
publish-subscribe messaging for mash-ups.
Learn more at http://www.pagebus.org

More information about the interop mailing list