PDA

View Full Version : Eagerly init session controllers


opsb
Apr 21st, 2006, 09:19 AM
In my project the majority of controllers sublcass SimpleFormController and have their sessionForm attribute set to true.

As far as I can tell these controllers are initialised the first time a user visits the associated url.

I would like to be able to change properties on these controllers before the first time their associated url is visited i.e. I want them to be eagerly initialised when a new session is created. Is there any way to do this?

michaelbaranov
Apr 21st, 2006, 10:47 AM
Hi!

Maybe there is a way to lazy-initialize your beans? What kind of information is immediately available on session creation that you want to use to instantiate ALL session beans?

Michael

opsb
Apr 21st, 2006, 11:58 AM
My query comes from a practice I used to use when using jsf. In this case all session scoped beans were available as soon as the session was created. I would then inject different backing beans (controllers in this case) into each other as a means by which I could pass information around.

This would work with spring mvc except for one thing. If I have controller B injected into controller A then I am able to easily pass information from A to B.

public class A extends SimpleFormController {
private B injectedB;

public void setB(B injectedB) {
this.injectedB = injectedB;
}

public void onSubmit(HttpServletRequest request, HttpServletResponse response) {
injectedB.setName("whatever");
}
}

public class B extends SimpleFormController {
private String name;

public void setName(String name) {
this.name = name;
}
}

However, if I have not already visited the url mapped to controller B then I am not manipulating a controller that is in session but in fact an instance of the controller which is shared between all users. That is to say that if I call setName() on controller B I am setting a field which is shared across the entire application and not just an instance in session.

So the question is how to have B initialised in session so that it is available before I have visited it?

What do people think about this approach, is there a better way to get the information between the two controllers? (without having to use hidden fields etc.)

michaelbaranov
Apr 21st, 2006, 02:01 PM
Hmm.. there may be a slight mismatch in JSF/Spring concepts. FAIK in JSF a backing bean is a controller AND a data model at the same time. In Spring controllers are usually instantiated eagerly as singletons. They use form beans as data holders (those which get populated on requests by AbstractFormController). IMHO, the property sessionForm of AbstractFormController actually controls instantiation of the form bean (data bean):

From javadoc API for AbstractFormController:
"Form controller that auto-populates a form bean from the request. This, either using a new bean instance per request, or using the same bean when the sessionForm property has been set to true."
and
"If sessionForm is not set, formBackingObject() is called to retrieve a form object. Otherwise, the controller tries to find the command object which is already bound in the session. If it cannot find the object, it does a call to handleInvalidSubmit which - by default - tries to create a new form object and resubmit the form."

So this is the form bean which is passed around in the session.
So AFAIK there is no separate controllers for different sessions, just singletons.

Actually all thie info does not solve the inter-controller comunication problem... Obviously this is achieved through the session. I'm also interested in finding a good solution to this, so if you get one, please post it here!!! :-)

Michael.

opsb
Apr 22nd, 2006, 12:24 PM
I should probably have mentioned that I've distorted the way in which spring mvc controllers behave. I have my own super controller which extends SimpleFormController and makes it behave in a more jsf fashion. This is done in 2 ways:

1) fromBackingObject() actually returns 'this'. That is to say the controller is the command object.

2) The name attribute on the submit button encodes several values as key=value pairs and is identified using a .action extension. These values include the name of the method to call, whether to bind, whether to validate and optionally a view to display next backed by the same controller.

I adopted this approach because I like the way jsf views bind to objects with methods and properties (this seems very OO). In addition if I am able to inject controllers into each other as mentioned before and thus pass information between them. This works fine so long as each controller only refers to another controller that has been visited previously.

I'm looking to solve the case of a controller referring to another controller that hasn't yet been visited.

opsb
Apr 27th, 2006, 10:35 AM
It turns out that as of milestone 3 this problem no longer exists. You are now able to scope spring beans in session or request. Take a look at http://wiki.opensymphony.com/display/WW/Spring+Session+Components+Workarounds.

tobysaville
Apr 28th, 2006, 04:22 AM
after your last reply, im not sure if you still require an answer, but ill post my 2 cents anyway.

Can you create a SessionContextListener implementation, then in your sessionCreated method, create a new instance of the controller, retrieved from the Spring WebApplicationContext, then save it into a session variable that has the following name:

com.my.package.MyControllerName.FORM.mycmdobjectna me

in the above name, its the fully qualified name of the controller, followed by the contsant ".FORM." followed by the name of your command object. This is where spring looks for its form controllers.

not sure if that even works, but maybe.

cheers, toby