Title: Message
Mike,
I like the general approach of passing multiple scope ids, generated by
the Consumer (I haven't drilled into the other parts of the interface). The only
downside to this approach is that the Producer has to re-map those ids back into
a Session object each round.
How about the following variation to help this issue a bit. In addition
to what you suggested, let the Producer return a token that the Consumer
must pass again for each call that belongs to the same ConsumerCtx. That token
may be different for each portlet on the page, or may be the same for multiple
portlets that belong to the same Producer. In the latter case, the Consumer can
easily compress the data and not store all of it, yet it may help the Producer
retrieve the transient information without complext mapping.
That means additions such as the ones below:
public class
FragmentResponse
{
Property[]
responseProperties;
String
fragment;
PersistentProperty[] values;
String producerToken;
}
public class ConsumerCtx
{
private ConsumerRef consumerId;
private UserIdentify user;
private SessionRef sessionId;
private EntityRef entityId;
private String entityType;
private EntitySessionRef
entitySessionId;
private PersistenceRef
persistenceId; // passed if portlet maintains data
private PersistenceProperties persistenceData; //
passed if consumer does
private PreambleData
updateData; // update the included session or
// persistent data before generating the fragment;
String producerToken;
}
Any thoughts?
Eilon
-----Original Message-----
From: Michael Freedman
[mailto:]
Sent: Monday, June 17, 2002
4:17 PM
To: interfaces; wsrp-wsia
Subject: [wsrp-wsia]:
Updated alternative API
The following is an updated
version of the counter-proposal to draft 0.1.2 I sent last week. The
main changes are the session as well as the entity references are created/sent
by the consumer. There is also a new reference for an entity session --
the session conversation with a specific entity. Finally, I have
simplified the method signature defining a single ConsumerCtx parameter to
hold all the (potential) references. There are still alot of details to
put in here so we have a consistent understanding but I though you would like
an early view. While waiting for these details the key to looking at
this is to think in terms of the consumer vs. the producer. This API
doesn't represent (many) abstractions as concrete objects in the
producer. Rather, most abstractions are seen as elements/scopes defined
by the consumer that are passed by reference to the producer. The
Producer is thus freed to represent themselves internally anyway they want to
-- merely needing to build a mechanism that maps from these references to
their implementation.
As background here are the terms and their defintions I am using:
client = an end user
consumer = an intemediary responsible for the aggregation and
control of heterogeneous producer services, responsible for the interaction
between
the client and the producer services placed on the clients
application interface.
producer = a container of producer services. the
WSIA/WSRP compliant service. As consumers are anticipated to be
aggregators, a producer
represents 1 or more entity types.
producer service = the WSIA/WSRP compliant service ( aka. portlet
)
entity type = a specific identifyable consumable function of a
producer. Producers publish its entity types to consumers.
Consumers reference entity
types to address its producer requests.
entity = a consumers particular usage of an entity type.
Consumers are anticipated to be aggregators, including aggregating multiple
distinct
instances or producer's entity type. The entity
represents each of these uses. From a producer perspective, the entity
identifies a particular consumer
usage. Producers will typically
use this ID as a key to per usage state.
reference: A reference is an ID passed from the consumer to
the producer to identify something known to consumer but maintained by the
producer.
persistence reference: A reference to persistent state
managed by the producer. Typically, a consumer will maintain a
persistence reference for
entities.
conversation reference: A conversation reference is an ID
that represents a particular (type of) conversation between the consumer and
the producer.
There are 4 converstation IDs: consumer to producer
(application), thread of a consumer to a producer (session), consumer to an
entity (entity), and
thread of a consumer to an entity (entity session).
application reference: A conversation between a consumer and
a producer. This conversation spans all consumer runtime use and all
producer
entities of this consumer. For convenience [in making
this unique], this ID is derived from the consumerID created by the producer
during
regristration.
session reference: A subconversation within an application
conversation between a consumer and a producer. As such it is a shared
scope between
all entities within a given producer that a consumer
chooses to group together. This can be all the entities of the
producer, a subset of entities, and
even at the extreme one session per
entity. Typically, a consumer/producer sessions scope will be tied to
a session maintained between the client and
the consumer.
entity reference: A conversation between a consumer and a
particular instance of an entity [type].
entity session reference: A conversation within a session
with a particular instance of an entity [type]
API:
ConsumerRef registerConsumer(ConsumerProperties
consumer);
void updateConsumer(ConsumerCtx ctx, ConsumerRef consumer,
ConsumerProperties consumerData);
deregisterConsumer(ConsumerCtx, ctx, ConsumerRef
consumer)
PersistenceRef createPersistenceRef(ConsumerCtx ctx,
PersistenceType type, PersistentProperty[] values);
PersistenceRef destroyPersistenceRef(ConsumerCtx ctx,
PersistenceRef ref, boolean cascade);
FragmentResponse getFragment(ConsumerCtx ctx,
FragmentRequestData
parameters);
void endScope(ConsumerCtx ctx, Scope scope); // scope is
application,
session, entity, or
entitySession
.... [aka performAction, describe, setProperties, getProperties]
Data:Note: we can break this into two or more
(heirarchical) data objects if we need/feel it works better in the
API/
public class ConsumerCtx
{
private ConsumerRef consumerId;
private UserIdentify user;
private SessionRef sessionId;
private EntityRef entityId;
private String entityType;
private EntitySessionRef entitySessionId;
private PersistenceRef persistenceId; // passed if
portlet maintains data
private
PersistenceProperties persistenceData; // passed if consumer does
private PreambleData updateData; // update
the included session or
// persistent data before generating the fragment;
}
public class FragmentRequestData
{
private String charSet;
private String markupType;
private String locale;
private Boolean secureClientCommunications;
private Property[] headers;
private Property[] parameters;
private DeviceInfo clientDevice;
private Mode producerMode;
}
public class FragmentResponse
{
Property[] responseProperties;
String fragment;
PersistentProperty[] values;
}
Quick overview of usage:
The producer creates two types of IDs.
One to represent a registered consumer and one to reference a persistent
record it maintains (on request by the consumer). The later is not
needed/used if the consumer manages the producers persistent itself (or the
producer does not support persistence). The consumer ID is expected to
be unique for all consumers of this producer. The consumer subsequently
uses this ID (or one derived from it) as the ConsumerRef in all subsequent
calls to identify the caller and to allow the producer to tie itself to this
consumer. The persistentRef is passed to all calls where an entity is
referenced.
A conversation might go like this:
Note: In this example a session represents a per user conversation
between a consumer and a producer. In this situation a SessionRef is
sent by the consumer to the producer for every call below where the consumer
is running within the context of a user. I.e. a consumer can choose not
to send sessionRefs when it doesn't know/can't identify the user (aka the
Public user). Question: is not sending the sessionRef when there
is no known conetxt okay? or do we force the consumer to always
find/have a context?
Operation: Portal locates and registers a portlet service.
Action: Consumer calls registerConsumer() to register itself with
the service. It also calls describe() to get entity information from the
producer.
Result: Because this is the first call received by the
producer since it has started running, the producer initializes its
application scope -- acquiring resources at the application level [It can
choose to defer until an operation needs application data].
Additionally, if a sessionRef is passed, the producer may choose to [if it
needs session data at this point] to initialize sessionscope. The consumer
receives a ConsumerRef from the producer that it maintains persistently.
Operation: As a consequence of registration, the portal creates an
entity instance for each entity type in its portlet repository (toolbox).
Action: Portal calls createPersistentRef() for each entity letting the
entity set its default values.
Result: The consumer (portal)
receives a persistent ref that it associates with the instance it created in
the toolbox.
Operation: Portal developer customizes the portlets settings in the
toolbox.
Action: Portal calls getFragment with an entityRef it
manufactuers to represent the toolbox instance, the persistenceRef it received
from createPersistenceRef, mode of Edit -- plus of course the
consumerRef, sessionRef, and the entitySessionRef.
Result:
Producer/portlet uses this information to present a screen to the developer
for customizing its settings.
Operation: End-user creates a portlet on a page from a templaet in the
toolbox.
Action: Portal calls createPersistentRef() to create a new
reference for the page instance. (The persistenceRef of the toolbox
instance is passed so the values can be inherited.) After this
completes, the Portal calls getFragment() on passing the new persistenceRef, a
new entityRef (for this new instance), etc.
Result: Producer/portlet
uses this information to present its "show" screen to the user.
-Mike-