piątek, 10 września 2010

Spring form:checkboxes a JSF h:selectManyCheckbox

Krótka notka dla wszystkich, którzy przesiedli się z JSF'a na Spring'a (wersja 2.5.6) i przyszło im użyć tagu form:checkboxes. Idea obu tagów jest taka sama, czyli jak "przyjemnie" obsłużyć na formularzu wiele checkboxów.

Załóżmy, że mamy encje Employee i Language, które są w relacji wiele-do-wielu.
Aby wyświetlić na formularzu wszystkie checkboxy (języki) z zaznaczonymi tymi, które dany pracownik zna. W JSF używamy:


  


To samo w Spring'u wygląda następująco


Pominę kwestie skąd i jak wstrzykiwane są allLanguages i languages. 

Wszystko teoretycznie powinno działać, ale niestety nie jest tak różowo. Pojawia się następujący błąd:
Failed to convert property value of type [java.lang.String] to required type [java.util.Set] for property languages; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [emp.entity.Language] for property languages[0]: no matching editors or conversion strategy found
Przyczyną błędu jest brak odpowiedniego PropertyEditor'a dla Language. Przykładowy editor dla klasy Language:
public class LanguageEditor extends PropertyEditorSupport {    
    private LanguageManager languageManager;   
    public LanguageEditor(LanguageManager languageManager) {
        super();
        this.languageManager = languageManager;
    }
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        setValue(languageManager.getLanguageById(Long.parseLong(text)));
    }    
    @Override
    public String getAsText() {        
        Language language = (Language) getValue();
        return language == null ? null :  Long.toString(language.getId());
    }    
}

W moim przypadku metoda setAsText używa managera, który pobiera encje Language o danym id z bazy. Trzeba jeszcze tylko dodać tego editora w metodzie initBuilder w kontrolerze który odpowiada za obsługę formularzu:

public class EmployeeEditController extends SimpleFormController{
    ...
    @Override
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    super.initBinder(request, binder);
    binder.registerCustomEditor(Language.class, new LanguageEditor(languageManager));
    
    .... 

} 

I coś takiego rozwiązuje zgłaszany błąd.

Brak komentarzy:

Publikowanie komentarza