PDA

View Full Version : Multiple wizards open at same time / Session state



gmatthews
Sep 12th, 2004, 10:01 PM
What's best practice for allowing a user to edit 2 or more multi-view (AbstractWizardFormControllers) at the same time.

I want to have 2 tabbed pages open at the same time without session state for one of them being clobbered. e.g. editing record id=1 in one browser, and editing record id=2 in another browser (and no, we can't force users to open a new browser completely -- they will be right clicking on links and selecting open in new tab/window).

I don't really want to always put all state as hidden fields in the view since i'm also playing around with overriding the formBackingObject method so that I can fork to other use-cases and then return to the calling use-case with it's state intact. e.g. leaving a tabbed page to go to a search page, doing a search, then putting the selected value in some field back in the tabbed page. The search page would be called from several use-cases throughout the system so i don't really want to build it into the calling AbstractWizardFormController as one of it's pages.



// formBackingObject() check if request param present.
// note that isReturning just checks for presence of some
// param that is included when we return from somewhere
// using a GET
if(isReturning(request)) {
return request.getSession(false).getAttribute(this.getFor mSessionAttributeName());
}
return super.formBackingObject(request);



Maybe if it were possible to override the session attribute name, then state for 2 or more AbstractWizardFormController could be stored.

e.g. getFormSessionAttributeName() could somehow be customised to return:

com.myco.myproj.controller.MyEditPageController.fo rm.command.id1
and
com.myco.myproj.controller.MyEditPageController.fo rm.command.id2

where id1 and id2 have been added by some code I write in my controller through some new template method like getFormSessionAttributeSuffix() or something.

Any ideas?

egervari
Sep 12th, 2004, 11:47 PM
I ran across this problem too actually and put up a post on the old sourceforge forums, but nobody replied. After I looked into the code and writing my own mvc framework, I realize that the problem is not easily solvable with the current Spring code base.

One way I thought about fixing this is to keep a request attribute or parameter with a key value, just like you suggest, and to have to have the session data for each form controller indexed by the controller name and that key, however this means that the controller implementer needs to be aware of this fact and it becomes harder to make session-based forms, so I never implemented it either although I spent some time thinking about the problem. Manageing the key poses similar problems, what happens if it's not posted or set for each form request? It's just a messy problem. If the key approach worked even, you wouldn't need to have the controller's name in the session name in the first place.

It's unfortunate that it's not solved conveniently (or the Spring team would have solved it already) because it's really a problem with HTTP and state management. Even if they did find a good way around it, it probably wouldn't be backwards compatible. I just told one of my customers they can't do it since the one that requested didn't pay all that much for the application in the first place. I hate to say that to customers, but I have to be practical.

Anyway, hope that helps in some way.

msqr
Sep 23rd, 2004, 07:07 PM
Is it possible for you to use different command names for your two form controllers instead of using the default of 'command'? Then the session keys will be different for each one since the session key is defined as


getClass().getName() + ".form." + getCommandName()

daniel.dent
Sep 23rd, 2004, 10:13 PM
Is it possible for you to use different command names for your two form controllers instead of using the default of 'command'? Then the session keys will be different for each one since the session key is defined as

Code:
getClass().getName() + ".form." + getCommandName()



The doesn't solve the more likely occurence when you have the same wizard form open in the 2 browsers with the same state. It is something that would have to be changed in Spring i think to solve the issue. I'm pretty sure even Aurora has the same problem with it's wizards, which sucks, because that is what i use.

msqr
Sep 24th, 2004, 12:01 PM
The doesn't solve the more likely occurence when you have the same wizard form open in the 2 browsers with the same state. It is something that would have to be changed in Spring i think to solve the issue. I'm pretty sure even Aurora has the same problem with it's wizards, which sucks, because that is what i use.


What I mean is can you use two definitions of the same wizard form class, each using a different command name. Sort of like this:


<bean name="addIngredientForm" class="foo.web.AddIngredientForm">
<property name="pages">
<list>
<value>edit-ingredient</value>
<value>validate-ingredient</value>
</list>
</property>
<property name="commandName"><value>editIngredient</value></property>
</bean>
<bean name="addIngredientForm2" class="foo.web.AddIngredientForm">
<property name="pages">
<list>
<value>edit-ingredient</value>
<value>validate-ingredient</value>
</list>
</property>
<property name="commandName"><value>editIngredient2</value></property>
</bean>

This would mean the view would need to distinguish between the two, but that's not too difficult.[/code]

sqrrrl
Sep 27th, 2004, 11:29 PM
I also did some prelimary work here and was able to get something simple working very quickly using an extra form parameter to discriminate between instances. But there's one issue that bothers me about this -- memory consumption.

The normal spring approach, while limited in functionality, has the nice advantage of limiting the amount of memory any given session consume to the number of distinct forms. Allowing for different instances removes this constraint, and a malicious, or just ignorant user could just keep revisting the form page without actually submitting it, using more and more memory each time. I'm not terribly worried about malicious users since they can just as easily exahust memory by establishling lots of sessions, but I'm really worried about doing something that normal users would trip over.

I played around with trying to cap the number of entries, but then the problem comes down to how/when to evict old form data. The code isn't terribly difficult, its just a question of picking the right policy. Something like keeping the N most recent forms would work reasonably well, I think, but I haven't gotten around to trying it yet.

Anyway, if anyone has any thoughts on the issue let me know. If the N most recent approach sounds reasonably I'll gladly finish the changes and share the code for whoever wants it.

nullPainter
Jul 14th, 2006, 12:53 AM
I've just had a similar issue in my application where two views of the form controller are possible.

The solution is similar to msqr's, but to avoid having to re-code my JSPs to account for the different command name, I simply introduced another bean parameter to my form class, set this attribute in the form controller definition and overrode getFormSessionAttributeName().

Example:



<bean id="disposalAuthorityFormController" class="nz.govt.archives.archwaystaff.web.disposalauthorit y.DisposalAuthorityFormController">
<property name="formView"><value>disposalAuthorityForm</value></property>

<property name="sessionKey"><value>workQueue</value></property>
</bean>

<bean id="disposalAuthorityFormControllerFromSearch" class="nz.govt.archives.archwaystaff.web.disposalauthorit y.DisposalAuthorityFormController">
<property name="formView"><value>disposalAuthorityForm</value></property>

<property name="sessionKey"><value>search</value></property>
</bean>
and in the controller:


protected String getFormSessionAttributeName() {
return getClass().getName() + ".FORM." + getSessionKey();
}