Let&#39;s try it the other way around. I toss you the minimal JSF-centric API and the <b>framework reps of ZK, GraniteDS, SE and Remoting can speak up on what they need more control of along with their usecase</b> then Pete can comment and I just act as a secretary ;-) That way we don&#39;t end up with too many &quot;nice to haves&quot; in the API that could be worked around more or less easy.<br>
<br>public interface ConversationManager<br>{<br>   /**<br>    * Checks the state of the conversation context<br>    * <br>    * @return true if the conversation context is active, false otherwise<br>    */<br>   public abstract boolean isContextActive();  <br>
// usecase: the conversation checks for active context before running methods<br>   <br>   /**<br>    * Activates the conversation context<br>    * <br>    * @return The conversation manager<br>    * <br>    * @throws IllegalStateException if the context is already active<br>
    */   <br>   public abstract ConversationManager activateContext();<br>// usecase: any non-JSF framework will want to run this themselves<br>   <br>   /**<br>    * Deactivates the conversation context<br>    * <br>    * @return The conversation manager<br>
    * <br>    * @throws IllegalStateException if the context is already deactive<br>    */   <br>   public abstract ConversationManager deactivateContext();<br>// usecase: any non-JSF framework will want to run this themselves<br>
<br>   /**<br>    * Resumes a long running conversation. If the cid is null, nothing is done and the current<br>    * transient conversation is resumed<br>    * <br>    * <br>    * @param cid The conversation id to restore<br>
    * @return The conversation manager<br>    * @throws NonexistentConversationException If the non-transient conversation is not known<br>    * @throws BusyConversationException If the conversation is locked and not released while waiting <br>
    * @throws IllegalStateException if the conversation context is not active<br>    */<br>   public abstract ConversationManager beginOrRestoreConversation(String cid);<br>// usecase: start of the conversation lifecycle.<br>
   <br>   /**<br>    * Destroys the current conversation if it&#39;s transient. Stores it for conversation <br>    * propagation if it&#39;s non-transient<br>    * <br>    * @return<br>    * @throws IllegalStateException if the conversation context is not active<br>
    */<br>   public abstract ConversationManager cleanupConversation();<br>// usecase: end of the conversation lifecycle.<br>   <br>   /**<br>    * Gets the current non-transient conversations<br>    * <br>    * @return The conversations mapped by id<br>
    * @throws IllegalStateException if the conversation context is not active<br>    */<br>   public abstract Map&lt;String, Conversation&gt; getConversations();<br>// usecase: Conversation checks if begin(String) was called with a known cid (no need for a isCidInUse, actually)<br>
<br>   /**<br>    * Returns a new, session-unique conversation ID<br>    * <br>    * @return The conversation id<br>    * @throws IllegalStateException if the conversation context is not active<br>    */   <br>   public abstract String generateConversationId();<br>
// usecase: Conversation gets a cid for begin()   <br><br>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 ;-) <b>Re-submit any wishes/suggestions you&#39;ve done in the past</b> in this thread (method signature + usecase) so we can keep stuff together.<br>
<br>---<br>Nik<br><br>