LazyQueryContainer and Combobox in a Form

Hello,

I’m currently on a project using Vaadin 6.8.1 + Spring 3, which is structured as a Vaadin interface that calls Spring services (and Hibernate behind).

Thanks to LazyQueryContainer (LQC), I could load from services my data and display it in Vaadin tables and comboboxes. At this point, everything is fine and great. However, I have a form which contains a combobox, with data from a LQC, that doesn’t select properly the correct item when the form’s
setItemDataSource
method is called.

For instance, my application manages a list of persons and companies in a database. There are 2 classes :
Person
and
Company
. And the relationship is as simple as a person is member of a company. So, the class
Person
has a field
company
of type
Company
.
Now, I have a Vaadin
Form
that manages a
Person
. And in this form is a combobox that displays all companies in the database, and the selected company is the company which the person is registered to.

Since my application is divided in services,
I can’t use a
JPAContainer
or
HibernateContainer
to directly access my data
. I’ve then choosed the
LazyQueryContainer
with its
AbstractBeanQuery
. I created a datasource for the Person and Company classes, and they display properly in a table and comboboxes. The Vaadin Form displays also properly the Person’s String fields in the text inputs.

However, I wanted to manage the
Company
field with the combobox instead of the default textbox. So, I implemented a
FormFieldFactory
and binded the field to the combobox. There is indeed no more default company textbox, which means the binding is working, but the selected value in the combobox is blank (null).

I implemented the
equals
and
hashcode
methods in the
Company
class, but it didn’t change anything. I thought also that I should load all the data in the combobox (since the number of items is low) but I don’t know how to get manually an object from the LQC object. And without source code, there’s no way to debug.

Any help would be very welcome. Thanks.

Hi Edwin,

the LQC source code is
here

Thank you, Andreas

Now I can try to figure out what’s happening.

Edit:
Well. I did investigate a bit, and I see that there’s a type probleme.
In my company field in the form, I have a Company type. But in the combobox, the values are a list of id integers generated by the LazyQueryContainer (like [0,1,2,3]
). So, in the isSelected method of the AbstractSelect class, like this:


public boolean isSelected(Object itemId) {
        if (itemId == null) {
            return false;
        }
        if (isMultiSelect()) {
            return ((Set<?>) getValue()).contains(itemId);
        } else {
            final Object value = getValue();
            return itemId.equals(value == null ? getNullSelectionItemId()
                    : value);
        }
    }

the value object is a type of Company and the itemId is a generated index from LQC, aka an Integer. Of course this method would never return true.

I don’t get the logic behind that. The combobox calls the method getItemIds() of the LQC to populate its values. But those itemIds are not my company objects, but rather an internal generated index list that I can’t control. What am I doing wrong?

You’re nothing doing wrong. That’s the way ComboBox and LQC works. To check if a given object is selected, you should retrieve the itemID (index) from the ComboBox via getValue() and then ask the LQC via getItem(itemID) for the object you’re requesting.

This is indeed confusing, since the BeanItemContainer is working in the way you have expected it. The problem afaiu is: if the LQC could work with real objects as itemIDs, it must have a list of all itemIDs and this is not practical for a
Lazy Query
Container. Image a query with millions of items. You resp. your server could never handle this. But if the LQC does know how many items are in the resultset (LQC.size()), it can handle this with paging. If you ask the LQC to return the items from 1.000.100 to 1.000.120 it’s an easy and fast job.

Indeed, this is how practically all containers work - BeanItemContainer is the exception that uses the beans themselves as IDs, practically no other container does so.

You might be interested in PropertyConverter, FieldWrapper etc. in the add-on
CustomField
and maybe also
CustomField Utils
if you want to work with the beans as your properties.