Right for the ConversationManager.beginConversation, there is already Conversation.begin. I've been mistaken by the ConversationManager.endConversation of Niklas' proposal.

I can maybe explain how we use the currently existing API, and in fact we are relatively happy with what exists today, except for one thing :

start() {
    ConversatonManager manager = { get from BeanManager };
    manager.beginOrRestoreConversation(cid);
    Conversation conversation = { get from BeanManager };

    // Beginning of the ugly part !!
    String cid = ((ConversationImpl)conversation).getUnderlyingId();
    ConversationContext ctx = Container.instance().deploymentServices().get(ContextLifecycle.class).getConversationContext();
    ctx.setBeanStore(new ConversationBeanStore(httpSession, cid));
    ctx.setActive(true);
    // End of the ugly part

    if (cid != null && conversation.isTransient())  // Don't remember why I need this, beginOrRestore should be enough
        conversation.begin(cid);
}

end() {
    ConversationManager manager = { get from BeanManager };
    manager.cleanupConversation();
}

The main thing is that I would prefer not having to mess with bean stores and contexts, so the manager.activateContext() looks fine. Ideally here what I would like to do (I know, I'm too lazy :-)) : 

start() {
    ConversatonManager manager = { get from BeanManager };
    manager.startupConversation();

    if (cid != null && conversation.isTransient())
        conversation.beginOrRestoreConversation(cid);
}

end() {
    ConversationManager manager = { get from BeanManager };
    manager.cleanupConversation();
}

From Flex, there is no need to switch the conversation in a particular request, but getting the list of the currently existing conversations with ConversationManager.getCurrentConversationIds() can be useful.

Finally I really think it's necessary to be able to share a conversation instance between different UIs and use the same ConversationContext implementation for all. We could obviously ship a FlexConversationContext with GraniteDS/CDI but we want to make possible to build applications where a part of the UI uses JSF, another part uses Flex and why not another uses ZK or the iPhone SDK.

William



Let's try it the other way around. I toss you the minimal JSF-centric API and the framework reps of ZK, GraniteDS, SE and Remoting can speak up on what they need more control of along with their usecase then Pete can comment and I just act as a secretary ;-) That way we don't end up with too many "nice to haves" in the API that could be worked around more or less easy.

public interface ConversationManager

{
  /**
   * Checks the state of the conversation context
   *
   * @return true if the conversation context is active, false otherwise
   */
  public abstract boolean isContextActive();  
// usecase: the conversation checks for active context before running methods

 
  /**
   * Activates the conversation context
   *
   * @return The conversation manager
   *
   * @throws IllegalStateException if the context is already active
   */  
  public abstract ConversationManager activateContext();
// usecase: any non-JSF framework will want to run this themselves

 
  /**
   * Deactivates the conversation context
   *
   * @return The conversation manager
   *
   * @throws IllegalStateException if the context is already deactive
   */  
  public abstract ConversationManager deactivateContext();
// usecase: any non-JSF framework will want to run this themselves

  /**
   * Resumes a long running conversation. If the cid is null, nothing is done and the current
   * transient conversation is resumed
   *
   *
   * @param cid The conversation id to restore
   * @return The conversation manager
   * @throws NonexistentConversationException If the non-transient conversation is not known
   * @throws BusyConversationException If the conversation is locked and not released while waiting
   * @throws IllegalStateException if the conversation context is not active
   */
  public abstract ConversationManager beginOrRestoreConversation(String cid);
// usecase: start of the conversation lifecycle.
 
  /**
   * Destroys the current conversation if it's transient. Stores it for conversation
   * propagation if it's non-transient
   *
   * @return

   * @throws IllegalStateException if the conversation context is not active
   */
  public abstract ConversationManager cleanupConversation();
// usecase: end of the conversation lifecycle.
 
  /**
   * Gets the current non-transient conversations
   *
   * @return The conversations mapped by id

   * @throws IllegalStateException if the conversation context is not active
   */
  public abstract Map<String, Conversation> getConversations();
// usecase: Conversation checks if begin(String) was called with a known cid (no need for a isCidInUse, actually)

  /**
   * Returns a new, session-unique conversation ID
   *
   * @return The conversation id

   * @throws IllegalStateException if the conversation context is not active
   */  
  public abstract String generateConversationId();
// usecase: Conversation gets a cid for begin()  

Notice that the begin and end of lifecycle are big chunks. Speak up where you need more granularity. Also speak up if you want fancy switching stuff etc ;-) Re-submit any wishes/suggestions you've done in the past in this thread (method signature + usecase) so we can keep stuff together.

---
Nik