The following proposal introduces the notion of a bookmark ID. This ID is provided by the consumer to the producer for use in distinguishing between render and resource requests that occur within a given bookmarkable context and those that do not. Its primarily intended to be used by portlets that either in whole or in part maintain state in the portlet session. The bookmark ID can be used as a key by such portlets to differentiate between requests which are in context and should use the current state vs. those that are not.
BookmarkIDs are unique identifiers most likely based on a value generated from the system clock. The consumer switches to a new bookmark ID for each initiating action or event call within a given client request. I.e. a consumer need not (should not) update this ID for events distributed to a portlet within the same request after it has processed an action nor for any cycle other then the first cycle of event distribution when no action has preceded the event in this request. performBlockingInteraction and handleEvents receive both the current bookmarkID (as represented in the navigationalContext) and the new bookmarkID (as part of each operation's parameter structure). In this circumstance the current bookmark ID represents the ID/key that is represented by the incoming client request. The new bookmarkID represesents the ID/key that is represented by the outgoing client response. Portlet's use the current ID to attach to existing state. Portlet's use the new ID to rekey the state or otherwise maintain a history of bookmarkable states. newBookmarkID is a required InteractionParams but an optional eventParams. If the situation that the value is omitted from a handleEvents, the semantic is that this call doesn't change the current bookmarkID. This occurs when the event is distributed within a given client request after a newBookmarkID has already been set. A bookmarkID with value = 0 is defined as signifying the render state of the portlet before any actions or events have been submitted to it. Whenever, the consumer receives a client request that either is missing a refrence to a bookmarkID or references a bookmarkID it no longer considers valid (because its missing state associated with this ID) the consumer MUST pass 0 as the current bookmarkID. The consumer is allowed to have additional policies that reset the bookmarkID to its initial default state. E.g. page traversal. With regards to caching, the bookmarkID is only considered part of the cache key if the portlet has set the usesBookmarkID boolean in its portletDescription. This recognizes that this commonly changing value should only impact caching in those circumstances that the portlet actually uses it as a key against internal state.
Structure:
NavigationalContext
[R] int bookmarkID
[O] string opaqueValue
[O] NamesString publicValues[]
[O] Extension extensions[]
* bookmarkID: current value of a consumer supplied unique ID the portlet uses to relate any internally maintained state with the given NavigationalContext. E.g. if a portlet maintains state in a portletSession but wants to only render from this state if the current request is in the same context as the the one that generated the state, it could key this information by the bookmarkID.
InteractionParams
[R] StateChange portletStateChange
[R] int newBookmarkID
[O] string interactionState
[O] NamedString formParameters[]
[O] UploadContext uploadContexts[]
[O] Extension extensions[]
* newBookmarkID: new value of a consumer supplied unique ID the portlet uses to relate any internally maintained state with the given NavigationalContext. From a consumer perspective this value becomes current upon the completion of this request/operation. I.e. portlets use the current value passed in NavigationalContext to locate its current state, however, because this operation results in the use of a new ID the portlet MUST either rekey the state with this new ID if it wants to be able to relocate this state or clone the state with this new key. [Note: should we make this an optional field as well for the not yet likely possibility that the consuemr send an event to the portlet within a given client request before it calls its PerformBlockingInteraction?]
EventParams
[R] StateChange portletStateChange
[R] Event events[]
[O] int newBookmarkID
[O] Extension extensions[]
* newBookmarkID: new value of a consumer supplied unique ID the portlet uses to relate any internally maintained state with the given NavigationalContext. From a consumer perspective this value becomes current upon the completion of this request/operation. I.e. portlets use the current value passed in NavigationalContext to locate its current state, however, because this operation results in the use of a new ID the portlet MUST either rekey the state with this new ID if it wants to be able to relocate this state or clone the state with this new key.
PortletDescription
....
....
[O] boolean usesBookmarkID
....
* usesBookmarkID: boolean value indicating whether the portlet uses the bookmarkID and hence the consumer should include this ID in any cache key it constructs. The default is false.