-
Notifications
You must be signed in to change notification settings - Fork 38.9k
Description
Ken Egervari opened SPR-8665 and commented
I have an application that I've recently upgraded to 3.0.6 from 3.0.5. The application used a property editor to convert a String to a List of objects, back and forth.
I am positive this code used to work. In fact, the unit tests for the property editor continue to work as expected.
However, whenever a controller uses the property editor, it wraps the List of objects with ANOTHER list, which is absolutely not what we want to happen. Did they change how property editors work? How do I fix it?
My init binder method looks like this:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(List.class, new UsernamesToRecipientsEditor(userAccountDao));
}
Because java is weakly typed when it comes to List, I want you to know that this is really a List<Recipient> and not just a List of any random object. Here is the property editor code:
public class UsernamesToRecipientsEditor extends PropertyEditorSupport {
private UserAccountDao dao;
public UsernamesToRecipientsEditor(UserAccountDao dao) {
this.dao = dao;
}
@Override
public String getAsText() {
Object obj = getValue();
if(obj == null) {
return "";
}
if(obj instanceof List) {
List<Recipient> recipients = (List<Recipient>) obj;
StringBuilder builder = new StringBuilder();
for(Iterator<Recipient> iterator = recipients.iterator(); iterator.hasNext();) {
Recipient recipient = iterator.next();
builder.append(recipient.getUserAccount().getUsername());
if(iterator.hasNext()) {
builder.append(", ");
}
}
return builder.toString();
}
throw new IllegalArgumentException("Value must be a UserAccount");
}
@Override
public void setAsText(String text) {
List<Recipient> recipients = new ArrayList<Recipient>();
if(!StringUtils.hasText(text)) {
setValue(recipients);
return;
}
for(String username : StringUtils.commaDelimitedListToSet(text)) {
UserAccount userAccount = dao.findByUsername(username.trim());
if(userAccount != null) {
Recipient recipient = new Recipient(userAccount);
if(!containsRecipient(recipients, recipient)) {
recipients.add(recipient);
}
}
}
setValue(recipients);
}
private boolean containsRecipient(List<Recipient> recipients, Recipient recipient) {
for(Recipient r : recipients) {
if(r.getUserAccount().getId() == recipient.getUserAccount().getId()) return true;
}
return false;
}
}
Basically what this code does is it converts a string containing a bunch of username's separated by commas and converts them to the actual user objects, back and forth between them. It works in unit tests, and this worked in the past.
Unfortunately, after Spring MVC calls into this property editor, it wraps the result from setValue(recipients) inside of ANOTHER List... so the end result is a "List of a List of Recipients". This isn't what I want.
Since this code above USED TO work, I have to conclude that some bug or behavioral change has happened. Please help.
Affects: 3.0.6
Reference URL: http://stackoverflow.com/questions/7293928/did-spring-framework-3-0-6-break-property-editor-support-for-lists
Issue Links:
- Collection Binding broken - TypeConverterDelegate does bind Collection Elements to Collection type instead of the collection elements Type [SPR-8674] #13316 Collection Binding broken - TypeConverterDelegate does bind Collection Elements to Collection type instead of the collection elements Type ("duplicates")