JPA using Combobox and SQLContainer

I have a meeting table, with a status column (Oracle number(4) → Java BigDecimal).
I bind the table using JPA/fieldgroup. I can update it as expected, so far so good.
I want to change the status column to be a combobox, so the user can select a status.

Status’ are stored in a codes table:-
Code Text

1 New
2 Open
3 Closed

I get the codes using a SQLcontainer and can populate the combobox as expected. However, when i select a value and try and COMMIT, it throws a conversion error:-

final ComboBox cbx_status = new ComboBox(“Status”);
cbx_status.setContainerDataSource(dbh.getCodes(“MEETINGSTATUS”));
cbx_status.setItemCaptionPropertyId(“LABEL”);
cbx_status.setFilteringMode(FilteringMode.CONTAINS);
cbx_status.setNullSelectionAllowed(false);
cbx_status.setImmediate(true);
fg.bind(cbx_status, “status”);
details.addComponent(cbx_status);

Error >> Could not convert value to BigDecimal at com.vaadin.ui.AbstractField.convertToModel

If i then add a converter:-


public class myConverter implements Converter<Object, T> {
private static final long serialVersionUID = 1L;
private final AbstractSelect select;

public SingleSelectConverterCorrected(AbstractSelect select) {
    this.select = select;
} 

@SuppressWarnings("unchecked")
private EntityContainer<T> getContainer() {
    return (EntityContainer<T>) select.getContainerDataSource();
}

public Class<T> getModelType() {
    return getContainer().getEntityClass();
}

public Class<Object> getPresentationType() {
    return Object.class;
}

@Override
public T convertToModel(Object value, Class<? extends T> targetType, Locale locale)
        throws com.vaadin.data.util.converter.Converter.ConversionException {
     if (value != select.getNullSelectionItemId()) {
            return getContainer().getEntityProvider().getEntity(getContainer(),
                    value);
        } else {
            return null;
        }
}

@Override
public Object convertToPresentation(T value, Class<? extends Object> targetType, Locale locale)
        throws com.vaadin.data.util.converter.Converter.ConversionException {
    if (value != null) {
        return getContainer().getEntityProvider().getIdentifier(value);
    }
    return select.getNullSelectionItemId();
}

public BigDecimal convertToModel(RowId value, Class<? extends BigDecimal> targetType, Locale locale)
            throws com.vaadin.data.util.converter.Converter.ConversionException {
    if (value == null)  return null;
       
    return new BigDecimal(value.toString());
}

public RowId convertToPresentation(BigDecimal value, Class<? extends RowId> targetType, Locale locale)
            throws com.vaadin.data.util.converter.Converter.ConversionException {
    if (value == null) return null;
    return new RowId(value);
}

}

and set it:-

cbx_status.setConverter(new myConverter(cbx_status));

The following is thrown when the form opens:-

java.lang.ClassCastException: com.vaadin.data.util.sqlcontainer.SQLContainer cannot be cast to com.vaadin.addon.jpacontainer.EntityContainer

ideas?

Using SQLContainer or JPAContainer makes this kind of pretty simple relation handling quite complex. Do you have some specific reason to keep SQLContainer in your stack? If you just select your JPA entities and pass them for ComboBox using BeanItemContainer, this should be much easier as no id mapping tricks are needed. Even easier if you use TypedSelect from
Viritin
.

cheers,
matti

Hi Matti, do you mean create a codes class, attach to JPA container and then use this as a source for the combobox, as follows?

@Entity
@Table(name=“CODES”)
@NamedQuery(name=“Code.findAll”, query=“SELECT c FROM Code c”)
public class Code implements Serializable {
private static final long serialVersionUID = 1L;

@EmbeddedId
private CodePK id;

@Column(name="\"LABEL\"")
private String label;

@Temporal(TemporalType.DATE)
@Column(name="\"ENDED\"")
private Date ended;

How do i ensure the class only returns the codes of interest, set the query in the entity class to include where domain = STATUS?, as in the codes table, there are many ‘domains’, such as:-

Domain Code Text

STATUS 1 New
STATUS 2 Open
STATUS 3 Closed
FOO 1 LOW
FOO 2 MEDIUM
FOO 3 HIGH

Do you have an example of this, passing the entity to a beanitemcontainer and to a comboxbox?

Thanks in advance,

John.

Hi,

I specifically suggest NOT to use JPAContainer, SQLContainer, or pretty much any other container that uses something else but the natural entity as the “item identifier”. That pretty much breaks all data binding goodies in Vaadin or at least makes it much more complicated. If you use BeanItemContainer (or similar, like a much better performing version called ListContainer from Viritin), the databinding works without hassles, independently of what you use as JPA identifier.

With “meta code” a suggested may to do a combobox based editor for a simple ManyToOne relation:

    @Entity
    public class Entity1 {
        //....

        @ManyToOne
        EntityListedInCombo reference;
        
    }

    @Entity
    public class EntityListedInCombo {
        //....
    }
    
    @Stateless
    public class Service {
        
        @PersistenceContext(name = "my-pu")
        EntityManager em;
        
        public List<EntityListedInCombo> findMyOptions() {
            return null; // do your raw JPA query, deltaspike data query whatever...
        }
    }

    
    public class MyForm extends VerticalLayout {
        @Inject
        Service service;
        
        ComboBox reference = new ComboBox();
        //....
        
        public void setEntity(Entity1 entity) {
            reference.setContainerDataSource(
                    new BeanItemContainer(EntityListedInCombo.class, 
                            service.findMyOptions()));
            BeanFieldGroup.bindFieldsUnbuffered(entity, this);
            // all done
            
        }
        
    }

I have an example invoicing applicaiton (work in progress, but already usable) that has lots of different kind of relations. You could
check that out
if you want good ideas for proper databinding.

cheers,
matti