View Full Version : FormBacking object, Confused!
Encrypt
May 18th, 2007, 05:07 AM
Hi me again
I am a little confused.
I have several classes that I want to provide "create" froms for, to create a user for example.
Most if not all of these forms have a "status" value in a drop down (Which is a forign key in the DB).
No currently I have a hibernate mapping that, has the forign key, but also a non-updating version of the parent object associated though a many-to-one mapping.
In the form I use the drop down to populate the forigen key field.
something like this:
<fieldset>
<legend>Create User</legend>
<form:label for="name" path="name">name: </form:label>
<form:input id="name" path="name"/>
<form:errors path="name" cssClass="error" />
<br />
<form:label for="pword" path="password">password: </form:label>
<form:input id="pword" path="password"/>
<form:errors path="password" cssClass="error" />
<br />
<form:label for="role" path="userRoleOID">role: </form:label>
<form:select id="role" path="userRoleOID">
<form:options items="${roleList}" itemLabel="name" itemValue="OID"/>
</form:select>
<form:errors path="userRoleOID" cssClass="error" />
<br />
<input class="submit" type="submit" value="Create" />
<form:errors path="*" cssClass="errorBox" />
<br />
</fieldset>
<class name="User" table="cmt_006_user">
<id name="OID" column="OID" unsaved-value="null">
<generator class="native">
</generator>
</id>
<version name="VID" column="VID" unsaved-value="negative" type="long"/>
<property name="updated" type="timestamp" column="Updated"></property>
<property name="name" column="Name"></property>
<property name="password" column="Password"></property>
<property name="userRoleOID" column="UserRoleOID"></property>
<property name="deleted" column="Deleted"/>
<many-to-one name="userRole" class="UserRole" column="UserRoleOID" insert="false" update="false" lazy="false"/>
</class>
No that strikes me as a bit of a hack, so I removed the userRoleOID property, and set insert and update to true (in the hibernate mapping) and changed my html to:
<form:label for="role" path="userRole.OID">role: </form:label>
<form:select id="role" path="userRole.OID">
<form:options items="${roleList}" itemLabel="name" itemValue="OID"/>
</form:select>
<form:errors path="userRole.OID" cssClass="error" />
But I get an NullValueInNestedPathException, now I dont know if this is something I am doing wrong, or if I should be using a propertyEditor to solve this, to my mind, I should be able to do it as above, as userRole is a property of the formbacking object, and OID is one of its properies, so they should be "initialised" just like the user object is in a black form in my original hack.
Of course I could be compeletely missunderstanding, espically the hibernate stuff and setting insert true might be trying to insert a value into the userRole table, rather then upadting user's userRoleOID, but considering previous errors and examples, I dont think so.
Your going to tell me I need to create a propertyEditor arent you?? :)
Sorry for the verbose nature of the topic
Thanks
G
Jörg Heinicke
May 19th, 2007, 11:01 AM
Your going to tell me I need to create a propertyEditor arent you?? :)
Yes, I am :) You have a list of roles which must be converted to strings (the value in <option>) and back after having selected one. In your object you should have only userRole, not userRoleOID since the latter is an internal thing of userRole. The form:select should look like:
<form:select path="userRole">
<form:options items="${roleList}" itemLabel="name"/>
</form:select>
Jörg
Encrypt
May 20th, 2007, 06:12 AM
In your object you should have only userRole, not userRoleOID since the latter is an internal thing of userRole. The form:select should look like:
Jörg
Sorry that bit confused me. you mean in my domainObject that the form is trying use I should have a userRole object? If so check, had got that far :D
So, when creating this property editor, I need to override getAsText and setAsText? This is the bit I dont get cos obivously I want to getAsObject. Or the propertyEditor is for the userRole, and getAsText returns an object, and setAsText takes the object and returns the string values for the select box?
off to do more research thanks :D
G
Jörg Heinicke
May 20th, 2007, 06:45 AM
you mean in my domainObject that the form is trying use I should have a userRole object?
Yes, in your Hibernate mapping the many-to-one name="userRole" should be preserved, but you should drop the property "userRoleOID".
So, when creating this property editor, I need to override getAsText and setAsText? This is the bit I dont get cos obivously I want to getAsObject. Or the propertyEditor is for the userRole, and getAsText returns an object, and setAsText takes the object and returns the string values for the select box?
Yes, you only need to override getAsText() and setAsText(String) (http://forum.springframework.org/showthread.php?t=38957). They are used for the conversion of the object to string and back. A property editor has two additional methods getValue() and setValue(Object) (http://forum.springframework.org/showthread.php?t=38332&page=2#19).
Hope that wipes out the confusion :)
Jörg
Encrypt
May 20th, 2007, 07:31 AM
Yep no confusing over the abstract idea :D
bit lost on implementing it.
Usual I would use a SimpleFormConrtollers referenceData method to populate an object for the UserRole drop down, is this still correct in this way of doing things?
Is it the "id" vaules of the drop down it is converting, or the textual values the user sees in the dropdown field?
I see no way to get at the dropDowns "model object" to convert from the string value to the object (setAsText)
getAsText converts from the Object (retrived from getValue()) to a text representation.
somethings like:
public String getAsText()
{
if(getValue() == null)
{
return null;
}
UserRole role = (UserRole)getValue();
return role.getOid().toString();
}
setAsTest I have no clue about, I can see the setValue, but I dont know what to do with it, I dont see where I am getting its value from.
Sorry, and thanks for taking your Sunday to answer my questions.
G
Encrypt
May 20th, 2007, 12:25 PM
Would it break best practice, if I had my propertyEditor, have a reference to one of my service/business objects, and can the reference be wired in my application context, just like for other beans?
Thanks
Gavin
Jörg Heinicke
May 20th, 2007, 06:05 PM
Usual I would use a SimpleFormConrtollers referenceData method to populate an object for the UserRole drop down, is this still correct in this way of doing things?
Yes. The only thing that changes here is the code in the JSP. You don't need to specify itemValue on the form:options since the property editor converts the object into a string representation and so the value of <option>.
Is it the "id" vaules of the drop down it is converting, or the textual values the user sees in the dropdown field?
The id.
I see no way to get at the dropDowns "model object" to convert from the string value to the object (setAsText)
I use Hibernate as persistence framework. Into my HibernateEntityPropertyEditor I inject an instance of Spring's HibernateTemplate. That is used for loading the actual model objects by their id in setAsText(String).
Sorry, and thanks for taking your Sunday to answer my questions.
My pleasure :)
Jörg
Encrypt
May 20th, 2007, 06:43 PM
HibernateEntityPropertyEditor....that is just a PropertyEditorSupport class? hope so cos I cant find it in hibernate or spring.
So I guess I can just inject my property editor with my service object.
You guys have been great thanks for all your help.
Gavin
Jörg Heinicke
May 21st, 2007, 06:25 AM
HibernateEntityPropertyEditor....that is just a PropertyEditorSupport class?
Yes, it's my implementation.
Jörg
pmularien
May 21st, 2007, 01:35 PM
So I guess I can just inject my property editor with my service object.
I don't think that PropertyEditors are used in a thread-safe way in Spring, so I don't believe setting up the PropertyEditor in your Spring config file is correct. You should instead instantiate a new PropertyEditor instance in initBinder and pass references to other beans through the constructor, or through setters.
Jörg Heinicke
May 21st, 2007, 07:11 PM
I don't think that PropertyEditors are used in a thread-safe way in Spring
They are not for sure. That's also why there are PropertyEditorRegistrars and initBinder method in controllers.
so I don't believe setting up the PropertyEditor in your Spring config file is correct.
I didn't get that you wanted to do this, but the other way around. Injecting the service for retrieving the objects into the property editor.
You should instead instantiate a new PropertyEditor instance in initBinder and pass references to other beans through the constructor, or through setters.
I'd go with PropertyEditorRegistrar since you can set it up once for application context and inject it into controllers when needed. That also allows for example consistent formatting of date values or whatever you use them for.
Jörg
pmularien
May 22nd, 2007, 12:35 PM
They are not for sure. That's also why there are PropertyEditorRegistrars and initBinder method in controllers.
... [snip] ...
I'd go with PropertyEditorRegistrar since you can set it up once for application context and inject it into controllers when needed. That also allows for example consistent formatting of date values or whatever you use them for.
Thanks Jörg - I wasn't even aware this class existed - it seems extremely helpful.
It would be great to have this covered in the documentation somewhere, but I don't see it - are you aware if it is or not? If not, perhaps I'll file a JIRA to get it documented in 2.1.
(Sorry to the OP for hijacking the thread :) )
Jörg Heinicke
May 22nd, 2007, 07:05 PM
I wasn't even aware this class existed - it seems extremely helpful.
This class is also necessary when working with custom data types in the XML config. See CustomEditorConfigurer (http://www.springframework.org/docs/api/index.html?org/springframework/beans/factory/config/CustomEditorConfigurer.html) for more information. This class is mentioned in the reference in the section Registering additional custom PropertyEditors (http://static.springframework.org/spring/docs/2.0.x/reference/validation.html#beans-beans-conversion-customeditor-registration). But from what I see it's still the old and in the meantime discouraged way (http://www.springframework.org/docs/api/org/springframework/beans/factory/config/CustomEditorConfigurer.html#setPropertyEditorRegis trars(org.springframework.beans.PropertyEditorRegi strar[])) with adding property editors directly to BeanFactory. In contrary using PropertyEditorRegistrar has two big advantages:
This allows for sharing PropertyEditorRegistrars with DataBinders, etc. Furthermore, it avoids the need for synchronization on custom editors: A PropertyEditorRegistrar will always create fresh editor instances for each bean creation attempt.
It would be great to have this covered in the documentation somewhere, but I don't see it - are you aware if it is or not? If not, perhaps I'll file a JIRA to get it documented in 2.1.
It's indeed not mentioned once in the reference.
Jörg
pmularien
May 23rd, 2007, 09:32 AM
OK, I filed a JIRA - SPR-3512. Hopefully I'll grab an hour and submit some documentation patches where the use of this could be covered. Thanks again for pointing this class out to me! :)
Encrypt
Jun 7th, 2007, 08:16 AM
Hi, sorry for the delay in replying.
Hmmmmm, I think I may be being bad, as I have my spring config xml create a propertyEditorBean, then assign it to a controllor, then I use that in an initBind method.
It seems to work quite well, I did it this way, as the property editor, was going to have to go off to the Database to get the object assoicated with the ID given in a drop down, and as i already had a service/manager to get that info I figured i could use spring to wire the propertyEditor to the service/manager, from that point itjust seemed like a good idea.
oops :D
Thanks
G
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.