Setting the conversation-timeout in Seam, why it really does work
December 13, 2007
Conversation timeout seems to be a commonly misunderstood Seam concept. I often see postings on the Seam forums claiming that the conversation-timeout doesn’t work! Well, actually it does, you simply have to understand the semantics.
Configuring the conversation-timeout period can be accomplished through the following in your components.xml:
<core:manager conversation-timeout="900000" />
At first glance most developers relate conversation-timeout to session timeout, where any conversation will simply timeout after the configured conversation timeout period. As you will quickly notice during testing, this is not the case. To execute a quick experiment, try the following configuration in the components.xml of the seam-booking example:
<core:manager conversation-timeout="60000" />
Because the conversation-timeout is set in milliseconds, the above configuration sets the conversation-timeout to 1 minute. Now in the web.xml set the session timeout to 5 minutes:
<session-config> <session-timeout>5</session-timeout> </session-config>
Now in the destroy method of the HotelBookingAction add the following line:
...
@Destroy @Remove
public void destroy() {
log.info("Destroying HotelBookingAction...");
}
...
This will log our message when the conversation ends and the HotelBookingAction is destroyed. Now deploy the seam-booking example to your local JBoss instance and start up a conversation. This can be accomplished by logging in, navigating to the hotels listing, and selecting a hotel for booking. At this point, wait for the 1 minute period… nothing happens. Now wait for another 4 minutes, the message is displayed. The conversation timed out along with the session.
Foreground vs. Background Conversations
So why didn’t our conversation timeout as configured? This is because the conversation-timeout only affects background conversations. The foreground conversation will only timeout when the session times out. Foreground, background, what? The foreground conversation is the conversation that the user last interacted with. A background conversation is any other conversation in the user’s session. Thus, in our previous scenario the foreground conversation timed out with the session as expected.
Now lets try another approach. Perform the same steps as before to proceed to the booking screen. Now open a new window and perform the same steps. We now have a foreground conversation and a background conversation in progress. Again, wait 1 minute. Nothing happened. If you wait an additional 4 minutes, both conversations will timeout. So what is going on here, I thought we had a background conversation? We did, Seam simply checks the conversation timeout on each request. Thus, if I interact with the foreground conversation after 1 minute, the background conversation times out. Try it, perform the same steps, wait 1 minute and then click on the window of the foreground conversation and you will see the log message.
This is very desirable behavior. Essentially when a user leaves his or her desk for a period of time and comes back, if the session is still active it would be desirable to maintain the state the user was previously in. This is the foreground conversation state. All other background conversation state is left to timeout after the configured conversation-timeout period which reduces overall memory consumption. This enables a developer to think less about memory usage and cleaning up state and more about developing business logic. That’s why we’re here right?
Letting the user choose
So you may be asking at this point why the conversation-timeout doesn’t use polling. As we said, you must interact with the foreground conversation to cause the background conversations to timeout after the conversation-timeout period. Imagine that the user had many windows open and leaves his or her desk. Based on which window the user clicks on when they return, that becomes the foreground conversation timing out any other background conversations. This gives the user a chance to resume whichever conversation he or she chooses, not the one the developer chooses.








Posted in 


