View Full Version : Spring Nested Commands
pbsr
Jun 3rd, 2006, 01:59 AM
I am building an application using AbstractWizardFormController. The properties of the controller only allows me to set a command class but doesn't allow to set a bean.
I want to have a nested command bean like this
Application Bean
Customer Info Bean
Address Bean
...
I have defined this relationship in the xml.
If I just put the "Application Bean" class name in the command class property of the controller, the nested objects would not be intialised. I could initialise them in the contructor on the main command bean, but it woudn't be IOC.
How do I inject the fully intialised bean into the controller. Is there any specific reason why this is not allowed. When I can wire validators why not allow to wire command beans.
Please excuse my knowledge gaps since I am new to spring.
pbsr
Jun 3rd, 2006, 03:56 AM
I kind of achieved this by overriding formBackingObject method and retreiving the bean from the ApplicationContext.
Using this method I did not define the CommandClass property of the Controller.
Is this the correct way to it? Comments will be greatly appreciated.
Mark Fisher
Jun 3rd, 2006, 09:55 AM
It's normally not necessary to use IoC for instances of domain objects. IoC is well-suited for configuring dependencies on coarse-grained "services", "data-access objects", etc. Can you briefly explain why you think it is necessary in this case to retrieve your command object from the ApplicationContext and/or show the relevant part of the configuration for the command object?
pbsr
Jun 3rd, 2006, 10:09 AM
Thanks for your reply.........
My bean configuration is like this
<bean id="personalInfo"
class="xxx.command.CustInfoBean" />
<bean id="currentAddress"
class="xxx.command.AddressInfoBean" />
<bean id="previousAddress"
class="xxx.command.AddressInfoBean" />
<bean id="employment"
class="xxx.command.Employment" />
<bean id="employerAddress"
class="xxx.command.AddressInfoBean" />
<bean id="financial"
class="xxx.command.FinancialBean" />
<bean id="electronicAccess"
class="xxx.command.ElectronicAccess" />
<bean id="balanceTransfer"
class="xxx.command.BalanceTransfer" />
<bean id="creditcardApp"
class="xxx.command.CreditCardApplicationCommand">
<property name="personalInfo">
<ref bean="personalInfo" />
</property>
<property name="currentAddress">
<ref bean="currentAddress" />
</property>
<property name="previousAddress">
<ref bean="previousAddress" />
</property>
<property name="employment">
<ref bean="employment" />
</property>
<property name="employerAddress">
<ref bean="employerAddress" />
</property>
<property name="financial">
<ref bean="financial" />
</property>
<property name="electronicAccess">
<ref bean="electronicAccess" />
</property>
<property name="balanceTransfer">
<ref bean="balanceTransfer" />
</property>
</bean>
I want to use "xxx.command.CreditCardApplicationCommand" as my command bean in the controller. As far as I know I could have done this two ways..
1. In the controller configuration specify "xxx.command.CreditCardApplicationCommand" as commandClass property and in the constructor of the command bean initialise all the private variabled to associated nested beans.
2. define all wiring in the xml and retreive it from the application context.
Which one is correct/better?
Mark Fisher
Jun 3rd, 2006, 10:32 AM
Typically, a controller will be injected with a service which in turn has been injected with a data-access object. For an "update" controller the formBackingObject(..) method might be responsible for retrieving the object from the persistence layer via the service - such as your "creditCardApplication" object - with all nested properties already set (including both primitives and objects). If the form is used for adding new instances (looks like the case here), then you need to provide an object which is initialized with proper defaults (may require empty collections for example). If those defaults always apply for that particular object then it's probably best to initialize in the constructor. If the defaults vary widely based on use-case, then you may want to add that behaviour to the formBackingObject(..) method. In either case, you should be able to rely on your domain objects without a proliferation of web-tier-specific command objects, and at the level of domain instances, you should minimize or eliminate dependencies on Spring.
pbsr
Jun 3rd, 2006, 10:37 AM
Thanks. Makes sense.
infinity2heaven
Jan 3rd, 2007, 12:44 PM
I have the same problem while designing 4 pages with AbstractWizardFormController. As all my data is from my domain object and its corresponding associations, I would like my command bean to be the domain object itself. However Spring forces you to have your collections initialised, so when I tried to modify my constructor by intialising with a new object for each association
Say ParentObject has 2 collections col1, col2
ParentObject()
{
col1.add(new childobject1());
col2.add(new childobject2());
}
I did the same for the nested childobjects by changing their constructors.
But I think Spring forces you to have default empty constructors as I got this exception when I ran the above
org.hibernate.InstantiationException: could not instantiate test object xxx.ParentObject
How do I solve this? My final goal is to be able to access from my parentobject all the nested properties, collection objects like
my jsp to which I have my domain object ParentObject as command class
<td><form:input path="childobject[0].property1" /></td>
One hack probably is to have a wrapper on my domain object as a seperate command object and have additional constructor which takes an argument (still have a default empty contr) to initialise my domain objects but I find this rather stupid!
Also see my earlier post related to this http://forum.springframework.org/showthread.php?t=33115 a
still awaiting for some replies :(
infinity2heaven
Jan 3rd, 2007, 05:24 PM
Got this working!
As I didn't want to mess up my domain objects too much with spring specific implementation, I added an extra constructor with ParentObject(boolean initialize)
In your Controller override formBackingObject (I didnt do this previously)
protected Object formBackingObject(HttpServletRequest request) throws ServletException {
ParentObject parent = new ParentObject(true); return parent ;
}
Make sure that your entire graph of objects has an extra constructor which initializes with an empty object.
Once done, you can access the entire nested graph directly using <form:form> tag using the index notation for collection objects
vBulletin® v3.7.3, Copyright ©2000-2009, Jelsoft Enterprises Ltd.