I have a tri-state Boolean attribute (true, false, and null) in of one of my objects, and I don’t know how to properly bind it using the Spring Forms tags. I would like to use a series of 3 radio buttons (true, false, and null), but it seems that Spring does not like what I’m trying thus far.
Here’s the backing POJO:
public class Spirit {
/*** Private Fields **/
private Integer id;
private String name;
private Boolean isAlive;
/*** Constructor **/
public Spirit() {}
/*** Getters **/
public Integer getId() {return id;}
public String getName() {return name;}
public Boolean isAlive() {return isAlive;}
/*** Setters **/
public void setId(Integer id) {this.id = id;}
public void setName(String name) {this.name = name;}
public void isAlive(Boolean isAlive) {this.isAlive = isAlive;}
}
And here’s the form I’m using (that doesn’t work):
<sf:form method="POST" modelAttribute="spirit">
<table>
<tr>
<th><label for="spirit_name">Name</label></th>
<td><sf:input path="name" id="spirit_name" /></td>
</tr>
<tr>
<th><label for="spirit_isAlive">Livelyness</label></th>
<td>N/A: <sf:radiobutton path="isalive" value="null" /> Alive: <sf:radiobutton path="isalive" value="true" /> Dead: <sf:radiobutton path="isalive" value="false" /></td>
</tr>
</table>
<sf:hidden path="id"/>
<input type="submit" value="save" />
</sf:form>
The error I’m getting:
SEVERE: Servlet.service() for servlet jsp threw exception
org.springframework.beans.NotReadablePropertyException: Invalid property 'isAlive' of bean class [com.example.Spirit]: Bean property 'isAlive' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:707)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:699)
at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:98)
at org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:224)
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:120)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:174)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:194)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:160)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:147)
at org.springframework.web.servlet.tags.form.AbstractCheckedElementTag.autogenerateId(AbstractCheckedElementTag.java:78)
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:138)
at org.springframework.web.servlet.tags.form.AbstractSingleCheckedElementTag.writeTagContent(AbstractSingleCheckedElementTag.java:82)
at org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:102)
at org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79)
at org.apache.jsp.WEB_002dINF.views.spirits.edit_jsp._jspx_meth_sf_005fradiobutton_005f0(edit_jsp.java:523)
at org.apache.jsp.WEB_002dINF.views.spirits.edit_jsp._jspService(edit_jsp.java:201)
There is another question that is very similar, but the solution in that case was to simply change the type to boolean, rather than Boolean. Unfortunately, changing the get/set methods for the tri-state is only available as a last-resort option. What is it that I am doing incorrectly?
You shouldn’t specify
value=nullin the JSP Tag. This will result in the browser sending a value ofisalive=nullin the HTTP POST.Since there is no way to bind
"null"(the String) to aBoolean, this rightfully throws an error.If the radio button is not selected by the user, then the browser will not send anything for the form parameter (or it will send
isalive=, I forget which – but it does not matter). In this case Spring will not attempt to bind the field, which will leave your POJO with aisAlivefield withnullvalue.So in summary – if you set
value=nullin the HTML/JSP tag, you are telling the browser to POST a string literalnull. Just leave it out.