Spring checkbox JSP Tag breaks when using converter for type Boolean

I installed a CRUD web application with Spring Roo and Spring MVC. My problem is this: since I use a converter to localize the display of booleans, the Spring JSP Tag is checked , which means that the flags do not accept the actual value from the beans backup. They are always false and unverified.

I did some research and probably found an error in the writeTagDetails org.springframework.web.servlet.tags.form.CheckboxTag method. Here is the interesting part of this method:

// the concrete type may not be a Boolean - can be String if (boundValue instanceof String) { boundValue = Boolean.valueOf((String) boundValue); } Boolean booleanValue = (boundValue != null ? (Boolean) boundValue : Boolean.FALSE); renderFromBoolean(booleanValue, tagWriter); 

Since I use the converter to display yes / no instead of true / false, boundValue is a string, and calling Boolean.valueOf always leads to false because the valueOf method does not know the Spring converter used and interprets yes / no as false.

How can I solve this problem using Spring? Someone tell me? My brain has reached an impasse.

Just for completeness: the converter for the boolean type works as expected (see the code below).

 public class BooleanConverter implements Converter<Boolean,String>, Formatter<Boolean> { @Autowired private MessageSource messageSource; @Override public String print(Boolean object, Locale locale) { return (object) ? messageSource.getMessage("label_true", null, LocaleContextHolder.getLocale()) : messageSource.getMessage("label_false", null, LocaleContextHolder.getLocale()); } @Override public String convert(Boolean source) { return this.print(source, null); } } 
+4
source share
3 answers

It seems possible to overcome. That is, you want the readable Formatter for people to display yes / no to the user for logical values ​​in the model. But you still want the HTML checkbox elements to work, and it seems that these HTML checkbox elements / widgets / JSP tags expect to use a true / false string (or Java boolean type), it does not use a converter to get an arbitrary yes / no string returns to the boolean type.

This problem for me manifests itself in the fact that the initial state of the checkbox is never checked when the model is set to Boolean.TRUE. This means that any read-change-update of the record (without editing this field ends the transition from "true" to "false" if the user has not changed it). This is due to the fact that the initial state in the user interface is incompatible with the model (it is always displayed without checking, i.e., False state), even when the model is a true state. The displayed value is a checked flag on the HTML record editing screen, even if the model has the value Boolean.TRUE. This is because yes is not interpreted as true by HTML elements and the default value is false (since this default value is logical).

So, define your Formatter / Converter (as you already do). But in your @Controller add:

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Boolean.class, "friesWithThat", new CustomBooleanEditor(false)); } 

It looks like the string display value continues to be yes / no, but the value used and passed to the element of the HTML element still remains true / false.

Now, when editing / updating a record (in CRUD), the initial state of the flag corresponds to the model and saving data (without editing any fields) does not translate the state of the flag (this is my understanding of the problem that you have).

So, from this, I think we can understand that Converters / Formatters are intended for general display of data and that PropertyEditors are intended for displaying model data, therefore data is required for a user interface widget.

+2
source

Perhaps you should write your own type called Choice , which has Choice.YES and Choice.NO as ordinal listings that match 1 or 0 based on the values ​​stored in the database.

You can then have your own display tags and input tags defined in the application for this type that can solve this problem.

+1
source

Adding to the previous answer, from spring 3.2 you can register a property editor for all controllers and all boolean fields, such as:

 package your.package.path; import org.springframework.beans.propertyeditors.CustomBooleanEditor; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.context.request.WebRequest; @ControllerAdvice public class GlobalBindingInitializer { @InitBinder public void registerCustomEditors(WebDataBinder binder, WebRequest request) { binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(false)); } } 

if you came from spring basic Roo configuration, remember also to add this line to your webmvc-config.xml

  <context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/> 

like this:

 <context:component-scan base-package="your.package.path" use-default-filters="false"> <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/> <context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/> </context:component-scan> 
+1
source

All Articles