On 9/11/07, Jean-Sebastien Delfino <[EMAIL PROTECTED]> wrote:
>
> I'm overall +1 with this proposal, with some minor changes described in
> comments inline.
>
> Raymond Feng wrote:
> > Hi,
> >
> > As we agreed, the conversation id alone is not sufficient to deal with
> > conversations. We need to maintain the state of the conversations
> > (STARTED, ENDED or EXPIRED).
>
> Right, if I understand correctly we need to keep the state of a
> conversation in a central place in a Tuscany runtime that all
> participants can point to, allowing one to end the conversation, and the
> other conversation participants to see that it has ended.
I would go further than this to say, if we follow the words of the spec, we
should keep the state of a conversation in a central place in a domain. At
least in the very specific cases where there is a 3rd party involved in the
conversation. However a sentral place in a node is a good place to start.
>
> > I propose that we do the following:
> >
> > 1) Define a ConversationManager like:
> >
> > public interface ConversationManager() {
> > String start(String conversationID); // If the conversationID is
> > null, the system will generate one. Returns the conversation ID
> Conversation startConversation(Object conversationID) as the
> conversation ID is not always a String.
>
> Change start to startConversation to make clear that it's the
> conversation that you're starting and not the ConversationManager.
>
> Also I think it's better to return the Conversation object (see below
> for its contents).
Why don't we register a Conversation object with a ConversationManager and
do away with getConversationState
> void end(String conversationID); // Ends the conversation
>
> void endConversation(Conversation conversation)
>
> Don't you need another method to make a conversation expire?
>
> > ConversationState getConversationState(String conversationID); //
> > Get the state of the conversation
>
> Conversation getConversation(Object conversationID)
+1
> void register(ConversationListener listener); // Register a listener
> > void unregister(ConversationListener listener); // Remove a listener
>
> Let's try to be consistent with other listener interfaces:
> addListener(ConversationListener listener)
> removeListener(ConversationListener listener)
>
> Also, these methods should be on the Conversation object described below
> I think.
> }
> >
> > public interface ConversationListener() {
> > void conversationStarted(String conversationID);
> > void conversationEnded(String conversationID);
> > void conversationExpired(String conversationID);
> > }
>
> Pass Conversation conversation instead of String conversationID.
>
> If the methods are on the Conversation object instead of the
> ConversationManager they can be simpler I think:
> public interface ConversationListener() {
> void conversationStarted();
> void conversationEnded();
> void conversationExpired();
> }
>
> > public enum ConversationState {
> > STARTED, ENDED, EXPIRED
> > }
>
> class Conversation {
> ConversationState state;
> Object conversationID;
> }
>
> Having this class allows you to evolve it over time, does not rely on
> the fact that conversations are stored in a map, and also IMO better
> represents what you'll store in persistent storage in the future.
>
> Do we we need an expiry time field here as well?
>
> >
> > 2) The proxy or callable references will only keep the conversation
> > ID. Whenever the Conversation object is referenced or we need to
> > perform any actions to a conversation, we use the ID to look up the
> > state of the conversation.
> >
> > 3) Move the expiration timer from the ConversationScopeContainer to
> > the ConversationManager.
>
> If different Conversations can have different expiration timers then the
> timer needs to be on the Conversation object instead of the
> ConversationManager.
> >
> > 4) The ConversationScopeContainer will be registered as listener to
> > the ConversationManager. When an active conversation is started,
> > expired or ended, the ConversationScopeContainer will be notified.
>
> It might be easier to register the actual instance wrapper wrappering
> the component instance associated with a particular conversation.
An instance wrapped could be registered as a listener with multiple
conversations.
>
> > 5) The ConversationManager maintains the conversations using an
> > in-memory Map as the first step. In the future, it can be extended to
> > backed by a persistent store.
>
> +1 to use an in-memory map for now.
>
> >
> > Thanks,
> > Raymond
> >
> > ----- Original Message ----- From: "Simon Laws"
> > <[EMAIL PROTECTED]>
> > To: <[email protected]>
> > Sent: Sunday, September 09, 2007 11:10 AM
> > Subject: Re: Resetting state of service references at conversation end
> >
> >
> >> Hi Raymond
> >>
> >> some comments below...
> >>
> >> Simon
> >>
> >> On 9/9/07, Raymond Feng <[EMAIL PROTECTED]> wrote:
> >>>
> >>> Hi,
> >>>
> >>> I have been thinking of this problem as well. It's not realistic to
> >>> search
> >>> for all CallableReferences because it can be dynamically created
> >>> too. We
> >>
> >>
> >> Agreed. You would have to have registered them somewhere first. This
> >> is what
> >> happens in the case of the conversation scope container currently.
> >>
> >> probably need to use a listener pattern to have all the Conversation
> >> objects
> >>> listen on the events of expiration or end of the conversation and
> reset
> >>> the
> >>> state based on the event. Another way is to have a pointer to the
> >>
> >>
> >> This would rely on having the conversation object register with
> >> something
> >> that is able to broadcast these events. Where would be a sensible
> >> place to
> >> put this event broadcasting function. Do we have an internal eventing
> >> feature? Scope container?
> >>
> >> ScopeContainer in the ConversationImpl object and query the state of
> the
> >>> conversation before it's used.
> >>
> >>
> >> This would still involve updating the scope containers to record the
> >> conversation status against conversation id. But maybe this is an
> easier
> >> generic change. I.e. instigate a collection at the abstract level that
> >> allows conversationIds to be assoicated with the conversation object
> >> that
> >> created them.
> >>
> >> You could just store the conversation state and allow the
> >> conversation to
> >> ask for it as you suggest. Not clear to me what this buys though.
> >>
> >> By the current design, the ConversationScopeContainer is per
> >> component to
> >>> keep implementation instances by conversation id. So when the same
> >>> conversation involves two components, there are two
> >>> ConversationScopeContainer instances.
> >>>
> >>
> >> I think this design is sound. The missing link for us it so be able to
> >> access a conversation object given conversationId during callback at
> the
> >> client end.
> >>
> >> Thanks,
> >>> Raymond
> >>>
> >>> ----- Original Message -----
> >>> From: "Simon Laws" <[EMAIL PROTECTED]>
> >>> To: "tuscany-dev" <[email protected]>
> >>> Sent: Sunday, September 09, 2007 4:15 AM
> >>> Subject: Resetting state of service references at conversation end
> >>>
> >>>
> >>> > When @ConversationEnd is called on a satefull callback the
> >>> conversation
> >>> id
> >>> > of the client reference is not reset back to null. I have put a
> >>> fix in
> >>> in
> >>> > the case where the scope of the originating component is
> >>> CONVERSATION.
> >>> > This
> >>> > relies on storing the Conversation object in the conversational
> scope
> >>> > container so that when the instance is marked for removal the
> >>> conversation
> >>> > id can be set to null also.
> >>> >
> >>> > However to make this approach work for all scopes I have to go and
> >>> add
> >>> > this
> >>> > feature to the other scope containers. Before I do this is there
> >>> an > easy
> >>> > way
> >>> > to get to all of a component instances CallableReferences from the
> >>> > JavaImplementationInvoker? If there were I could search for the
> >>> > conversation
> >>> > object with the matching conversationId rather than adding extra
> >>> code > to
> >>> > store it away.
> >>> >
> >>> > Simon
> >>> >
> >>>
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: [EMAIL PROTECTED]
> >>> For additional commands, e-mail: [EMAIL PROTECTED]
> >>>
> >>>
> >>
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
>
>
> --
> Jean-Sebastien
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>