content rss
December 14th, 2007 at 5:51 am
Jacob,
Interesting article and contains very useful info. It will help to also show how different conversations (parent/nested) on the conversation stack time-out based on the specified conversation time out. Use 2-3 different scenarios.
December 14th, 2007 at 5:54 am
Jacob,
One point to note that if a parent conversation is the foreground conversation, then all of its children (or nested) conversations at any level of depth would not time-out. Am I correct?
December 14th, 2007 at 1:53 pm
That is definitely a good point. Nested vs. parent conversations presents a very interesting scenario for timeouts with respect to the conversation stack. I will post a follow up that discusses this point.
December 14th, 2007 at 1:57 pm
No, if a parent conversation is the foreground conversation, only conversations down the stack (toward the root) would now be in the foreground. Any conversations nested on the parent would now be background conversations. Let’s take the following scenario:
cid1 -> cid2 -> cid3
These are conversations on the stack. Let’s say that the user started cid3 but backs up to cid2 and begins to interact with the application again. cid2 is the foreground conversation, so cid3 (being nested on cid2) is now a background conversation. On the other hand, cid1 is the parent of cid2 so will not timeout.
As you can imagine, the more nesting is done, the more interesting the timeout scenario could get. Hope that helps.
December 14th, 2007 at 10:57 pm
I like to keep foreground conversation timeout as session-timeout, and background conversation timeout as conversation-timeout. It is reasonable in a real application. Since the background conversations mostly are those which users propagate away from. So it is better to let system to clear them in a short time.
However, it is hard to convert a foreground conversation to background one in an application, and start a new foreground conversation. So, it is difficult to apply conversation scenario in a real production application based on my understanding.
December 15th, 2007 at 2:15 am
The Seam booking example described in this posting demonstrates an approach to apply this in practice. If a hotel is selected a conversation is started. If the user then uses the back button or opens a new window and selects another hotel, a different conversation is started. The previous conversation becomes a background conversation which leaves it to timeout. You can refer to the source to see how this is accomplished. Hope that helps.
December 26th, 2007 at 10:29 am
Hi Jacob, Thank you for your reply. However, I think the booking example only works on the SAME foreground conversation bean, for example, I start a conversation A from Conversation Bean A by clicking @Begin from A, then if I go back to click @Begin from the same Conversation Bean A, Seam will start a new foreground conversation, BUT instead, if I go back to click @Begin from Conversation B, the whole system will throw exception (need @Begin (join=true)) and the system will be down.
December 26th, 2007 at 1:22 pm
I have not reproduced the bug you are describing. Have you modified the source of the example? If you are getting an exception with the booking example without modification to the source I would recommend reporting it in the Seam JIRA. Make sure you provide a reliable test scenario in the JIRA issue and someone will certainly have a look at it.
Essentially, if we discuss in the context of the booking example, a conversation should @Begin each time a hotel is selected on the main page:
... @Begin public void selectHotel(Hotel selectedHotel) { hotel = em.merge(selectedHotel); } ...If I was to use the back-button to return to the main view and select another hotel, an exception should not be thrown on selection. This is because by backing up, I am no longer in the context of a long-running conversation.
Due to this, selecting a hotel can safely @Begin a new foreground conversation without joining or nesting. The conversation I backed up from would then become a background conversation.
For more information on this, the article I wrote on nested conversations may help. It describes a little more in-depth how the current long-running conversation is determined when a user interacts with the view.
December 31st, 2007 at 5:29 pm
Hi Jacob, Please take a look on this post: Thank you and Happy new year!
January 8th, 2008 at 7:41 am
There is something I don’t understand in the paragraph:”Foreground vs. Background Conversations”
When we opened another window, isn’t this conversation supposed to be foreground conversation and the previous conversation is now a background one?
January 8th, 2008 at 8:29 am
Hi Hussein,
Actually in the booking example a long-running conversation is not started until a hotel is selected as shown in a previous comment. But, yes, the new window would be a foreground conversation as a temporary conversation is started when the main view is rendered and the previous conversation would now be a background conversation. The example steps you through starting long-running conversations so that it makes a little more sense to readers. Hope that helps.
Jacob
July 23rd, 2008 at 1:33 pm
This is a fantastic article. It’s a shame that Dan Allen spends 50 pages in his book and still doesn’t explain anything important leaving the reader confused.
July 23rd, 2008 at 1:46 pm
Thanks, I’m glad you enjoyed it! If you want even more, our book goes in-depth on the topic of conversations as well as many other topics (SMPCs, transactions, events, caching, etc). I like to make sure we give our readers what they really need to know. I hope you get a chance to read it!
August 22nd, 2008 at 4:00 am
Hi all onlines,
I am workng on JBoss-Seam. I want to change the message “User Session Timeout”. I just want to know that from whre this message comes and by which Event.
I am using icefaces. in my seam application.
Thanks.
February 15th, 2009 at 9:49 am
Hi,
this was definitely a very important article on an important Seam concept. It is covered briefly in Seam in Action:
“When a background conversation is restored using a switcher component, the conversation comes into the foreground and the user is redirected to the last view ID recorded for that conversation.”
However, it would be nice if a Seam book covered the Conversation API in depth. I am currently trying to write a generic component that will show a modalPanel as a warning to the user (similar to BofA when your session is about to timeout) when any background conversation is about to timeout (e.g. less than 1 minute to timeout). If they click the continue button, the app resets that LRC’s lastRequestTime.
I’m not sure how to determine how much time is left prior to timeout for any given LRC (whether foreground or background). I’ve looked at the conversationList and ConversationEntry API. This is not explained clearly anywhere.
It would be very nice if this info was added to the Seam ref doc.
Also, it would be nice to know exactly what does Conversation.instance() return.
here: http://docs.jboss.org/seam/2.1.0.GA/api/org/jboss/seam/core/Conversation.html
there is no description for the instance() method!
thx for the post Jacob!
February 15th, 2009 at 10:23 am
@Jacob:
regarding this statement:
“If a hotel is selected a conversation is started. If the user then uses the back button or opens a new window and selects another hotel, a different conversation is started. The previous conversation becomes a background conversation which leaves it to timeout.”
I have been doing Seam development since 1.2.1 and never knew that if you click the back button a different LRC is started. I always believed that if you used @Begin(join=true), then Seam would use the pre-existing LRC. In fact, a project I’m currently working on was exhibiting this behavior when using the browser back button many times and re-executing use cases (I would see more than the expected # of LRCs in the debug.seam page).
Wow, this really needs to be covered in the Seam ref doc. Not sure if I read this concept in Seam in Action or not…
February 15th, 2009 at 10:28 am
it would be VERY helpful if there was an enhancement done to the degug.xhtml such that a type column was added to indicate if each LRC was active or background, otherwise how do we know which one is the active one?
plus how does Seam handle activation of a background LRC? If the user click on a different tab, will it immediately become active or when an action on the page is taken (i.e. a4j:support even=”onblur”… or h:commandButton action fires submitting the form)?
February 15th, 2009 at 10:29 am
will there be an author’s forum for your new book like manning has for Seam in Action?
February 17th, 2009 at 7:55 am
Take a look at the ConversationEntry component. The time of creation and last accessed are there. You can retrieve all ConversationEntry instances through injection: @In List conversationEntries
Take another look
February 17th, 2009 at 7:59 am
=> JIRA. I have actually added this in a custom debug page I use and I agree, it can be helpful at times.
Once the conversation is accessed on the server-side through a request the conversation becomes foreground. So, if you were to use event=”onblur” with an AJAX request to a conversation context, then yes, that conversation would become foreground.
February 17th, 2009 at 8:01 am
There are no plans for this at the moment, but please send a request to Prentice if you feel this would be useful. Perhaps we could get something set up.