VAADIN: Why I can't set a converter to a ComboBox?

4k views Asked by At

I've made a converter:

public class BooleanToDateConverter implements Converter<Boolean, Date> {
    private static final long serialVersionUID = 1L;

    @Override
    public Date convertToModel(Boolean value, Class<? extends Date> targetType, Locale locale)
            throws com.vaadin.data.util.converter.Converter.ConversionException {
        if (value == true) {
            return new Date();
        } else {
            return null;
        }
    }

    @Override
    public Boolean convertToPresentation(Date value, Class<? extends Boolean> targetType, Locale locale)
            throws com.vaadin.data.util.converter.Converter.ConversionException {
        if (value == null) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public Class<Date> getModelType() {
        return Date.class;
    }

    @Override
    public Class<Boolean> getPresentationType() {
        return Boolean.class;
    }
}

Then I have a Vaadin ComboBox myComboBox I try to set my converter to it:

myComboBox.setConverter(new BooleanToDateConverter());

Then I get an error in Eclipse saying:

The method setConverter(Class<?>) in the type AbstractField<Object> is not applicable for the arguments (BooleanToDateConverter)

However, I've seen other converters being used similarly and they don't get errors. Why?

1

There are 1 answers

2
Roland Krüger On BEST ANSWER

Your code cannot be compiled because there is no setConverter() method available on class ComboBox that fits your custom converter. Let me explain how converters are used on select components and what is the idea behind the specific method signatures you find for setting converters on a ComboBox.

ComboBox provides two overloaded versions of setConverter():

  • setConverter(Class<?> datamodelType): set a pre-registered converter for the given data model type
  • setConverter(Converter<Object, ?> converter): set a concrete converter instance

Both of these methods are actually inherited from class AbstractField<T> where T is the data type managed by the field (e.g. Strings for text fields, Date for a DateField, Object for ComboBoxes). A converter is typically used to convert between a presentation type (such as the textual representation of a value on the UI) and its internal model type (such as a date, a monetary value or a custom JavaBean). So, for instance, if you have a Label you can use a StringToDateConverter to correctly display a Date object, which has been set as the value of the Label, in a properly localized way.

How is that with select components such as ComboBox? Here the type T is Object. The data type of a select component actually represents the item ID of the selected item from the underlying container data source. So, if you use a BeanItemContainer as the data source of a ComboBox, the container's item IDs (and hence the selected value of the ComboBox) are the contained JavaBean objects themselves. The concrete type of the item IDs depends on the container implementation used. Therefore, select components are Field components with value type Object. In other words, select components use Object as presentation type.

That is why you can only set a converter instance on a select component whose generic PRESENTATION type is Object. The model type can be chosen freely. And this also explain why you can't set a converter with presentation type Boolean and model type Date on a ComboBox -- ComboBox doesn't use Boolean as presentation type.

I wrote a blog post about Vaadin FieldGroups which also provides a good example for a use case when to use a Converter<Object, ?> on a ComboBox. You can find this article at http://blog.oio.de/2014/04/25/select-nested-javabeans-vaadin-fieldgroup/.

I don't know what you want to achieve with your code, because a converter between a presentation type of Boolean and a model type of Date doesn't make much sense. I can only guess that you want to implementat some sort of decision logic, maybe to decide whether or not a date has been set? In that case you need to take a different approach.

For reference, have a look at the Book of Vaadin on Converters.