Hi, I've used wizard pattern in my web application (written in standard technologies specified in JEE). I have encountered popular problem using CDI's @ConversationScoped. When conversation expires JSF throws ViewExpiredException or NonexistentConversationException. Yeah, I can make custom error page or exception handler, but these solutions are not complete in my honest opinion. Why? Let assume that I have several different wizards - for each of them the same error page because of timeout? I have written my own exception handler for NonexistentConversationException but I cannot identify jsf page / bean being cause of the error. It's difficult to understand for me. In the first place why session/conversation timeout is treated as error? It makes no sense for me. I am using newest Mojarra as JSF's implementation and GlassFish 3 as container. Am I forced to make just one error page for several different cases?
I've started to wonder if it would be better to abandon learning JSF 2 already. Solving one problem means encountering another one. It's painful.
Thank you for your time - it's my first topic here :)
JSF doesn't throw ViewExpiredException just for the fun of it. JSF expires Views because the more Views it remembers, the more resources are required to remember them. You can adjust for this problem by tweaking the FacesServlet parameters in the WEB-INF/web.xml file, both in terms of how long the View is retained and whether the information is retained on the client (more conversations are possible at the cost of security and network overhead) or on the server (more server memory required to hold the conversations, but more secure and less network traffic).
The reason you cannot get the offending backing bean's name is that JSF does not mandate a 1-to-1 correspondence between backing bean IDs and backing bean classes. While the majority of times there is 1 ID matched to 1 bean instance, it is perfectly legal to use the same class for multiple bean instances, each of which must have a unique ID. The IDs are mapped to their instances in a Map, which is the HttpSession object for that user, and there is no reverse lookup function for that Map.
View timeouts are not handled very gracefully in the current J2EE specs. Essentially you will still have to deal with them yourself, regardless of what server and JSF version you are using. There are various helpful bits of code for this if you search the web, however. They must suffice until the standard incorporates something more elegant. ViewExpiredExceptions shouldn't normally be that much of a problem, however, since the default settings are good enough except for people who are only communicating with the webapp every 15 minutes or so,
I'm not certain whether your particular implementation of the Wizard pattern is JSF-friendly or not, but if you are attempting to use CDI Conversation Scope on a JSF backing bean, be sure that it is being mapped to an actual JSF scope, and in particular that it is NOT mapped to Request Scope, which is almost, but not quite completely 100% useless in JSF. My wizard implementations in JSF are more likely to consist of a series of Views, each backed by a View Scoped backing bean and each of those View Scoped backing beans would in turn have a master wizard bean injected as a Managed Property in order to hold the context of the entire conversation. The master wizard bean has to have session scope in order to be able to retain information as you move from View to View.
An IDE is no substitute for an Intelligent Developer.
Joined: Apr 20, 2013
Thanks for your reply.
Yeah, I am aware that throwing exception by JSF has reason, but I am surprised that it's not given to me in a way that I could handle it more elegant. I wish it will be changed for better in the near future.
My sample implementation of wizard pattern consist only of 2 @conversationscoped backing beans which begin and end conversation.
Sorry, Hubert. I'm not as alert as I should be at this time of day. People get my name wrong in all sorts of creative ways, too. :)
I read up on ConversationScoped in JSF, and the Number One issue I have is whether or not all that functionality is available in the particular release of your web application server. Your chances are fairly good with a recent GlassFish, but I wouldn't be so optimistic if it was something like Tomcat.
My preference for a master object to co-ordinate Wizard activities is actually a lot older than web-based Wizards. It just makes sense to me to have whatever you are assembling all in one place, which you can then augment on a per-view basis according to whatever the current view requires.
However, as far as having the view component objects expire in the middle of the conversation, about the best advice I can offer is to either tweak the server settings to reduce the likelihood of timeout, analyse what the users are doing that cause then to time out so frequently and see if you cannot adjust the workflow to allow for them, and/or exert the effort needed to intercept and handle the timeouts gracefully.
While it would be nice if the framework provided better support for expired views and conversations, at least it is possible to deal with them.